我还是Java项目开发的新手,你能指出我把String传递给另一个控制器做错了什么吗?以下是我的解决方案。我正试图将StringpurchaseCode
的值从我的第一个控制器(DashboardController.java
(传递给另一个控制器,以便在查询中使用它,或者只是简单地将它设置为文本。但是当我把它调用到我的另一个控制器(InfoSalesController.java
(时,结果我得到了null。
DashboardController.java
...
SalesController sales = getTableView().getItems().get(getIndex());
String purchaseCode = sales.getPurchaseCol();
Hyperlink link = new Hyperlink(purchaseCode);
link.setOnAction(event->{
try{
Stage stage = new Stage();
FXMLLoader loader = new
FXMLLoader(getClass().getResource("/store/sales/infoSales.fxml"));
Parent pane = (Parent) loader.load();
InfoSalesController is = loader.getController();
is.setPurchaseSales(purchaseCode);
stage.setScene(new Scene(pane));
stage.setResizable(false);
stage.initModality(Modality.APPLICATION_MODAL);
stage.show();
}catch(IOException e){
e.printStackTrace();
}
});
setGraphic(link);
...
InfoSalesController.java
public String getPurchaseSales() {
return purchaseSales;
}
public void setPurchaseSales(String purchaseSales) {
this.purchaseSales = purchaseSales;
}
@Override
public void initialize(URL url, ResourceBundle rb) {
purchaseTxt.setText(purchaseSales);
}
这个问题实际上是的重复
- 传递参数JavaFXFXML
但这个问题提出了一个有趣的附带问题:";Platform.runLater()
如何帮助程序工作&";,对此,我将在这里发布一个答案作为解释。
首先,让我们看看传递参数答案中的代码,并解释它是如何工作的:
public Stage showCustomerDialog(Customer customer) {
FXMLLoader loader = new FXMLLoader(
getClass().getResource(
"customerDialog.fxml"
)
);
Stage stage = new Stage(StageStyle.DECORATED);
stage.setScene(
new Scene(loader.load())
);
CustomerDialogController controller = loader.getController();
controller.initData(customer);
stage.show();
return stage;
}
...
class CustomerDialogController {
@FXML private Label customerName;
void initialize() {}
void initData(Customer customer) {
customerName.setText(customer.getName());
}
}
这里的关键区别在于CustomerDialogController中的initialize()
语句为空,并且添加了一个单独的initData()
函数。initialize()
语句在加载FXML时由FXMLLoader隐式调用。当时,初始化视图实际需要的其余数据(客户数据(不可用,因为它尚未传递给新的控制器。initData(Customer customer)
调用是在加载后显式进行的,它包含作为参数的客户数据,因此可以用来初始化视图。
现在让我们来看看问题中的代码以及Platform.runLater
对它做了什么
您的呼叫控制器中有以下代码:
FXMLLoader loader = new
FXMLLoader(getClass().getResource("/store/sales/infoSales.fxml"));
Parent pane = (Parent) loader.load();
InfoSalesController is = loader.getController();
is.setPurchaseSales(purchaseCode);
这个在你的接收控制器中:
public void setPurchaseSales(String purchaseSales) {
this.purchaseSales = purchaseSales;
}
@Override
public void initialize(URL url, ResourceBundle rb) {
purchaseTxt.setText(purchaseSales);
}
这不起作用,因为调用initialize语句时purchaseTxt为null。
但如果您执行以下操作,则purchaseTxt不为空:
@Override
public void initialize(URL url, ResourceBundle rb) {
Platform.runLater(() -> {
purchaseTxt.setText(purchaseSales);
});
}
将initialize()
的内容封装在Platform.runLater()
中的作用是将初始化函数的处理延迟到将来某个未定义的点。
执行可能发生在下一个场景脉冲。脉冲基于内部计时器,JavaFX使用该计时器来处理动画和布局更改,并向应用程序代码发送事件和回调。
例如,Platform.runLater()
代码可以在1/60秒后,在之后执行
- 应用程序中针对当前脉冲的所有后续语句都已执行AND
- 控制权已移交给JavaFX应用程序框架,该框架执行动画、渲染和布局过程
- 控制权已返回到您的应用程序代码,以执行下一个脉冲的应用程序处理
因此,Platform.runLater()
有效地使初始化过程成为异步调用。异步逻辑是在执行完所有后续代码之后执行的。这意味着,在执行initialize()
Platform.runLater()
块中的异步代码以初始化由新控制器管理的视图元素之前,将执行您在新控制器中设置应用程序数据的代码。
这两种方法都是有效的。我想你可以选择一个你和其他读者最清楚的。就我个人而言,在这种情况下我不会使用Platform.runLater()
。