如何获取对另一个控制器的引用-JavaFX
假设我有3个视图和3个控制器:如何获取对另一个控制器的引用-JavaFX,javafx,Javafx,假设我有3个视图和3个控制器: LogInController,LogInView MainMenuController,MainMenuView 内部医疗中心控制器患者列表,内部医疗中心视图患者列表 单击一个InternalMedicineButonClicked方法将我的场景更改为另一个场景(带有一些其他内容),但在这个新场景中,我希望有一个按钮,允许我返回主菜单(goBacktoMainMenuButtonClicked()方法)。我的问题来了。我如何才能获得对MainMenuContro
LogInController
,LogInView
MainMenuController
,MainMenuView
内部医疗中心控制器患者列表
,内部医疗中心视图患者列表
单击一个InternalMedicineButonClicked
方法将我的场景更改为另一个场景(带有一些其他内容),但在这个新场景中,我希望有一个按钮,允许我返回主菜单(goBacktoMainMenuButtonClicked()
方法)。我的问题来了。我如何才能获得对MainMenuController(与在LogInController中创建的fxml文件相对应的文件)的引用,以填充setController()
方法
public class LogInController {
MainMenuController mainMenuController = new MainMenuController();
@FXML
private JFXTextField logInTextField;
@FXML
private JFXButton logInButton;
@FXML
private JFXPasswordField passwordTextField;
@FXML
void logInButtonClicked(ActionEvent event) throws IOException {
LogInDAO logInDAO = new LogInDAO();
if(logInDAO.checkIfLoginAndPasswordIsCorrect(logInTextField.getText(),passwordTextField.getText()))
{
FXMLLoader loader = new FXMLLoader(getClass().getResource("/fxml/MainMenu.fxml"));
Window window = logInButton.getScene().getWindow();
Stage stage = (Stage) window;
loader.setController(mainMenuController); // here i'm passing original controller corresponding with fmxl
stage.setScene(new Scene(loader.load()));
}
else
{
(...)
}
}
}
MainMenuController类:
public class MainMenuController {
ContentOfPatientTableView patientTableViewModel = new ContentOfPatientTableView();
(..)
@FXML
void internalMedicineButtonClicked(ActionEvent event) throws IOException {
FXMLLoader loader = new FXMLLoader(getClass().getResource("/fxml/ListOfPatientsInternalMedicineView.fxml"));
Button button = (Button) event.getSource();
Scene scene = button.getScene();
Stage stage = (Stage) scene.getWindow();
loader.setController(new ListOfPatientsInternalMedicineController(patientTableViewModel));
stage.setScene(new Scene(loader.load()));
}
以及InternalMedicineController类的患者列表
public class ListOfPatientsInternalMedicineController {
IPatientDAO patientDAO = new PatientDAO();
ContentOfPatientTableView patientTableViewModel;
public ListOfPatientsInternalMedicineController(ContentOfPatientTableView content) {
patientTableViewModel=content;
}
@FXML
public void goBacktoMainMenuButtonClicked(ActionEvent event)
{
FXMLLoader loader = new FXMLLoader(MainMenuController.class.getResource("/fxml/MainMenuView.fxml");
loader.setController(?????????); // Here if I will pass new MainController() i will create new instance, not this which is corresponding with fxml file. How am I able to refer to instance MainController created in LogInController ?
}
}
考虑使用另一个模型来表示当前视图。您可以通过以下方式实现这一点:
public class ViewState {
private final ContentOfPatientTableView patientTableViewModel ;
private final ReadOnlyObjectWrapper<Parent> currentView = new ReadOnlyObjectWrapper<>();
private Parent logInView ;
private Parent mainMenuView ;
private Parent listOfPatientsMainMedicineView ;
public ViewState(ContentOfPatientTableView patientTableViewModel) {
this.patientTableViewModel = patientTableViewModel ;
}
public ReadOnlyObjectProperty<Parent> currentViewProperty() {
return currentView.getReadOnlyProperty();
}
public void showLogIn() {
if (logInView == null) {
try {
FXMLLoader loader = new FXMLLoader("/fxml/LogIn.fxml");
loader.setController(new LogInController(this));
logInView = loader.load();
} catch (IOException exc) {
// fatal...
throw new UncheckedIOException(exc);
}
}
currentView.set(logInView);
}
public void showMainMenu() {
// similarly...
}
public void showListOfPatientsMainMedicineView() {
// ...
}
}
同样地
public class MainMenuController {
private final ViewState viewState ;
public MainMenuController(ViewState viewState) {
this.viewState = viewState ;
}
@FXML
void internalMedicineButtonClicked(ActionEvent event) throws IOException {
viewState.showListOfPatientsMainMedicineView();
}
}
对于另一个控制器也是如此
请注意,您正在ViewState
中实例化每个控制器,因此只需让该类访问它可能需要的每个其他模型
最后,你可以用
public class MyApp extends Application {
@Override
public void start(Stage primaryStage) {
ViewState viewState = new ViewState(/* pass models here...*/);
viewState.showLogIn();
Scene scene = new Scene(viewState.currentViewProperty().get());
scene.rootProperty().bind(viewState.currentViewProperty());
primaryStage.setScene(scene);
primaryStage.show();
}
}
要执行此操作,您必须将
MainMenuController
的实例传递到患者列表sinternalmedicinecontroller
类。当再次加载FXML时,您可能不希望重用控制器类的实例,因此您可能并不真正希望重新加载FXML。如果主控制器保留对其根元素的引用,则可以使用一个方法将该根元素设置为场景的根元素。将对主控制器的引用传递给第三个控制器,并在需要返回时调用该方法。另一种(可能更好?)方法是使用另一个模型类,该类具有类似于ObjectProperty currentView
的特性。与您的所有控制器共享该模型(您已经演示了如何使用现有模型执行此操作)。您可以观察该值,并在其更改时将该视图显示为场景的根;然后,控制器只需更改属性即可切换场景。同样,您可能希望加载每个FXML一次。是的,我确实希望加载每个FXML一次,但我仍然不明白如何保存创建的每个FXML加载程序!此ObjectProperty一次只能保存一个场景。我知道如何传递模型等。但我不知道您对该模型应如何工作的想法。我在回答中简述了该想法非常感谢!现在这对我来说是有意义的me@Michael213伟大的它可能需要一些“调整”来获得您想要的方式(例如,您可能只是在“视图状态”中实例化所有其他模型,或者相反,您甚至可以将所有ViewState
代码移动到应用程序
类)。但它应该给你这个想法的要点。
public class MyApp extends Application {
@Override
public void start(Stage primaryStage) {
ViewState viewState = new ViewState(/* pass models here...*/);
viewState.showLogIn();
Scene scene = new Scene(viewState.currentViewProperty().get());
scene.rootProperty().bind(viewState.currentViewProperty());
primaryStage.setScene(scene);
primaryStage.show();
}
}