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

发布于 2025-01-28 08:37:07 字数 1746 浏览 1 评论 0 原文

我正在创建一个 简单 Javafx程序。在 helloapplication 我想做逻辑,在 hellocontroller 我想收听按钮点击,然后在 HelloApplcation 中执行方法。

helloapplication.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();
        }
}

hellocontroller.java:

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

,但是我如何访问 helloapplication abound> abound> abound> pluench()上创建的对象? loader.getApplication()之类的东西将是完美的,而不是在控制器中创建新对象(无论如何都无法使用)。

现在,鼠标单击helloapp.startcounter()原因: java.lang.reflect.invocationTargetException

I'm creating a simple javaFX program. In HelloApplication I want to do the logic, and in HelloController I want to listen to button clicks which then execute methods inside the HelloApplcation.

HelloApplication.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();
        }
}

HelloController.java:

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

But how can I access HelloApplication object that was created on launch()?
Something like loader.getApplication() would be perfect instead of creating a new object in controller (which doesn't work anyway).

Right now, after mouse click the helloApp.StartCounter() causes:
java.lang.reflect.InvocationTargetException

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(1

清音悠歌 2025-02-04 08:37:08

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

直接回答您的问题。

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

这有点像单身模式,但是应用程序实例是由启动方法创建的。

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

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

AccessibleApp.getApplicationInstance()

示例代码和方法

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

    abougn() method的调用来创建。

    启动()方法只能为JVM进程调用一次。

  2. 在应用程序类中绝不应该有 @fxml 注释。

    @fxml 仅在控制器中使用,应用程序类也不应为控制器。

  3. 您的整体方法不正确:

    在Hellocontroller中,我想收听按钮点击,然后在HelloApplcation内部执行方法

    您不应该这样做。

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

建议的方法

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

  1. 编写一个具有用于计数器值和时间表的整数属性的计数类。
  2. 在班上提供开始和停止方法,请勿为此使用字符串状态。
  3. 在控制器中,创建一个计数器实例,然后在用户交互中启动并停止它。
  4. 在控制器初始化方法中,绑定显示字段文本< /a>到计数器值。

我建议您不必尝试调试和修复您的当前代码,而是建议您改用建议的方法。

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

How can I access the Application object in Controller?

To directly answer your question.

  1. Save the application instance to a static variable in the application init method.
  2. Provide a static accessor method to access it.

This is kind of like a singleton pattern, but the application instance is created by the launch method.

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

Then the application can be accessed from any class using:

AccessibleApp.getApplicationInstance()

Issues with your sample code and approach

  1. You should not create another application instance.

    The application lifecycle javadoc notes there should be only one application instance in the JVM and this will be created by the invocation of the launch() method.

    The launch() method can only be called once for the JVM process.

  2. There should never be an @FXML annotation in an Application class.

    @FXML is only used in a controller and the application class should not also be a controller.

  3. Your overall approach is incorrect:

    in HelloController I want to listen to button clicks which then execute methods inside the HelloApplcation

    You should not do this.

    The application class is responsible for the application lifecycle. Unless it is a trivial self-contained hello world style application, it should not be doing anything else. It definitely should not be servicing fxml controller callbacks.

Recommended Approach

Perform your application logic either directly in the controller or in a dedicated service class.

  1. Write a Counter class that has an integer property for the counter value and a timeline.
  2. Provide start and stop methods on the class, do not use a string status for that.
  3. In the controller create a Counter instance and start and stop it on user interaction.
  4. In the controller initialize method, bind the display field text to the counter value.

Rather than trying to debug and fix your current code, I recommend you work on implementing the suggested approach instead.

To understand such approaches more, see:

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文