JavaFX Von welcher Klasse und zu welchem Zeitpunkt werden Event-Objekte erstellt?

Diskutiere Von welcher Klasse und zu welchem Zeitpunkt werden Event-Objekte erstellt? im AWT, Swing, JavaFX & SWT Bereich.
B

BigMemo007

Hallo Community,

ich habe mal da eine blöde Frage. Ich habe folgenden einfachen Code:

Java:
public class MeinMausBewegtEvent extends Application {
    @Override
    public void start(Stage primaryStage) {
        Circle kreis = new Circle(30);
        Group gruppe = new Group();
        Scene sc = new Scene(gruppe);
        
        sc.setOnMouseMoved(new EventHandler<MouseEvent>() {
            @Override
            public void handle(MouseEvent event) {
                kreis.setCenterX(event.getX());
                kreis.setCenterY(event.getY());
            }
        });
        
        gruppe.getChildren().add(kreis);
        primaryStage.setScene(sc);
        primaryStage.show();
    }
    
    public static void main(String[] args) {
        launch(args);
    }
}

Hier wird ein Kreis mit einem Radius von 30 erstellt. Dieser wird in eine Group und die Group in die Scene eingepakkt. Die Scene regiert mit setOnMouseMoved auf Mausbewegungen, in dem es auf MouseEvent-Daten zurückgreift. Der Kreis folgt der Mausbewegung innerhalb der Scene. Soweit so gut. Das Programm funktioniert. Ich habe da nur eine kleine Verständnisfrage. Mit dem Aufruf der Scene-Funktion setOnMouseMoved wird eine anonyme Klasse erstellt, die das Interface EventHandler implementiert und mit MouseEvent parametisiert ist. Welche Klasse erstellt das MouseEvent-Objekt? Ich sehe nirgendswo den Aufruf von "new MouseEvent()".
Auch wenn ich eine eigene Klasse mache wie folgt:

Java:
public class MyEventHandler implements EventHandler<RotateEvent>{

    Circle c;
    
    public MyEventHandler(Circle c) {
        this.c = c;
    }
    
    @Override
    public void handle(MouseEvent event) {
        c.setCenterX(event.getX());
        c.setCenterY(event.getY());

    }
}
Das funktioniert auch. Aber auch hier wird nirgendswo "new MouseEvent" gemacht. Ich habe etwas ganz banales nicht verstanden oder vergessen. Bitte helft mir gerade die Funktionsweise richtig zu verstehen.
 
H

httpdigest

Die JavaFX-Laufzeitumgebung erstellt solche Eventobjekte. Es wird das Betriebssystem nach solchen Ereignissen für das native Fenster gefragt, dann wird geguckt, welches JavaFX-Element sich an dieser Position befindet und dann wird ein EventObjekt gebaut und die EventHandler-Methode "handle" aufgerufen.
Die JavaFX-Laufzeit bzw. die Scene weiss ja von deinem EventHandler durch deinen Aufruf von setOnMouseMoved() auf der Scene. Und dementsprechend holt sich die JavaFX-Laufzeitumgebung dann diesen EventHandler von der Scene und ruft seine "handle"-Methode mit einem MouseEvent-Objekt auf, was dann dazu führt, dass deine Methode in deinem EventHandler ausgeführt wird.
 
B

BigMemo007

Woww cool was die JavaFX-Laufzeitumgebung für einen alles macht :) Danke für die Aufklärung. Jetzt hab ich ein besseres Gesamtbild von der Sache.
 
mihe7

mihe7

ich habe mal da eine blöde Frage.
Tatsächlich ist das die Frage, deren Antwort den essentiellen Kern der Java-UI-Programmierung erklärt :)

Die Ereignisse werden nämlich nicht zu beliebigen Zeitpunkten (z. B. parallel) verteilt, sondern der Reihe nach. Dazu werden sie in eine Warteschlange eingereiht und der Reihe nach abgearbeitet. Letzteres passiert in einem eigenen Thread, dem sog. UI-Thread (unter AWT/Swing passenderweise auch Event Dispatch Thread genannt).

Warum macht man das und was hat das für Konsequenzen?

Das UI läuft auf diese Weise Java-seitig praktisch in einem einzigen Thread. Das hat den Vorteil, dass man sich nicht um eine Koordination von Threads kümmern muss.

Wenn Du Deine handle-Methode ansiehst, setzt Du dort erst die x-Koordinate, dann die y-Koordinate. Was passiert z. B., wenn sich nach dem Setzen der x-Koordinate das Betriebssystem überlegt, dass das Fenster neu gezeichnet werden muss?

Würde keine Warteschlange verwendet und auch keine Thread-Synchronisation stattfinden, würde das Fenster sofort neu gezeichnet, so dass der Kreis kurzzeitig falsch dargestellt würde (die x-Koordinate ist bereits aktualisiert, die y-Koordinate aber noch nicht). Je nach Programmlogik kann so etwas zu ganz üblen Effekten führen. Kurz: es würde das Chaos ausbrechen.

Durch die Warteschlange wird alles sehr einfach: das Neuzeichnen-Erignis wird in die Warteschlange eingereiht, so dass Deine handle-Methode erst vollständig abgearbeitet wird. Danach wird das nächste Ereignis aus der Warteschlange verarbeitet usw. Irgendwann ist dann auch das zuvor eingereihte Neuzeichnen-Ereignis an der Reihe.

Das hat zur Folge, dass Änderungen am UI erst sichtbar werden können, wenn die handle-Methode vollständig abgearbeitet wurde. Daraus folgt wiederum, dass z. B. Animationen nicht einfach mit einer Schleife in der handle-Methode möglich sind oder dass die Reaktionszeit des UI davon abhängig ist, wie lange die Verarbeitung des Ereignisses im UI-Thread dauert. Wartest Du in Deiner handle-Methode z. B. 10 Sekunden, wird das UI eben 10 Sekunden lang nicht reagieren, weil die Ereignisse, die in der Warteschlange stehen, nicht abgearbeitet werden können.

Die Lösung solcher Probleme besteht darin, derlei Aufgaben in einem anderen Thread zu erledigen und dafür zu sorgen, dass Änderungen am UI wiederum nur im UI-Thread ausgeführt, also in die Warteschlange eingereiht werden. Letzteres erreicht man "low-level" mittels Platform.runLater. Auch stellen die verschiedenen Frameworks z. T. ausgefeilte Lösungen zur Verfügung, die sich darum kümmern. Für JavaFX gibt es wohl Task und Service (s. https://docs.oracle.com/javase/8/javafx/interoperability-tutorial/concurrency.htm), für Swing dagegen den SwingWorker. Bzgl. Animationen kann man in JavaFX auf Timeline zurückgreifen, unter Swing muss man den (Swing-)Timer bemühen.
 
Thema: 

Von welcher Klasse und zu welchem Zeitpunkt werden Event-Objekte erstellt?

Passende Stellenanzeigen aus deiner Region:
Anzeige

Neue Themen

Anzeige

Anzeige
Oben