将数据传递到Javafx中的另一个控制器



我还是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秒后,在之后执行

  1. 应用程序中针对当前脉冲的所有后续语句都已执行AND
  2. 控制权已移交给JavaFX应用程序框架,该框架执行动画、渲染和布局过程
  3. 控制权已返回到您的应用程序代码,以执行下一个脉冲的应用程序处理

因此,Platform.runLater()有效地使初始化过程成为异步调用。异步逻辑是在执行完所有后续代码之后执行的。这意味着,在执行initialize()Platform.runLater()块中的异步代码以初始化由新控制器管理的视图元素之前,将执行您在新控制器中设置应用程序数据的代码。

这两种方法都是有效的。我想你可以选择一个你和其他读者最清楚的。就我个人而言,在这种情况下我不会使用Platform.runLater()

最新更新