2016-04-08 14 views
1

Bitte helfen Sie mir, es funktioniert. Es friert ein, anstatt Szenen zu ändern. Es funktioniert gut, wenn die Tasten auf diese Weise erstellt werden:Javafx wie man Tasten über Funktion erstellt?

Button b1 = new Button("Go to s2"); 
b1.setOnAction(e -> window.setScene(s2)); 
Button b2 = new Button("Go to s1"); 
b2.setOnAction(e -> window.setScene(s1)); 

Aber ich mag es eleganter machen ...

import javafx.application.Application; 
import javafx.scene.Scene; 
import javafx.scene.control.Button; 
import javafx.stage.Stage; 

public class Main extends Application { 

    Stage window; 
    Scene s1,s2; 

    public static void main(String[] args) { 
     launch(args); 
    } 

    @Override 
    public void start(Stage primaryStage) throws Exception { 
     window = primaryStage; 

     Button b1 = makeButton("Go to s2", s2); 
     Button b2 = makeButton("Go to s1", s1); 

     s1 = new Scene(b1); 
     s2 = new Scene(b2); 

     primaryStage.setScene(s1); 
     primaryStage.show(); 
    } 

    public Button makeButton(String name, Scene destScene) { 
     Button button = new Button(name); 
     button.setOnAction(e -> window.setScene(destScene)); 
     return button; 
    } 
} 

Vielen Dank im Voraus!

Antwort

1

Blick auf die Bestellung, wie alles initialisiert wird:

Button b1 = makeButton("Go to s2", s2); 
Button b2 = makeButton("Go to s1", s1); 

s1 = new Scene(b1); 
s2 = new Scene(b2); 

Wenn Sie makeButton aufrufen, übergeben Sie in der Wert des Referenz gespeichert derzeit in s1 und s2. Da es nie initialisiert wurde, nimmt es den Standardwert null. Dies wird nicht geändert, wenn Sie die Zeichen s1 und s2 wegen der kopierten Referenz setzen.

Sie haben nicht das gleiche Problem im ersten Fall, weil Sie nie eine Kopie von s1 und s2 machen. Stattdessen haben Sie die EventHandler verweisen auf das Feld in der aktuellen Instanz von Main, die korrekt aktualisiert wird, sobald Sie es festlegen. Also Ihr Original-Code ist etwas, das entspricht dies:

Button b1 = new Button("Go to s2"); 
b1.setOnAction(e -> window.setScene(this.s2)); 

So sind Kopieren Sie den Verweis auf die umschließenden Main Instanz, anstatt der Bezugnahme auf die Schaltfläche selbst.

Ich sehe leider keine triviale Lösung dafür. Die einfachste Lösung, die ich sehen würde Ihre Funktion makeButton(String, EventHandler<ActionEvent>), zu ändern und es so nennen:

Button b1 = makeButton("Go to s2", e -> window.setScene(s2)); 

Nicht so schön wie das, was Sie wollen, aber es sollte funktionieren.

Eine weitere mögliche Lösung besteht darin, alle Ihre Button s in ein Array zu setzen und dann einen Index in dieses Array in makeButton zu übergeben. Das würde so aussehen tihs:

public class Main extends Application { 
    Stage window; 
    Scene[] scenes = new Scene[2]; 

    @Override 
    public void start(Stage primaryStage) throws Exception { 
     window = primaryStage; 

     Button b1 = makeButton("Go to s2", 1); 
     Button b2 = makeButton("Go to s1", 0); 

     scenes[0] = new Scene(b1); 
     scenes[1] = new Scene(b2); 

     primaryStage.setScene(scenes[0]); 
     primaryStage.show(); 
    } 

    public Button makeButton(String name, int destScene) { 
     Button button = new Button(name); 
     button.setOnAction(e -> window.setScene(scenes[destScene])); 
     return button; 
    } 
} 

dass die EventHandler ändert ein Feld von Main (scenes) eher als eine lokale Variable (destScene) zu verweisen.

Verwandte Themen