studyklar
GdI 2 · Übungsblatt 10 · Aufgabe 2

Springender Button: Klick und Mausberührung

Ein Button, der wegspringt, sobald man ihn klickt, und später schon, wenn die Maus ihn nur berührt. Dafür setzen wir den Button an feste Koordinaten und lassen JavaFX bei einem Ereignis neue, zufällige Koordinaten wählen. Rechts steht das Programm des aktuellen Teils, die Zeilen zum Schritt sind hervorgehoben. Mit Weiter geht es Schritt für Schritt voran.

Die Aufgabe

Aufgabe 2

a) Programmieren Sie eine JavaFX-Anwendung, die in der Mitte des Fensters einen Button anzeigt. Wenn man auf den Button drückt, soll er an eine andere, zufällige Stelle des Fensters springen.

Hinweise:

Verwenden Sie als Container ein Objekt der Klasse „Pane“. Die Zuordnung eines Buttons zu einer Pane erfolgt wie bei HBox, VBox usw. Zur Positionierung des Buttons in absoluten Koordinaten (ausgehend vom Nullpunkt links oben) rufen Sie die Methoden „setLayoutX“ und „setLayoutY“ des Buttons auf.

Der Button soll immer ganz im Fenster sichtbar sein. Hierzu müssen Sie die Breite und die Höhe des Buttons berücksichtigen. Diese können Sie mit den Methoden „getWidth“ und „getHeight“ des Buttons ermitteln (allerdings erst, wenn die betreffenden Buttons bereits einmal angezeigt wurden).

b) Nun soll der Button nicht mehr wegspringen, wenn er gedrückt wird, sondern bereits, wenn der Mauszeiger den Button berührt. Verwenden Sie hierzu die Methode „setOnMouseEntered“ des Buttons.

Gesucht ist ein Fenster mit einem einzigen Button. In a) springt er bei jedem Klick an eine zufällige Stelle. In b) springt er schon, wenn der Mauszeiger ihn berührt; fangen kann man ihn dann kaum noch. In beiden Teilen muss der Button immer ganz zu sehen sein.

Merke: Die Koordinaten eines Knotens nennen seine linke obere Ecke. Damit ein Button ganz ins Fenster passt, darf diese Ecke höchstens bei Fensterbreite minus Buttonbreite liegen.
  1. a) Pane mit Button, Aktion beim Klick, Grenzen für den Zufall.
  2. b) Dieselbe Aktion beim Berühren mit der Maus.

Eine Pane und der Button an festen Koordinaten

        final int BREITE = 1000;        final int HOEHE = 800;         Pane root = new Pane();        Button button = new Button("Drück' mich");        button.setLayoutX(BREITE / 2);        button.setLayoutY(HOEHE / 2);        root.getChildren().add(button);

Fang mich

das Fenster als Skizze
TeilGröße in Pixelnlinke obere Ecke
Fenster (Scene)1000 × 800(0, 0)
Button „Drück’ mich“82,1 × 26 (gemessen)(500, 400)

Eine Pane ordnet ihre Kinder nicht selbst an, anders als HBox oder VBox. Jeder Knoten steht dort, wo seine Koordinaten es sagen. Genau das brauchen wir: Der Button soll an beliebigen Stellen stehen können.

BREITE und HOEHE legen die Fenstergröße fest, 1000 mal 800 Pixel. setLayoutX(BREITE / 2) und setLayoutY(HOEHE / 2) setzen die linke obere Ecke des Buttons auf (500, 400), die Mitte des Fensters. Gezählt wird ab dem Nullpunkt links oben; y wächst nach unten.

Genau genommen steht damit die Ecke in der Mitte, nicht der Button. Gegenüber einem mittigen Button ist er um seine halbe Breite (82,1 / 2 ≈ 41 Pixel) nach rechts und seine halbe Höhe (26 / 2 = 13 Pixel) nach unten verschoben. Seine Größe kennt Java erst, wenn er einmal angezeigt wurde (Hinweis der Aufgabe). Die Musterlösung nimmt diese kleine Abweichung hin.

Aus Blatt 1, Aufgabe 3 („Minuten in Tage, Stunden und Minuten umrechnen“): final macht eine Variable zur Konstanten: Ihr Wert kann nach der ersten Zuweisung nicht mehr geändert werden.
Aus Vorlesung 12, Folie 21 („Verschiedene Arten von Containern (1)“): Pane ist die Oberklasse aller Container und positioniert ihre Knoten absolut.

Beim Klick: neue Koordinaten

        Random zufall = new Random();         button.setOnAction(e -> {            button.setLayoutX(zufall.nextInt(1, BREITE - (int) button.getWidth()));            button.setLayoutY(zufall.nextInt(1, HOEHE - (int) button.getHeight()));        });

setOnAction legt fest, was beim Drücken des Buttons passiert. Übergeben wird ein Lambda, eine Methode ohne Namen: e -> { … }. Links vom Pfeil steht der Parameter e, das Ereignis (der Klick). Rechts steht, was dann ausgeführt wird. Wir brauchen e hier nicht.

Im Lambda bekommt der Button mit setLayoutX und setLayoutY neue, zufällige Koordinaten. Den Zufall liefert zufall, ein Objekt der Klasse Random. Es wird nur einmal angelegt (Zeile 22) und bei jedem Klick wieder benutzt.

Aus Vorlesung 12, Folie 17 („Den Buttons Funktionalität hinzufügen“): Was beim Drücken eines Buttons passieren soll, steht als Lambda in setOnAction.
Aus Blatt 2, Aufgabe 5 („Schere, Stein, Papier: Gewinner und Regel bestimmen“): r.nextInt(1, 4) liefert eine zufällige ganze Zahl ab 1 und unter 4, also 1, 2 oder 3. Die obere Grenze selbst kommt nie vor.
Noch 5 Schritte bis zum Ergebnis
Den ganzen Lösungsweg sehen Studierende und Lehrende der HS KL. Registriere dich mit deiner Adresse @stud.hs-kl.de oder @hs-kl.de, dann geht es hier direkt weiter.

SpringenderButton.java

Teil a)

Abbildung 1SpringenderButton.java

Teil a)

import java.util.Random;import javafx.application.Application;import javafx.scene.Scene;import javafx.scene.control.Button;import javafx.scene.layout.Pane;import javafx.stage.Stage; public class SpringenderButton extends Application {     @Override    public void start(Stage primaryStage) {         final int BREITE = 1000;        final int HOEHE = 800;         Pane root = new Pane();        Button button = new Button("Drück' mich");        button.setLayoutX(BREITE / 2);        button.setLayoutY(HOEHE / 2);        root.getChildren().add(button);         Random zufall = new Random();         button.setOnAction(e -> {            button.setLayoutX(zufall.nextInt(1, BREITE - (int) button.getWidth()));            button.setLayoutY(zufall.nextInt(1, HOEHE - (int) button.getHeight()));        });         Scene scene = new Scene(root, BREITE, HOEHE);         primaryStage.setTitle("Fang mich");        primaryStage.setScene(scene);        primaryStage.show();    }     public static void main(String[] args) {        launch(args);    }}
LegendeDas ganze Programm für Teil a).