从Controller外部和应用程序类操作FXML节点

时间:2018-02-15 20:22:02

标签: java fxml

我需要操纵Controller类中的元素。但是,我设法找到的每个示例都通过扩展Application的类来进行此操作。

我需要在类Main中的VBoxSampleController中操作TextField inputText。

操纵如下:

inputText.setText(“TEST”);


期望的结果是一旦启动FXML应用程序,inputText TextField就预先填充了文本“TEST”。
我的困惑源于如何在任何地方操纵这个领域,但是:

  • VBoxSampleController
  • UIManager的

设置VBoxsampleController静态的行为,以便我可以使用类名访问它:

UIManager.vbsc.inputText.setText("TEST");

什么都不做。启动的FXML窗口中的元素不会更改。它仍然是空的。
此项目取自https://examples.javacodegeeks.com/desktop-java/javafx/javafx-applications-efxclipse/,因为我目前无法创建新的FXML应用程序。
感谢。

完整代码:

/* Main */
public class Main {
    public static void main(String[] args) {
        UIManager.main(args);
        // Does nothing
        // UIManager.vbsc.inputText.setText("TEST");
        // I want to change inputText here
    }
}


/* UIManager */
import javafx.application.Application;
import javafx.stage.Stage;
import javafx.scene.Scene;
import javafx.scene.layout.VBox;
import javafx.fxml.FXMLLoader;

public class UIManager extends Application {

    public static VBoxSampleController vbsc;

    public FXMLLoader loader;

    @Override
    public void start(Stage primaryStage) {
        try {
            loader = new FXMLLoader();
            loader.setLocation(Main.class.getResource("VBoxSample.fxml"));
            VBox root = loader.load();
            Scene scene = new Scene(root, 400, 400);
            primaryStage.setScene(scene);
            primaryStage.show();

            vbsc = loader.getController();
        } catch (Exception e) {
            e.printStackTrace();
        }
    }

    public static void main(String[] args) {
        launch(args);

    }

}


/* VBoxController */
import java.net.URL;
import java.util.ResourceBundle;

import javafx.fxml.FXML;
import javafx.scene.control.TabPane;
import javafx.scene.control.TextArea;
import javafx.scene.control.TextField;

public class VBoxSampleController {
    @FXML
    // The reference of inputText will be injected by the FXML loader
    public TextField inputText;
    // The reference of outputText will be injected by the FXML loader
    @FXML
    private TextArea outputText;

    // location and resources will be automatically injected by the FXML loader
    @FXML
    private URL location;

    @FXML
    private TabPane mainPane;

    @FXML
    private ResourceBundle resources;

    // Add a public no-args constructor
    public VBoxSampleController() {
    }

    @FXML
    private void initialize() {

    }

    @FXML
    private void printOutput() {
        outputText.setText(inputText.getText());
    }
}


<!-- FXML -->
<?xml version="1.0" encoding="UTF-8"?>

<?import javafx.scene.layout.VBox?>
<?import javafx.scene.control.Label?>
<?import javafx.scene.control.TextField?>
<?import javafx.scene.control.Button?>
<?import javafx.scene.control.TextArea?>

<VBox xmlns:fx="http://javafx.com/fxml/1" fx:controller="VBoxSampleController">
  <children>
    <Label alignment="CENTER_LEFT" cache="true" cacheHint="SCALE" prefHeight="30.0" prefWidth="200.0" text="Please insert Your Input here:" textAlignment="LEFT" />
    <TextField fx:id="inputText" prefWidth="100.0" />
    <Button alignment="CENTER_RIGHT" contentDisplay="CENTER" mnemonicParsing="false" onAction="#printOutput" text="OK" textAlignment="CENTER" />
    <Label alignment="CENTER_LEFT" cache="true" cacheHint="SCALE" prefHeight="30.0" prefWidth="200.0" text="Your Input:" textAlignment="LEFT" />
    <TextArea fx:id="outputText" prefHeight="100.0" prefWidth="200.0" wrapText="true" />
  </children>
</VBox>

3 个答案:

答案 0 :(得分:1)

我认为这是因为您试图从非静态方法修改静态变量:

@Override
public void start (Stage primaryStage) { // non-static method

    vbsc = loader.getController(); // vbsc is a static variable

}

如果我猜对了,您正在尝试在应用程序启动时动态更新 FXML 字段。所以你可以简单地通过使用控制器的 initialize() 方法来实现:

public class VBoxSampleController {

    @FXML                        // I suggest you to always keep class variable 
    private TextField inputText; // field private or non-public to prevent
                                 // unauthorized modifications

    ...

    @FXML
    public void initialize() {

        String text = "TEST"; // or any other at-runtime generated string
        inputText.setText(text);
    }

    ...

}

答案 1 :(得分:0)

public class Main extends Application {
//controllers
static HomeController homeController;
static StageController stageController;
//...
}

在HomeControllers类的初始化方法中写:

homeController = this;

并在StageController类的initialize方法中写:

StageController = this;

答案 2 :(得分:0)

您的问题似乎源于您在主线程而不是平台线程上进行更新。这里有两个问题。

  • 您应该始终在平台线程上进行 ui 更改。
  • 您正在启动方法之前执行 UIManager.vbsc.inputText.setText("TEST");

试试。

Platform.runLater( () -> UIManager.vbsc.inputText.setText("TEST") );