JavaFX Absoluter Fokus während drag Event

mirisbowring

Bekanntes Mitglied
Hi,
aktuell habe ich eine undecorated Etage, in der ein BorderPane liegt.
Das Fenster lässt sich nur unten rechts vergrößern/Verkleinern...
Ein work around für die min Size habe ich auch schon.

Jetzt habe ich allerdings ein Problem:
Wenn ich das Fenster sehr schnell kleiner ziehe, und meine Maus dann auf dem child (Panel im Border Center) landet, scheint dieses child den Focus zu bekommen, womit das Border Pane stoppt sich zu verkleinern.
Wenn ich die Maus jetzt nicht loslasse, sondern wieder in das bottom Border gehe, dann verkleinert sich das Fenster wieder wie es soll.

Jetzt meine Frage:
Gibt es eine Möglichkeit, während des drag Events dem BorderPane absoluten Fokus zu gewähren?

Ich habe schon probiert in der drag Methode root.requestFokus() aufzurufen, aber das funktioniert auch nicht (ich glaube, der Focus wird ganz am Anfang vom drag einmal requested und danach nicht mehr)

Danke schonmal im voraus

mirisbowring
 
Du kannst in der Zeit ja die Events konsumieren und damit sollten sie nicht weiter-propagiert werden (event#consume()) - das machst du am Ende deiner Arbeit im Listener. Sonst mal ein kleines Beispiel posten - btw: Ich kämpfe auch gerade mit so etwas, aber ich benötige einen "lightweight" Dialog, der so etwas können muss - meine bisherige Variante ist leider zu "schwergewichtig" (render-Zeiten sind unterirdisch) und hat noch einen API-Call drin, der mit Java 9 wohl nicht mehr gehen wird (private API).
 
Erst einmal danke, für deine Antwort. 🙂
leider hat das Konsumieren der events nichts verändert. (tritt halt wirklich nur bei sehr schnellen Vergrößerungen auf)
Trotzdem möchte ich dir meine Codeschnipsel nicht vorenthalten:
Java:
public static void resizeHelper(Node root, Stage stage){    
        Scene scene = stage.getScene();
        root.setOnMousePressed((MouseEvent event) -> {
            if (event.getX() > stage.getWidth() - 10
                    && event.getX() < stage.getWidth() + 10
                    && event.getY() > stage.getHeight() - 10
                    && event.getY() < stage.getHeight() + 10) {
                resizebottom = true;
                dx = stage.getWidth() - event.getX();
                dy = stage.getHeight() - event.getY();
            } else {
                resizebottom = false;
            }
        });

        root.setOnMouseMoved((MouseEvent event) -> {
            if(event.getSceneX() > scene.getWidth() - 10 && event.getSceneY() > scene.getHeight() - 10)
            {
                scene.setCursor(Cursor.SE_RESIZE);
            }else{
                scene.setCursor(Cursor.DEFAULT);
            }
        });

        root.setOnMouseDragged((MouseEvent event) -> {
            if (resizebottom == true) {
                double x = event.getX() + dx;
                double y = event.getY() + dy;
                if(x>MIN_WIDTH)
                    stage.setWidth(event.getX() + dx);              
                if(y>MIN_HEIGHT)
                    stage.setHeight(event.getY() + dy);
            }
        });
    }
das ist meine Resize Methode.
Ich übergebe das Element (in meinem Fall ein BorderPane) als root und die aktuelle Stage eben als Stage)...

Der code sollte relativ selbsterklärend sein... Wenn nicht, dann frag mich einfach nochmal^^
Auf jeden fall funktioniert das resizen bei mir schöner, als windows mit seinen eigenen fenstern (explorer, etc.)

Gruß
mirisbowring

PS:
Was ich noch anmerken muss ist, dass ich mein Fenster nur unten rechts in der Ecke vergrößern/verkleinern kann

Wenn du auch die anderen Seiten kannten haben willst, musst du die oberen beiden Action listsner anpassen 🙂
 
Zuletzt bearbeitet:
Kannst du mir einen Gefallen tun und ein ganzes, selbständig laufendes, Beispiel geben? Ich möchte jetzt nicht drumherum irgendwas basteln...
 
Also da ist nicht viel drum und dran:
Java:
package resizeexample;

import java.io.IOException;
import javafx.application.Application;
import javafx.geometry.Pos;
import javafx.scene.Cursor;
import javafx.scene.Node;
import javafx.scene.Scene;
import javafx.scene.control.Label;
import javafx.scene.input.MouseEvent;
import javafx.scene.layout.BorderPane;
import javafx.stage.Stage;
import javafx.stage.StageStyle;
import static resizeexample.Main.StyleHelper.resizeHelper;

public class Main extends Application {
   
    private double xOffset = 0;
    private double yOffset = 0;
   
