Wo hält das Programm an?

matze86

Bekanntes Mitglied
Ich habe mal ein JavaFX Programm erstellt, welches auf klicken der Maus reagiert, mir geht es aber ums Prinzip, denn meine Frage ist an welcher Stelle das Programm anhält und wartet bis wieder etwas passiert?

Wird beim Klicken einer Maustaste alle beide Eventhandler (canvas.setOnMousePressed(new MausLinks()); und canvas.setOnMouseReleased(new MausRechts())😉
durchgegangen um zu schauen ob das das richtige ist?

Java:
import javafx.application.Application;
import javafx.event.EventHandler;
import javafx.scene.Scene;
import javafx.scene.canvas.Canvas;
import javafx.scene.canvas.GraphicsContext;
import javafx.scene.input.MouseButton;
import javafx.scene.input.MouseEvent;
import javafx.scene.layout.FlowPane;
import javafx.stage.Stage;

public class StartMaus extends Application{
    
    @Override
    public void start(Stage stage) throws Exception {
        FlowPane root = new FlowPane();
        Canvas canvas = new Canvas(400, 400);
        root.getChildren().add(canvas);
        
        canvas.setOnMousePressed(new MausLinks());
        canvas.setOnMouseReleased(new MausRechts());
        Scene meineScene = new Scene(root, 400, 400);
        
        stage.setScene(meineScene);
        stage.setTitle("test");;
        stage.show();
    }
    
    public static void main(String[] args) {
        launch(args);
    }
}

class MausLinks implements EventHandler<MouseEvent> {
    @Override
    public void handle(MouseEvent e) {
        if (e.getButton() == MouseButton.PRIMARY)
            System.out.println("Linke Maustaste");
            }
}
    
class MausRechts implements EventHandler<MouseEvent> {
    @Override
    public void handle(MouseEvent ee) {
        if (ee.getButton() == MouseButton.SECONDARY) {
            System.out.println(ee.getX());
        }
        }
}
 
Eine UI Anwendung hat (außerhalb von Deinem Code) eine Event Loop. Der UI Thread führt nur diese Loop aus. Dabei ist der Event blockiert, bis ein Event kommt und dann wird dieses Event abgearbeitet.

Der eigentliche Haupt-Thread beendet sich. Das kannst Du erkennen, wenn Du z.B. am Ende der main Methode noch etwas ausgibst.
 
Dein Programm hält nicht an. Du hast mit setOnMousePressed einen Listener eine Callback Methode an das Betriebssystem übergebenen.

Wenn der Code deiner Start Methode durch ist gibst du die Kontrolle an das BS zurück.
Stellt das BS einen klick innerhalb deiner Canvas fest ruft es die Callback Methode auf. Und du bist wider in deinem Programm.

Konrad war schneller .
 
hier ist eine ausführliche Erklärung wie das abläuft
 
warum hast du eig die EventHandler als klasse implementiert? du verlierst ja alle Vorteile wenn du es so machst
 
Wenn der Code deiner Start Methode durch ist gibst du die Kontrolle an das BS zurück.
Stellt das BS einen klick innerhalb deiner Canvas fest ruft es die Callback Methode auf. Und du bist wider in deinem Programm.
Genauer gesagt ruft hier nicht das Betriebssystem diese Callback-Methode auf, sondern eine Schleife und ein großes Switch-case-Statement in der JavaFX Runtime in einem Thread, der von der JavaFX Runtime gestartet wird.
JavaFX ruft nur Betriebsystem-spezifische Platform-APIs auf, um zu erfragen, ob es für diesen Prozess neue Ereignisse in der Event Queue des Prozesses gibt. Wenn ja, interpretiert die JavaFX Runtime das Ereignis, findet das entsprechende JavaFX-Control bzw. den Canvas heraus und ruft den EventHandler (falls einer registriert war) darauf auf für das entsprechende Ereignis.
Im Großen und Ganzen hast du aber Recht: Die Ausführung des Callbacks wird effektiv durch ein Ereignis ausgelöst, welches vom Betriebssystem generiert wird.
 
Wie meinst du das? Wie sollte man es anders machen?
Das Stichwort sind hier Lambda Ausdrücke und Methoden Referenzen.

Ab Java 8 ist die Idee der Funktionalen Interfaces eingeführt worden. Das sind Interfaces, bei denen nur eine Methode Implemetiert werden muss. Es dreht sich somit alles um nur eine Methode.

Und da ist dann die erste Idee: Warum geben wir dann nicht einfach nur eine Methode?
Java:
public void handle(MouseEvent e) {
    if (e.getButton() == MouseButton.PRIMARY)
        System.out.println("Linke Maustaste");
    }
}
wäre eine der Methoden, die Du gerne hättest. Die Methode packen wir also einfach in die eigentliche Klasse und benennen sie sinnvoll. Also von mir aus printLinkeMaustaste. Und dann kannst Du diese Methode angeben:
canvas.setOnMousePressed(this::printLinkeMaustaste);

Das wäre dann die Syntax für eine Methodenreferenz.

Die zweite Idee ist dann in Analogie zu anonymen Klassen zu sehen: Anonyme Methoden. Wenn eine Methode angegebene werden muss und die Methode nur dort benötigt wird, dann kann man evtl. einiges weglassen. Und damit ist dann der lambda Ausdruck geboren:
Code:
canvas.setOnMousePressed( e -> System.out.println("Eine Maustaste wurde gedrückt!"));

Lambda Ausdrücke sind (Parameter) -> Code wobei bei einem Parameter die () entfallen können. Code sollte ein einzelner Befehl sein. Ein Block ist auch technisch möglich, aber das wird unübersichtlich.
Bei den Parametern muss der Typ nicht angegeben werden. Den sucht sich der Compiler selbst heraus.

Das wäre die absolute Kurzerklärung. Aber im Netz wirst Du zu Lambda Ausdrücken und Methodenreferenzen auch sehr viel finden!
 

Neue Themen


Zurück
Oben