Change/Update 另一个 class 中的 FXML 组件

Change/Update FXML components in another class

我的问题是:我想更改 .fxml 中的某些内容,但无论我做什么,都没有任何改变。这只是一个简单的例子。

我浏览了整个互联网,但 none 的解决方案对我有用。 在这里我想通过从主 class.

调用相应的方法来更改标签的文本

单击按钮时调用相同的方法(此处 setLabel()),在控制器中使用事件处理程序 class,一切正常,但是当我尝试修改另一个按钮时class 没有任何效果。

主要class:

package sample;
import javafx.application.Application;
import javafx.application.Platform;
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 Exception{

Parent root = FXMLLoader.load(getClass().getResource("sample.fxml"));
primaryStage.setTitle("Hello World");
primaryStage.setScene(new Scene(root, 300, 275));
primaryStage.show();
Controller controller = new Controller();
Platform.runLater(()->controller.setLabel());

}

FXML 代码:

<BorderPane xmlns="http://javafx.com/javafx/8" xmlns:fx="http://javafx.com/fxml/1" fx:controller="sample.Controller">
   <center>
      <Label fx:id="label" text="This" BorderPane.alignment="CENTER" />
   </center>
</BorderPane>

控制器class: 包装样品;

import javafx.fxml.FXML;
import javafx.scene.control.Label;

public class Controller {
@FXML
private Label label=new Label();

public void setLabel(){
    label.setText("Test");
}
}

你的代码实际上有两个问题。

1)Applicationstart 方法中,您使用 FXMLLoader 加载 sample.fxml,这是正确的.但是创建一个像 Controller controller = new Controller(); 这样的新控制器是不正确的,因为你应该使用 getController 方法从 FXMLLoader 本身获取控制器,而且你不应该使用静态 load 函数FXMLLoader,但您应该创建它的一个实例。

FXMLLoader loader = new FXMLLoader();
Parent root = loader.load(getClass().getResource("sample.fxml"));
Controller controller = loader.getController();

当您在 FXMLLoader 上调用 load 时,它将从 FXML 文件加载对象层次结构,并且还会创建一个控制器(在 FXML 文件中引用)。

2)Controller 中,您从 FXML 文件中注入 Label,但您重新创建了它。当 FXMLLoader 基于 fx:id 向您的控制器注入控件时,它还可以确保初始化。如果您创建一个新的 Label,它将不会指向加载程序创建的 Label 实例。

这个

@FXML private Label label=  new Label();

应替换为

@FXML private Label label;

这很简单...您可以通过在控制器 class 中为所需标签添加 getter 方法来更改 Main class 中的标签文本,并且然后使用控制器对象 (loader.getController()) 在 Main class 中获取它并更新其文本。或者使用 Main 中的控制器对象调用控制器 class 内的 setter 方法。 正如 DVagra 所说,使用 loader.getController() 获取控制器对象。 (其中 loader 是 FXMLLoader 的对象)。

此外,您不需要 Platform.runLater() 来更新 gui 控件。因为您已经 运行 在 FX 线程上了。

无论如何,这就是你需要的。

主要Class

package sample;
import javafx.application.Application;
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 Exception{
    FXMLLoader loader = new FXMLLoader();
    loader.setLocation(Main.class.getResource("sample.fxml"));
    Parent root = loader.load();
    primaryStage.setTitle("Hello World");
    primaryStage.setScene(new Scene(root, 300, 275));
    primaryStage.show();

    Controller controller = loader.getController();

    controller.setLabel("Test");
//  Or
//  controller.getLabel().setText("Test");
 }
public static void main(String[] args) {
    launch(args);
 }
}

控制器Class

package sample;
import javafx.fxml.FXML;
import javafx.fxml.Initializable;
import javafx.scene.control.Label;
import java.net.URL;
import java.util.ResourceBundle;

public class Controller implements Initializable{
@FXML
Label label;

//setter
public void setLabel(String labelText){
    label.setText(labelText);
}

//getter for label
public Label getLabel() {
    return label;
}

@Override
public void initialize(URL location, ResourceBundle resources) {
 }
}

Sample.fxml

<?xml version="1.0" encoding="UTF-8"?>
<?import javafx.scene.control.Label?>
<?import javafx.scene.layout.BorderPane?>

<BorderPane xmlns="http://javafx.com/javafx/8.0.60" 
xmlns:fx="http://javafx.com/fxml/1" fx:controller="sample.Controller">
<center>
    <Label fx:id="label" text="This" BorderPane.alignment="CENTER" />
</center>
</BorderPane>