Thema in Kurzform
Gerade in spielorientierter Software ist es notwendig, dass sich einzelnde Nodes durch Nutzersteuerung von einem Ort zum anderen bewegen lassen. In diesem Tutorial zeigen wir dir drei Wege, genau das hinzukriegen: Über Buttonklick, via Tastatur-Input und über einen Klick mit der Maus.
Für unser Beispiel erstellen wir ein kleines Rechteck, das sich mithilfe von vier Buttons jeweils 20 Pixel nach oben, links, rechts und unten bewegen soll:
Für die Gestaltung der vier Richtungs-Buttons sowie dem Rechteck-Node verwenden wir dieses JavaFX-Programm:
// Buttons erstellen
Button b1 = new Button("HOCH");
b1.setPrefSize(100, 25);
b1.setLayoutX(100);
b1.setLayoutY(50);
Button b2 = new Button("LINKS");
b2.setPrefSize(100, 25);
b2.setLayoutX(50);
b2.setLayoutY(75);
Button b3 = new Button("RECHTS");
b3.setPrefSize(100, 25);
b3.setLayoutX(150);
b3.setLayoutY(75);
Button b4 = new Button("RUNTER");
b4.setPrefSize(100, 25);
b4.setLayoutX(100);
b4.setLayoutY(100);
// Rechteck-Node erstellen
Rectangle rechteck = new Rectangle(125,200,50,50);
rechteck.setFill(Color.FUCHSIA);
rechteck.setStroke(Color.BLACK);
rechteck.setFocusTraversable(true);
// Scene erstellen
AnchorPane ap = new AnchorPane();
ap.getChildren().addAll(b1, b2, b3, b4, rechteck);
Scene s = new Scene(ap, 600, 400);
Es ist jetzt sehr einfach, das Rechteck bewegen zu lassen. Wie wir im Kapitel zum EvenHandling gesehen haben, können wir über die Button-Methode setOnAction() und einem Lambda-Ausdruck einen EventHandler auf jeden der vier Buttons legen. Bei einem Klick auf einen der Buttons, wir jeweils eine Aktion ausgeführt.
In unserem Fall soll das Rechteck um je 20 Pixel in eine der vier Richtungen bewegt werden. Je nachdem, welcher Button geklickt wird. Die Position des Rechtecks wird dabei über die Methoden setY() und setX() neu bestimmt:
b1.setOnAction(e -> {
rechteck.setY(rechteck.getY() - 20);
});
b2.setOnAction(e -> {
rechteck.setX(rechteck.getX() - 20);
});
b3.setOnAction(e -> {
rechteck.setX(rechteck.getX() + 20);
});
b4.setOnAction(e -> {
rechteck.setY(rechteck.getY() + 20);
});
Das war's auch schon ☺️
Von der Code-Masse noch einfacher ist es, unser Rechteck-Node via Tastatureingaben zu bewegen (z.B. WASD-Movement).
Da wir die vier Buttons von oben nicht mehr benötigen, nehmen wir sie aus dem Programm. Stattdessen legen wir den EventHandler, der auf die Tastatur hört, direkt das Rechteck-Node. Und so sieht das Stück aus:
// Rechteck-Node erstellen
Rectangle rechteck = new Rectangle(125,200,50,50);
rechteck.setFill(Color.FUCHSIA);
rechteck.setStroke(Color.BLACK);
rechteck.setFocusTraversable(true);
// EventHandler
rechteck.addEventHandler(KeyEvent.KEY_PRESSED, (key) -> {
if (key.getCode() == KeyCode.W) {
rechteck.setY(rechteck.getY() - 20);
}
else if (key.getCode() == KeyCode.A) {
rechteck.setX(rechteck.getX() - 20);
}
else if (key.getCode() == KeyCode.D) {
rechteck.setX(rechteck.getX() + 20);
}
else if (key.getCode() == KeyCode.S) {
rechteck.setY(rechteck.getY() + 20);
}
});
// Scene erstellen
AnchorPane ap = new AnchorPane();
ap.getChildren().add(rechteck);
Scene s = new Scene(ap, 600, 400);
primaryStage.show();
primaryStage.setScene(s);
Mit der Methode addEventHandler() setzen wir auf die Rectangle-Referenz rechteck den EventHandler, der auf Keyboard-Eingaben lauscht und reagiert, sofern eine der Tasten W, A, S oder D gedrückt wird. Das Rechteck wird dann entsprechend in eine der vier Richtungen um 20 Pixel versetzt.
In der Regel funktioniert das Bewegen des Rechteck-Nodes über die Tastatur nur dann, wenn das Node auch den Fokus hat. Sollte der Fokus auf ein anderes Node (ungewollt) übergehen, können wir ihn einfach wieder auf das Rechteck zurückholen. Dazu verwenden wir folgende Methode:
Platform.runLater(() -> rechteck.requestFocus());
Diesen Lambda-Ausdruck bauen wir am besten direkt vor dem Codeblock des EventHandlers ein. Wollen wir außerdem sicherstellen, das zu jeder Tastatureingabe der Fokus (erneut) auf das Rechteck-Node zurückgeholt wird, platzieren wir die Anweisung zusätzlich direkt zu Beginn innerhalb des EventHandlers ein.
Kommen wir jetzt noch dazu, unser Rechteck-Node mithilfe eines Mausklicks zu steuern. Das heißt: Das Node soll an die Stelle "springen", wo wir mit der linken Maustaste geklickt haben:
// Rechteck-Node erstellen
Rectangle rechteck = new Rectangle(125,200,50,50);
rechteck.setFill(Color.FUCHSIA);
rechteck.setStroke(Color.BLACK);
rechteck.setFocusTraversable(true);
// Scene erstellen
AnchorPane ap = new AnchorPane();
ap.getChildren().add(rechteck);
Scene s = new Scene(ap, 600, 400);
primaryStage.show();
primaryStage.setScene(s);
// EventFilter erstellen
s.addEventFilter(MouseEvent.MOUSE_PRESSED, new EventHandler<MouseEvent>() {
@Override
public void handle(MouseEvent mouseEvent) {
rechteck.setX(mouseEvent.getX());
rechteck.setY(mouseEvent.getY());
}
});
Wie du siehst, legen wir einen EventFilter direkt auf die Scene-Referenz, weshalb wir uns um den Fokus nicht kümmern müssen.
Das im EventFilter verbaute MouseEvent-Objekt zieht sich die Koordinaten des Maus-Klicks (getX() und getY()). Mit diesen Werten setzen wir dann die Position des Rechecks mit den setter-Methoden einfach neu.
So einfach ist das 🤩
Java Basics
[Java einrichten] [Variablen] [Primitive Datentypen] [Operatoren] [if else] [switch-case] [Arrays] [Schleifen]
Objektorientierung
[Einstieg] [Variablen ] [Konstruktor] [Methoden] [Rekursion] [Statische Member] [Initializer] [Pass-by-value] [Objektsammlungen] [Objektinteraktion] [Objekte löschen]
Klassenbibliothek
[Allgemeines] [String ] [Math] [Wrapper] [Scanner] [java.util.Arrays] [Date-Time-API]
Vererbung
[Einstieg Vererbung] [Konstruktoren bei Vererbung ] [Der protected Zugriffsmodifikator] [Abstrakte Klassen und Methoden] [Polymorphie in Java] [Typumwandlung] [Die Klasse Object] [Die toString()-Methode] [Objekte vergleichen] [Was ist ein Interface?]