[英]JavaFx Change Window, Without New Controller Constructor
I have 2 fxml file. 我有2个fxml文件。 Example A.fxml.
示例A.fxml。 B.fxml.
B.fxml。 I have 2 controller.
我有2个控制器。 AController (A.fxml) BController (B.fxml).
AController(A.fxml)BController(B.fxml)。 A fxml and B fxml have change button changing Scene or fxml.
fxml和B fxml有更改按钮更改Scene或fxml。 This is button code;
这是按钮代码;
try {
FXMLLoader loader = new FXMLLoader(getClass().getResource("/infoLibrary/view/A.fxml"));
Parent root = loader.load();
Scene scene = new Scene(root);
Stage stage = (Stage)((Node)event.getSource()).getScene().getWindow();
stage.setScene(scene);
stage.show();
} catch (IOException e) {
e.printStackTrace();
}
Same code in BContrroller change button. BContrroller中的相同代码更改按钮。 When i click change button scane changing.
当我点击更改按钮scane更改。 But everytime init method and controller contructers working too.
但每次init方法和控制器构造都会起作用。 When user change fxml javafx everytime using new constructor.
当用户每次使用新构造函数更改fxml javafx时。 How can i change windows without new controller constructor?
如何在没有新控制器构造函数的情况下更改窗口?
Use a view model: 使用视图模型:
public class ViewModel {
public enum View {A, B}
private final ObjectProperty<View> currentView = new SimpleObjectProperty<>(View.A);
public ObjectProperty<View> currentViewProperty() {
return currentView ;
}
public final View getCurrentView() {
return currentViewProperty().get();
}
public final View setCurrentView(View view) {
currentViewProperty().set(view);
}
}
Now in your AController
do: 现在在你的
AController
做:
public class AController {
private ViewModel viewModel ;
public void setViewModel(ViewModel viewModel) {
this.viewModel = viewModel ;
}
// button handler:
@FXML
private void goToB(ActionEvent event) {
viewModel.setCurrentView(ViewModel.View.B);
}
}
and BController
is similar. 和
BController
类似。
Finally, you set everything up with something like the following, which is executed only once (eg in your start()
method, or somewhere similar): 最后,你用以下内容设置所有东西,只执行一次(例如在你的
start()
方法或类似的地方):
Stage stage = ... ; // maybe it's the primary stage in start...
Scene scene = new Scene();
ViewModel viewModel = new ViewModel();
FXMLLoader aLoader = new FXMLLoader(getClass().getResource("/infoLibrary/view/A.fxml"));
Parent a = aLoader.load();
AController aController = aLoader.getController();
aController.setViewModel(viewModel);
FXMLLoader bLoader = new FXMLLoader(getClass().getResource("/infoLibrary/view/B.fxml"));
Parent b = bLoader.load();
BController bController = bLoader.getController();
bController.setViewModel(viewModel);
scene.rootProperty().bind(Bindings.createObjectBinding(() -> {
if (viewModel.getCurrentView() == ViewModel.View.A) {
return a ;
} else if (viewModel.getCurrentView() == ViewModel.View.B) {
return b ;
} else {
return null ;
}
}, viewModel.currentViewProperty());
stage.setScene(scene);
stage.show();
Now the two FXML files are only loaded once (so the controllers are only created once, and their initialize()
methods called only once). 现在两个FXML文件只加载一次(因此控制器只创建一次,并且它们的
initialize()
方法只调用一次)。 The switching is managed by changing the state of the ViewModel
and observing that state, so the scene's root is changed when the model state changes. 通过更改
ViewModel
的状态并观察该状态来管理切换,因此在模型状态更改时会更改场景的根。
Here is a complete SSCCE: 这是一个完整的SSCCE:
ViewModel.java: ViewModel.java:
package sceneswitcher;
import javafx.beans.property.ObjectProperty;
import javafx.beans.property.SimpleObjectProperty;
public class ViewModel {
public enum View {A, B}
private final ObjectProperty<View> currentView = new SimpleObjectProperty<>(View.A);
public ObjectProperty<View> currentViewProperty() {
return currentView ;
}
public final View getCurrentView() {
return currentViewProperty().get();
}
public final void setCurrentView(View view) {
currentViewProperty().set(view);
}
}
AController.java: AController.java:
package sceneswitcher;
import javafx.event.ActionEvent;
import javafx.fxml.FXML;
import javafx.scene.control.TextField;
public class AController {
private ViewModel viewModel ;
@FXML
private TextField textField ;
public void setViewModel(ViewModel viewModel) {
this.viewModel = viewModel ;
}
// button handler:
@FXML
private void goToB(ActionEvent event) {
viewModel.setCurrentView(ViewModel.View.B);
}
public String getText() {
return textField.getText();
}
}
A.fxml: A.fxml:
<?xml version="1.0" encoding="UTF-8"?>
<?import javafx.scene.layout.VBox?>
<?import javafx.scene.control.Label?>
<?import javafx.scene.control.TextField?>
<?import javafx.scene.control.Button?>
<VBox fx:controller="sceneswitcher.AController" spacing="5" alignment="CENTER"
xmlns:fx="http://javafx.com/fxml/1">
<Label text='This is view A'/>
<TextField fx:id="textField" />
<Button onAction="#goToB" text="Go to view B"/>
</VBox>
BController.java: BController.java:
package sceneswitcher;
import javafx.event.ActionEvent;
import javafx.fxml.FXML;
import javafx.scene.control.TextArea;
public class BController {
private ViewModel viewModel ;
@FXML
private TextArea textArea ;
public void setViewModel(ViewModel viewModel) {
this.viewModel = viewModel ;
}
// button handler:
@FXML
private void goToA(ActionEvent event) {
viewModel.setCurrentView(ViewModel.View.A);
}
public String getText() {
return textArea.getText();
}
}
B.fxml: B.fxml:
<?xml version="1.0" encoding="UTF-8"?>
<?import javafx.scene.layout.VBox?>
<?import javafx.scene.control.Label?>
<?import javafx.scene.control.TextArea?>
<?import javafx.scene.control.Button?>
<VBox fx:controller="sceneswitcher.BController" spacing="5" alignment="CENTER"
xmlns:fx="http://javafx.com/fxml/1">
<Label text="This is view B"/>
<TextArea fx:id="textArea" />
<Button onAction="#goToA" text="Go to View A"/>
</VBox>
Main.java: Main.java:
package sceneswitcher;
import java.io.IOException;
import javafx.application.Application;
import javafx.beans.binding.Bindings;
import javafx.fxml.FXMLLoader;
import javafx.scene.Parent;
import javafx.scene.Scene;
import javafx.stage.Stage;
public class Main extends Application {
@Override
public void start(Stage primaryStage) throws IOException {
ViewModel viewModel = new ViewModel();
FXMLLoader aLoader = new FXMLLoader(getClass().getResource("A.fxml"));
Parent a = aLoader.load();
AController aController = aLoader.getController();
aController.setViewModel(viewModel);
FXMLLoader bLoader = new FXMLLoader(getClass().getResource("B.fxml"));
Parent b = bLoader.load();
BController bController = bLoader.getController();
bController.setViewModel(viewModel);
Scene scene = new Scene(a, 400, 400);
scene.rootProperty().bind(Bindings.createObjectBinding(() -> {
if (viewModel.getCurrentView() == ViewModel.View.A) {
return a ;
} else if (viewModel.getCurrentView() == ViewModel.View.B) {
return b ;
} else {
return null ;
}
}, viewModel.currentViewProperty()));
primaryStage.setScene(scene);
primaryStage.show();
}
public static void main(String[] args) {
launch(args);
}
}
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.