1

这个问题已经在这里问过,但找不到任何答案。我已经重现了类似的情况,我想使用控制器从另一个类更改标签的文本

FXMLDocumentController.java

public class FXMLDocumentController implements Initializable {

    @FXML
    private Label label;

    @FXML
    private void handleButtonAction(ActionEvent event) {
        System.out.println("FXMLDocumentController.#handleButtonAction");
        label.setText("Hello World!");
        Connector.Connecting();
    }

    @Override
    public void initialize(URL url, ResourceBundle rb) {
        // TODO
    }    

    public void setLabelText(String text)
    {
        System.out.println("FXMLDocumentController.setLabelText(): Called");
        label.setText(text);
    }

}

FXML文档.fxml

<AnchorPane id="AnchorPane" prefHeight="200" prefWidth="320" xmlns:fx="http://javafx.com/fxml/1" fx:controller="demo5.FXMLDocumentController">
    <children>
        <Button layoutX="126" layoutY="90" text="Click Me!" onAction="#handleButtonAction" fx:id="button" />
        <Label layoutX="126" layoutY="120" minHeight="16" minWidth="69" fx:id="label" />
    </children>
</AnchorPane>

Demo5.java

public class Demo5 extends Application {

    @Override
    public void start(Stage stage) throws Exception {
        Parent root = FXMLLoader.load(getClass().getResource("FXMLDocument.fxml"));

        Scene scene = new Scene(root);

        stage.setScene(scene);
        stage.show();
    }

    /**
     * @param args the command line arguments
     */
    public static void main(String[] args) {
        launch(args);
    }

}

连接器.java

public class Connector {
    public static void Connecting() {
        try {
            System.out.println("Connector.Connecting(): Called");

            FXMLLoader loader = new FXMLLoader(FXMLDocumentController.class.getResource("FXMLDocument.fxml"));
            loader.load();
            FXMLDocumentController controller = (FXMLDocumentController) loader.getController();

            controller.setLabelText("Bye World");
        } catch (IOException ex) {
            Logger.getLogger(Connector.class.getName()).log(Level.SEVERE, null, ex);
        }
    }
}

控制台输出

Connector.Connecting(): Called
FXMLDocumentController.setLabelText(): Called

但可以看到标签没有变化。我在这里错过了什么重要的东西吗?

4

3 回答 3

6

您可以更改连接器类以接收控制器实例:

public class Connector {
    public static void Connecting(FXMLDocumentController controller) {
        try {
            System.out.println("Connector.Connecting(): Called");
            controller.setLabelText("Bye World");
        } catch (IOException ex) {
            Logger.getLogger(Connector.class.getName()).log(Level.SEVERE, null, ex);
        }
    }
}


public class FXMLDocumentController implements Initializable {

    @FXML
    private Label label;

    @FXML
    private void handleButtonAction(ActionEvent event) {
        System.out.println("FXMLDocumentController.#handleButtonAction");
        label.setText("Hello World!");
        Connector.Connecting(this);
    }

    @Override
    public void initialize(URL url, ResourceBundle rb) {
        // TODO
    }    

    public void setLabelText(String text)
    {
        System.out.println("FXMLDocumentController.setLabelText(): Called");
        label.setText(text);
    }

}

笔记:

如果您的连接器需要更长的时间来执行它需要的任何操作,您可能想要使用任务,这样您就不会冻结您的 UI。要更新标签,您必须绑定文本属性,然后使用该updateMessage()方法更新文本值。

public class FXMLDocumentController implements Initializable {

    @FXML
    private Label label;

    @FXML
    private void handleButtonAction(ActionEvent event) {
        System.out.println("FXMLDocumentController.#handleButtonAction");
        label.setText("Hello World!");

        Task<Boolean> connectorTask = new ConnectorTask();
        label.textProperty().bind(connectorTask.messageProperty());
        connectorTask.setOnSucceeded(e -> {
            // this is going to be called if the task ends up without error
            label.textProperty().unbind();
        });
        new Thread(connectorTask).start();
    }

    @Override
    public void initialize(URL url, ResourceBundle rb) {
        // TODO
    }    

    //public void setLabelText(String text)
    //{
    //    System.out.println("FXMLDocumentController.setLabelText(): Called");
    //    label.setText(text);
    //}


    public class ConnectorTask extends Task<Boolean> {

        @Override
        protected Boolean call() throws Exception {
            // ... do whatever you need here

            // then you call this method to update the TextProperty from the Label that was bound.
            updateMessage("Bye World");

            return Boolean.TRUE;
        }
    }

}
于 2015-05-18T17:21:59.867 回答
1

您的 Demo5 类和 Connector 类都通过调用来创建 FXMLDocumentController 的唯一实例FXMLLoader.load()。Demo5 类中的实例被放置在场景图中并变得可见。连接器中的实例不可见。当您调用 setLabelText() 时,它正在更改看不见标签的文本。您可能想要做的是获取 Demo5 中的 FXMLDocumentController 实例,并通过构造函数或 setter 方法将其提供给 Connector 类。根据 Connector 类的用途,您可能需要更改一些内容。或者,您可以使用连接器类加载 FXML 根和控制器并提供访问它们的方法,然后使用 Demo5 中的这些方法使场景可见。

于 2015-05-18T16:55:42.530 回答
1

我通过在 FXMLDocumentController.java 中将 Label 定义为 static 以一种简单的方式实现了它:

@FXML GridPane myGridPane;
public static Label totLabel = new Label("Total"); 

并将其添加到 FXMLDocumentController 类的 initialize 方法中的 myGridPane 中:

@Override
public void initialize(URL url, ResourceBundle rb) {
    myGridPane.add(totLabel, 0, 3);
}

在任何其他类中,您可以像这样调用此标签的 setText():

String message = "this message will appear in the total label";//your string
FXMLDocumentController.totLabel.setText(message);
于 2016-12-08T18:30:37.273 回答