Изменение текста метки из другого класса в JavaFX

Этот вопрос уже задавался здесь, но не смог найти любые ответы. Я воспроизвел аналогичную ситуацию, когда я хотел бы изменить текст метки из другого класса с помощью контроллера

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

}

FXMLDocument.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>

Демо5.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

Но изменений на этикетке не увидел. Я пропустил что-то важное здесь?


person Talat    schedule 18.05.2015    source источник
comment
Пожалуйста, ознакомьтесь с этим сообщением, чтобы узнать, как вы можете оживить вопрос без ответа.   -  person Rick Smith    schedule 18.05.2015


Ответы (3)


Вы можете изменить свой класс Connector, чтобы получить экземпляр Controller:

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

}

Примечание.

Если вашему соединителю потребуется больше времени для выполнения всего, что ему нужно, вы можете использовать задачу, чтобы не замораживать свой пользовательский интерфейс. Чтобы обновить метку, необходимо привязать свойство text, а затем обновить значение Text с помощью метода 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;
        }
    }

}
person henriqueor    schedule 18.05.2015
comment
Если мы предположим, что есть WebView вместо кнопки с запущенным Javascript, и я хотел бы вызвать FXMLDocumentController.setLabelText() через JS(‹div style='width: 100; height: 100; background: green;' + onclick ='javaObj.Connecting();' /›). В этом случае, как передать экземпляр FXMLDocumentController, чтобы изменения были видны на сцене? Я добавляю что-то подобное в слушатель WebEngine - JSObject win = (JSObject) webEngine.executeScript(window); win.setMember(javaObj, новый коннектор()); - person Talat; 19.05.2015

Ваш класс Demo5 и класс Connector создают уникальные экземпляры FXMLDocumentController посредством вызова FXMLLoader.load(). Экземпляр класса Demo5 помещается в граф сцены и становится видимым. Экземпляр в соединителе не отображается. Когда вы вызываете setLabelText(), он изменяет текст невидимой метки. Возможно, вы захотите получить экземпляр FXMLDocumentController в Demo5 и предоставить его классу Connector через конструктор или метод установки. Возможно, вам придется изменить некоторые вещи в зависимости от того, для чего используется класс Connector. В качестве альтернативы вы можете использовать класс соединителя для загрузки корня и контроллера FXML и предоставить методы для доступа к ним, а затем использовать эти методы в Demo5, чтобы сделать сцену видимой.

person OttPrime    schedule 18.05.2015

Я сделал это простым способом, определив метку как статическую в FXMLDocumentController.java:

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

и добавьте его в myGridPane в методе инициализации класса FXMLDocumentController:

@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);
person Emad N.    schedule 08.12.2016