it-swarm.com.ru

Как поменять местами экраны в javafx-приложении в классе контроллера?

Эй, я долго искал в сети, но не смог найти решение следующей проблемы:

В javafx вы получили 3 основных файла; класс контроллера, файл fxml и класс приложения. Теперь я хочу отреагировать в контроллере на нажатие кнопки (которое прекрасно работает) и изменить экран на этом щелчке (что вы обычно делаете с stage.setScreen ()), но я не имею никакого отношения к этапу (который вы можно найти в классе приложений).

Применение-Sample:

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-Sample:

<?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>

Контроллер-Sample:

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
}    
}

Я был бы благодарен за любую помощь.

15
B Y E
@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()));
}
26
Uluk Biy

Я нашел этот старый вопрос, входя в Java и пытаясь решить одну и ту же проблему ........ Поскольку я хотел, чтобы сцены запоминали содержимое между коммутаторами, я не мог использовать принятый ответ, потому что при переключении между сценами он создает экземпляры. их снова (теряя свое предыдущее состояние).

В любом случае принятый ответ и ответ на аналогичный вопрос дал мне подсказку о том, как переключать сцены, не теряя их состояния .. Основная идея состоит в том, чтобы внедрить экземпляр сцены в другой контроллер, чтобы Контроллеру не нужно создавать новую сцену снова и снова, но он может использовать уже существующий экземпляр (с его состоянием).

Итак, вот основной класс, который создает сцены:

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);
    }
}
10
WallTearer

Вы тоже можете попробовать это.

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();
    }

}
2
Abdul.Moqueet