JavaFX 如何访问控制器中的应用程序对象?

Rek*_*eft 0 java javafx

我正在创建一个简单的javaFX 程序。我HelloApplication想要执行逻辑,并且HelloController我想要监听按钮单击,然后执行HelloApplcation.

你好应用程序.java:

Timeline timeline;
@FXML
HelloController HC;
FXMLLoader fxmlLoader;
private int counter=0;
public void start(Stage stage) throws IOException {
        fxmlLoader = new FXMLLoader(HelloApplication.class.getResource("hello-view.fxml"));

        Scene scene = new Scene(fxmlLoader.load(), 640, 480);
        stage.setTitle("Program!");
        stage.setScene(scene);
        stage.show();
        StartCounter("start");
}
public void StartCounter(String status)
    {
        HC = fxmlLoader.getController();
        if(timeline==null) {
            timeline = new Timeline(new KeyFrame(Duration.seconds(1), ev -> {
                HC.getCmd().setText(String.valueOf(counter));
                counter++;
            }));
            timeline.setCycleCount(Animation.INDEFINITE);
        }else{
            if(status=="stop")
                timeline.stop();
            else if(status=="start")
                timeline.play();
        }
}
Run Code Online (Sandbox Code Playgroud)

你好控制器.java:

  HelloApplication helloApp=new HelloApplication(); //this creates another instance...
 @FXML
    protected void onHelloButtonClick() {
        helloApp.StartCounter("stop");
    }
Run Code Online (Sandbox Code Playgroud)

但是我如何访问在 上创建的HelloApplicationlaunch()对象?像这样的东西loader.getApplication()将是完美的,而不是在控制器中创建一个新对象(无论如何它都不起作用)。

现在,鼠标单击后 helloApp.StartCounter() 会导致: java.lang.reflect.InitationTargetException

jew*_*sea 6

如何访问控制器中的应用程序对象?

直接回答你的问题。

  1. 将应用程序实例保存到应用程序方法中的静态变量中init
  2. 提供静态访问器方法来访问它。

这有点像单例模式,但应用程序实例是通过该launch方法创建的。

public class AccessibleApp extends Application {
    private static AccessibleApp applicationInstance;

    public static AccessibleApp getApplicationInstance() {
        return applicationInstance;
    }

    @Override
    public void init() {
        applicationInstance = this;
    }

    // other app functionality ...

    public static void main(String[] args) {
        launch(args);
    }
}
Run Code Online (Sandbox Code Playgroud)

然后可以使用以下命令从任何类访问该应用程序:

AccessibleApp.getApplicationInstance()
Run Code Online (Sandbox Code Playgroud)

您的示例代码和方法存在问题

  1. 您不应该创建另一个应用程序实例。

    应用程序生命周期javadoc 指出 JVM 中应该只有一个应用程序实例,并且该实例将通过调用该launch()方法来创建。

    launch()方法对于 JVM 进程只能调用一次。

  2. @FXMLApplication 类中不应该有注释。

    @FXML仅在控制器中使用,并且应用程序类不应该也是控制器。

  3. 您的总体方法是不正确的:

    在 HelloController 中,我想监听按钮点击,然后执行 HelloApplcation 内的方法

    你不应该这样做。

    应用程序类负责应用程序的生命周期。除非它是一个简单的独立的 hello world 风格的应用程序,否则它不应该做任何其他事情。它绝对不应该为 fxml 控制器回调提供服务。

推荐方法

直接在控制器中或在专用服务类中执行应用程序逻辑。

  1. 编写一个 Counter 类,该类具有计数器值的整数属性和时间线。
  2. 在类上提供启动和停止方法,不要为此使用字符串状态。
  3. 在控制器中创建一个 Counter 实例并在用户交互时启动和停止它。
  4. 在控制器初始化方法中,将显示字段文本绑定到计数器值。

我建议您不要尝试调试和修复当前的代码,而是致力于实施建议的方法。

要更多地了解此类方法,请参阅: