当前位置: 首页 > 知识库问答 >
问题:

JavaFX应用程序:.start()中的主要阶段有什么特殊之处吗?

楚浩然
2023-03-14

这是基本的fxml文件:

<BorderPane maxHeight="-Infinity" maxWidth="-Infinity" minHeight="-Infinity"
    minWidth="-Infinity" prefHeight="600.0" prefWidth="800.0"
    xmlns="http://javafx.com/javafx/8" xmlns:fx="http://javafx.com/fxml/1"
    fx:controller="com.github.parboiled1.grappa.debugger.basewindow.BaseWindowUi">
    <top>
        <MenuBar BorderPane.alignment="CENTER">
            <Menu mnemonicParsing="false" text="File">
                <MenuItem mnemonicParsing="false"
                    text="New window" onAction="#newWindowEvent"/>
                <MenuItem mnemonicParsing="false"
                    text="Close" onAction="#closeWindowEvent"/>
            </Menu>
        </MenuBar>
    </top>
    <center>
        <Label text="Hello"/>
    </center>
</BorderPane>

BaseWindowUI类非常简单:

public class BaseWindowUi
{
    private BaseWindowPresenter presenter;

    public void init(final BaseWindowPresenter presenter)
    {
        this.presenter = presenter;
    }

    @FXML
    void newWindowEvent(final ActionEvent event)
    {
        presenter.handleNewWindow();
    }

    @FXML
    public void closeWindowEvent(final ActionEvent event)
    {
        presenter.handleCloseWindow();
    }
}

演讲者也是:

public final class BaseWindowPresenter
{
    private final BaseWindowFactory windowFactory;

    public BaseWindowPresenter(final BaseWindowFactory windowFactory)
    {
        this.windowFactory = windowFactory;
    }

    public void handleCloseWindow()
    {
        windowFactory.close(this);
    }

    public void handleNewWindow()
    {
        windowFactory.createWindow();
    }
}
// Interface...
public interface BaseWindowFactory
{
    void createWindow(Stage stage);

    default void createWindow()
    {
        createWindow(new Stage());
    }

    void close(BaseWindowPresenter presenter);
}

// Implementation...
public final class DefaultBaseWindowFactory
    implements BaseWindowFactory
{
    private static final AlertFactory ALERT_FACTORY = new AlertFactory();
    private static final URL MAIN_WINDOW_FXML;

    static {
        try {
            MAIN_WINDOW_FXML = DefaultBaseWindowFactory.class.getResource(
                "/baseWindow.fxml");
            if (MAIN_WINDOW_FXML == null)
                throw new IOException("base window fxml not found");
        } catch (IOException e) {
            ALERT_FACTORY.showError("Fatal error", "cannot load base FXML", e);
            throw new ExceptionInInitializerError(e);
        }
    }

    private final Map<BaseWindowPresenter, Stage> windows
        = new HashMap<>();

    private final AtomicInteger windowCount = new AtomicInteger();

    @Override
    public void createWindow(final Stage stage)
    {
        final FXMLLoader loader = new FXMLLoader(MAIN_WINDOW_FXML);
        final Pane pane;
        try {
            pane = loader.load();
        } catch (IOException e) {
            ALERT_FACTORY.showError("Fatal error", "unable to create window",
                e);
            return;
        }

        final BaseWindowPresenter presenter = new BaseWindowPresenter(this);

        final BaseWindowUi ui = loader.getController();
        ui.init(presenter);

        stage.setScene(new Scene(pane));
        stage.setTitle("window " + windowCount.getAndIncrement());

        windows.put(presenter, stage);

        stage.show();
    }

    @Override
    public void close(final BaseWindowPresenter presenter)
    {
        windows.get(presenter).close();
    }
}
public final class TestApp
    extends Application
{
    private final BaseWindowFactory factory = new DefaultBaseWindowFactory();

    @Override
    public void start(final Stage primaryStage)
        throws Exception
    {
        factory.createWindow(primaryStage);
    }

    public static void main(final String... args)
    {
        launch(args);
    }
}

共有1个答案

虞修平
2023-03-14

初级阶段

primaryStage唯一的特殊之处在于(与任何其他阶段不同),它是由JavaFX系统创建的,而不是由应用程序创建的。但除此之外,初级阶段的行为与其他阶段一样。

有一个与应用程序生命周期相关的阶段相关规则:

    null
    null

您提供的代码没有引入任何新的线程,它只是使用JavaFX系统传递给它的线程(JavaFX应用程序线程)。因此,所提供的代码永远不会违反上述规则(正如Vitomir在他的评论中指出的那样)。

您的DefaultBaseWindowFactory createWindow方法应该只在JavaFX应用程序线程上运行,因此您不需要并发实用程序(如AtomicInteger)来封装窗口的数量,一个简单的整数就足够了,因为只有一个线程在JavaFX应用程序线程上操作读写该值。

如果您引入了创建新线程的新代码(您编写的代码或从库中生成的代码),那么请注意这些代码不要修改活动场景图中的对象,也不要试图直接从另一个线程创建窗口(如果有疑问,您可以通过system.out.println(thread.getname())轻松地检查正在执行的线程。如果您最终使用了一些多线程代码,请使用platform.runlater()包装对操作SceneGraph中的节点或创建新窗口的函数的调用,或者使用JavaFX并发实用程序来管理并发服务。

 类似资料:
  • 我有一个小型Java桌面应用程序,没有任何图形用户界面。我使用蚂蚁来开发、运行、构建和发布它。我没有为它创建一个jar文件。我使用一个. sh文件来启动/运行它,并在发行版中附加JRE。 现在我在上面添加了一个简单的JavaFX2GUI。我仍然可以用Ant开发、运行、构建和发布。JavaFX的Ant文件中没有特殊的目标或添加。发布后,我无法再使用现有的.sh文件运行它。我收到以下错误: 线程"ma

  • 问题内容: 我想在关闭JavaFX应用程序之前保存文件。 这就是我在中设置处理程序的方式: 当按下按钮时,控制器将调用: 如果关闭窗口,请单击窗口边框上的红色X(正常方式),然后会收到输出消息“ ”,这是所需的行为。 但是,在调用应用程序时,它会在不调用处理程序的情况下关闭(没有输出)。 如何使控制器使用添加到的处理程序? 问题答案: 如果你看一下在生命周期中的类: 每当启动应用程序时,JavaF

  • 我想在关闭JavaFX应用程序之前保存一个文件。 这就是我在中设置处理程序的方法: 以及当按下按钮时调用的控制器: 如何使控制器使用我添加到中的处理程序?

  • 我在JavaFX中有一个阶段,可以通过多种方式关闭,通过单击红色(X)或通过调用的按钮 无论舞台如何关闭,我都想在舞台关闭之前(或关闭时)执行一个动作。 如果我使用以下代码: 然后,当我单击(X)时调用处理程序,但当我调用<code>myStage.close()</code>时不会调用 这与这个问题讨论的问题相同(有一个关键区别):JavaFX:Stage-close-handler 不同之处在

  • 我想在javafx中从CLI控制台创建尽可能多的阶段,所有这些阶段都是相互独立的。我知道只能有一个应用程序实例,这就是为什么我这样做: 我在屏幕上只看到,并且没有调用SomeStage的构造函数。

  • javafx中的stage只需要一个场景,而场景只需要一个根节点<所以我想知道这个场景的主要角色是什么?这似乎是一个场景连接了两个侧面,可以直接连接,而无需中间层<我只想理解其中的逻辑。非常感谢。