gpt4 book ai didi

JavaFx 更改窗口,无需新的 Controller 构造函数

转载 作者:行者123 更新时间:2023-11-30 06:50:20 25 4
gpt4 key购买 nike

我有 2 个 fxml 文件。示例 A.fxml。 B.fxml。我有 2 个 Controller 。 A Controller (A.fxml)B Controller (B.fxml)。 A fxml 和 B fxml 具有更改场景或 fxml 的更改按钮。这是按钮代码;

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

BContrroller 更改按钮中的代码相同。当我单击更改按钮时,扫描会发生变化。但每次 init 方法和 Controller 构造器也在工作。当用户每次使用新的构造函数更改 fxml javafx 时。如何在没有新 Controller 构造函数的情况下更改窗口?

最佳答案

使用 View 模型:

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

}

现在在您的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);
}
}

BController类似。

最后,您可以使用如下所示的内容设置所有内容,该内容仅执行一次(例如在您的 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();

现在,这两个 FXML 文件仅加载一次(因此 Controller 仅创建一次,并且它们的 initialize() 方法仅调用一次)。通过更改 ViewModel 的状态并观察该状态来管理切换,因此当模型状态更改时场景的根也会更改。

这是一个完整的 SSCCE:

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:

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:

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

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:

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

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

关于JavaFx 更改窗口,无需新的 Controller 构造函数,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/42937083/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com