    @Override
    public void start(Stage stage) throws IOException {
        Label test = new Label();      
        test.setMinSize(200, 200);
        test.setText("Drag Me To Move");
        test.setAlignment(Pos.CENTER);
        test.setStyle("-fx-background-color: red;");
       
        BorderPane pane = new BorderPane();
        pane.setStyle("-fx-background-color: beige");
        pane.setMinSize(400, 400);
        pane.setPrefSize(500, 500);       
        pane.setCenter(test);
       
        //Listeners to move the undecorated Stage
        test.setOnMousePressed((MouseEvent e) -> {
            xOffset = e.getSceneX();
            yOffset = e.getSceneY();
        });
        test.setOnMouseDragged((MouseEvent e) -> {
            stage.setX(e.getScreenX()-xOffset);
           
            stage.setY(e.getScreenY()-yOffset);
        });
       
        Scene scene = new Scene(pane);
       
        stage.initStyle(StageStyle.UNDECORATED);
        stage.setScene(scene);
        stage.show();
       
        resizeHelper(pane, stage);
    }

    public static void main(String[] args) {
        launch(args);
    }
   
   
    public static class StyleHelper {
   
        public static final double MIN_WIDTH = 525.0;
        public static final double MIN_HEIGHT = 450.0;
        private static double dx;
        private static double dy;
        //resizeBottom is only needed if the Stage has a min Size
        private static Boolean resizebottom = false;

        /**
         *
         * @param root rootPane which has to be resized
         * @param stage current stage status
         */
        public static void resizeHelper(Node root, Stage stage){     
            Scene scene = stage.getScene();
            //Curser at "correct" position?
            //Change '10's to increse / decrease Action scope of Cursor
            root.setOnMousePressed((MouseEvent event) -> {
                if (event.getX() > stage.getWidth() - 10
                        && event.getX() < stage.getWidth() + 10
                        && event.getY() > stage.getHeight() - 10
                        && event.getY() < stage.getHeight() + 10) {
                    resizebottom = true;
                    dx = stage.getWidth() - event.getX();
                    dy = stage.getHeight() - event.getY();
                } else {
                    resizebottom = false;
                }
            });
            //Change Curser Style and Check which Border is hit
            root.setOnMouseMoved((MouseEvent event) -> {
                if(event.getSceneX() > scene.getWidth() - 10 && event.getSceneY() > scene.getHeight() - 10)
                {
                    scene.setCursor(Cursor.SE_RESIZE);
                }else{
                    scene.setCursor(Cursor.DEFAULT);
                }
            });
            //resize till min Size recognized
            root.setOnMouseDragged((MouseEvent event) -> {
                if (resizebottom == true) {
                    double x = event.getX() + dx;
                    double y = event.getY() + dy;
                    if(x>MIN_WIDTH)
                        stage.setWidth(event.getX() + dx);               
                    if(y>MIN_HEIGHT)
                        stage.setHeight(event.getY() + dy);
                }
            });
        }
    }
   
}
 
Hm... Häh? Was ich witzig finde: Bei mir unter Linux kann ich die Fenster an jeder Ecke & Kante "resizen" auch wenn ich deinen StyleHelper auskommentiere...
Dein Problem kann ich jedoch nicht nachstellen. Hast du vielleicht eine langsame Graphikkarte?

BTW: Das einzige Problem das ich habe ist dass JavaFX-Anwendung bei mir meistens beim Vergrössern/-kleinern von Fenstern immer "Artefakte" aufweist - hässliche schwarze Bereiche, "Sprünge" beim Rendering, etc.
 
Ok das ist interessant...
Vielleicht ist das ein Betriebssystem Spezifischer Fall (ich verwende Win10)
Heute Abend muss ich das mal auf Linux testen.

Also an der GPU kann es definitiv nicht liegen (R9 290).
Ich habe ja auch kein Renderproblem, sondern das Problem, dass das Root Pane irgendwie den Fokus verliert. (Auf Windows kann ich ja nur unten rechts die Größe verändern, und wenn ich dann zu schnell nach oben oder links ziehe - also verkleinere - bleibt das Root Pane auf einmal auf seiner Größe und verändert sich nicht mehr. Wenn ich dann mit der Maus wieder zur Ecke gehe - ohne die linke Maustaste los zulassen - verkleinert er sich wieder)

Diese "Artefakte" die du meinst treten bei mir auch in sehr geringem Maße auf. Erst war ich nicht sehr erfreut, aber als ich das ganze mit dem FileExplorer, Microsoft Edge, etc. von Windows 10 probiert habe, ist mir aufgefallen, dass es dort wesentlich stärker auftritt. Deshalb mache ich mir darum keine Gedanken 🙂
 
Sag mir mal, wie es bei dir unter Linux ist. Ich muss erst mal schauen, dass ich einen Win10 Rechner dafür finde. :-D
 
Also ich habe das mal auf meiner Kali Distro probiert, und ich konnte nur unten rechts vergößern/verkleinern... (Wenn ich den ResizeHelper abgeschaltet habe, gings gar nicht mehr)

Allerdings muss ich sagen, dass ich bei Kali fast gar keine "Fragmente" habe
 

Neue Themen


Zurück
Oben