2012-10-09 33 views
10

嘿,我搜查了一段時間的網,但我找不到解決以下問題:如何在控制器類中的javafx應用程序中交換屏幕?

在javafx中你有3個基本文件;控制器類,fxml文件和應用程序類。現在我想在控制器中做出反應,按下按鈕(其效果非常好),然後在點擊時改變屏幕(通常用stage.setScreen()做的),但是我沒有提及舞臺(你可以在應用程序類中找到)。

應用程序示例:

public class JavaFXApplication4 extends Application { 

@Override 
public void start(Stage stage) throws Exception { 
    Parent root = FXMLLoader.load(getClass().getResource("Sample.fxml")); 

    Scene scene = new Scene(root); 

    stage.setScene(scene); 
    stage.show(); 
} 

/** 
* The main() method is ignored in correctly deployed JavaFX application. 
* main() serves only as fallback in case the application can not be 
* launched through deployment artifacts, e.g., in IDEs with limited FX 
* support. NetBeans ignores main(). 
* 
* @param args the command line arguments 
*/ 
public static void main(String[] args) { 
    launch(args); 
} 
} 

FXML-樣品:

<?xml version="1.0" encoding="UTF-8"?> 

<?import java.lang.*?> 
<?import java.util.*?> 
<?import javafx.scene.*?> 
<?import javafx.scene.control.*?> 
<?import javafx.scene.layout.*?> 

<AnchorPane id="AnchorPane" prefHeight="200.0" prefWidth="320.0" xmlns:fx="http://javafx.com/fxml" fx:controller="javafxapplication4.SampleController"> 
    <children> 
    <Button id="button" fx:id="nextScreen" layoutX="126.0" layoutY="90.0" onAction="#handleButtonAction" text="Next Screen" /> 
    <Label fx:id="label" layoutX="126.0" layoutY="120.0" minHeight="16.0" minWidth="69.0" /> 
    </children> 
</AnchorPane> 

控制器 - 樣品:

public class SampleController implements Initializable { 

@FXML 
private Label label; 

@FXML 
private void handleButtonAction(ActionEvent event) { 
    System.out.println("You clicked me!"); 
    label.setText("Hello World!"); 
    //Here I want to swap the screen! 
} 

@Override 
public void initialize(URL url, ResourceBundle rb) { 
    // TODO 
}  
} 

我會感謝任何形式的幫助。

回答

18
@FXML 
private void handleButtonAction(ActionEvent event) { 
    System.out.println("You clicked me!"); 
    label.setText("Hello World!"); 
    //Here I want to swap the screen! 

    Stage stageTheEventSourceNodeBelongs = (Stage) ((Node)event.getSource()).getScene().getWindow(); 
    // OR 
    Stage stageTheLabelBelongs = (Stage) label.getScene().getWindow(); 
    // these two of them return the same stage 
    // Swap screen 
    stage.setScene(new Scene(new Pane())); 
} 
+0

非常感謝,那就是我一直在尋找:) –

+0

這是非常有益的!謝謝 :) –

0

我在進入Java並嘗試解決同樣的事情時發現了這個老問題。 因爲我想讓場景記住開關之間的內容,所以我無法使用接受的答案,因爲在場景之間切換時,它會再次實例化它們(丟失之前的狀態)。

反正接受的答案和answer to the similar question給了我一個提示,如何切換場景而不失去他們的狀態。 主要想法是將場景的實例注入另一個控制器,以便控制器不需要一遍又一遍地實例化新場景,但可以使用已存在的實例(及其狀態)。

所以這裏是實例化場景的主類:

public class Main extends Application { 

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

    @Override 
    public void start(Stage primaryStage) throws Exception { 
     // getting loader and a pane for the first scene. 
     // loader will then give a possibility to get related controller 
     FXMLLoader firstPaneLoader = new FXMLLoader(getClass().getResource("firstLayout.fxml")); 
     Parent firstPane = firstPaneLoader.load(); 
     Scene firstScene = new Scene(firstPane, 300, 275); 

     // getting loader and a pane for the second scene 
     FXMLLoader secondPageLoader = new FXMLLoader(getClass().getResource("secondLayout.fxml")); 
     Parent secondPane = secondPageLoader.load(); 
     Scene secondScene = new Scene(secondPane, 300, 275); 

     // injecting second scene into the controller of the first scene 
     FirstController firstPaneController = (FirstController) firstPaneLoader.getController(); 
     firstPaneController.setSecondScene(secondScene); 

     // injecting first scene into the controller of the second scene 
     SecondController secondPaneController = (SecondController) secondPageLoader.getController(); 
     secondPaneController.setFirstScene(firstScene); 

     primaryStage.setTitle("Switching scenes"); 
     primaryStage.setScene(firstScene); 
     primaryStage.show(); 
    } 
} 

而且這裏有兩個控制器:

public class FirstController { 

    private Scene secondScene; 

    public void setSecondScene(Scene scene) { 
     secondScene = scene; 
    } 

    public void openSecondScene(ActionEvent actionEvent) { 
     Stage primaryStage = (Stage)((Node)actionEvent.getSource()).getScene().getWindow(); 
     primaryStage.setScene(secondScene); 
    } 
} 

是的,第二個看起來是一樣的(一些邏輯也許可以共享,但目前的狀態足以作爲概念證明)

public class SecondController { 

    private Scene firstScene; 

    public void setFirstScene(Scene scene) { 
     firstScene = scene; 
    } 

    public void openFirstScene(ActionEvent actionEvent) {  
     Stage primaryStage = (Stage)((Node)actionEvent.getSource()).getScene().getWindow(); 
     primaryStage.setScene(firstScene); 
    } 
} 
0

你可以嘗試這樣太。

public void onBtnClick(ActionEvent event) { 
    try { 
     FXMLLoader loader = new FXMLLoader(getClass().getResource("login.fxml")); 
     Stage stage = (Stage) btn.getScene().getWindow(); 
     Scene scene = new Scene(loader.load()); 
     stage.setScene(scene); 
    }catch (IOException io){ 
     io.printStackTrace(); 
    } 

} 
相關問題