JavaFX应用程序:.start()中的初级阶段有什么特殊之处吗?
这是基本fxml文件:JavaFX应用程序:.start()中的初级阶段有什么特殊之处吗?,java,javafx,javafx-8,Java,Javafx,Javafx 8,这是基本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="co
<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>
演讲者也是如此:
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();
}
}
BaseWindowFactory
是一个只有一个具体实现的接口:
// 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();
}
}
所有这些工作;我可以打开新窗口,关闭从“主阶段”创建的窗口,当所有窗口关闭时应用程序正确退出,等等
那么,初级阶段有什么特别之处呢
此外,应用程序
的文档说明:
JavaFX创建一个应用程序线程,用于运行应用程序启动方法、处理输入事件和运行动画时间线。必须在JavaFX应用程序线程上创建JavaFX场景和舞台对象,以及修改场景图操作以激活对象(已附加到场景的对象)
我的代码目前可以工作,但几乎什么都不做;我是否最终会遇到应该在应用程序线程中运行但不在应用程序线程中运行的代码的问题?所有new Stage()
s是否都自动识别应用程序线程?主阶段
primaryStage的唯一特殊之处在于(与其他任何阶段不同),它是由JavaFX系统创建的,而不是由应用程序创建的。但除此之外,初级阶段的行为与其他阶段类似
有一项与阶段相关的规则,涉及:
- 等待应用程序完成,发生以下任一情况时会发生这种情况:
- 应用程序调用
或Platform.exit()
- 最后一个窗口已关闭,
上的Platform
属性为trueimplicitExit
- 应用程序调用
- 必须在JavaFX应用程序线程上创建JavaFX场景和舞台对象,以及修改场景图操作以激活对象(已附加到场景的对象)
System.out.println(thread.getName()
)轻松检查正在执行的线程。如果您最终得到了一些多线程代码,请使用来包装对操作场景图中节点或创建新窗口的函数的任何调用,或者使用来管理并发服务。实际上有一个(重要的非明显的)区别:用户可以通过单击窗口装饰中的最小化按钮来最小化主阶段。对于其他阶段,窗口最小化按钮被禁用。我们必须以不同的方式设计我们的应用程序来解释这一点
使用Java 1.8.0_121进行测试。您的确切问题是什么?请编辑标题以包含问题,并编辑您的问题以清楚地询问您需要知道的内容。当我无法准确理解您不理解的内容时,帮助您理解某些内容有点困难。为什么您认为初级阶段很特别?为什么您认为初级阶段很特别代码是否会遇到线程问题?为什么要使用AtomicInteger进行窗口计数?您需要什么规则?@jewelsea问题已编辑;问题是,我甚至不知道如何完全正确地表达我的问题…您的应用程序不会创建任何附加线程。这意味着所有内容都已经是应用程序线程的一部分,并且不需要担心线程。初级阶段有些特殊,尽管可能不是问题所问的方式。它不能有所有者,不能设置其模态,也不能用
showAndWait()显示
。请注意,只有当后台或后台将要运行时,这才是正确的。至少,这是使用JavaFX14的Windows 10上的行为。
// 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);
}
}