【发布时间】:2015-03-14 06:12:15
【问题描述】:
这是基本的 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();
}
}
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();
}
}
最后,这是实现Application的类:
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);
}
}
所有这些工作;我可以打开新窗口,关闭从“初级阶段”创建的窗口,关闭所有窗口时应用程序正确退出等等。
那么,初级阶段有什么特别之处呢?
更重要的是,Application 的文档是这样说的:
JavaFX 创建一个应用程序线程,用于运行应用程序启动方法、处理输入事件和运行动画时间轴。 JavaFX 场景和舞台对象的创建以及将场景图操作修改为活动对象(那些已经附加到场景的对象)必须在 JavaFX 应用程序线程上完成。
我的代码目前可以工作,但它几乎什么也没做;我最终不会遇到应该在应用程序线程中运行但没有运行的代码问题吗?所有new Stage()s 都自动知道应用程序线程吗?
【问题讨论】:
-
您的具体问题是什么?请编辑标题以包含问题并编辑您的问题以清楚地询问您需要知道的内容。当我无法完全理解您不理解的内容时,要帮助您理解某些内容有点困难。为什么你认为初级阶段很特别?为什么你认为这段代码会遇到线程问题?为什么使用 AtomicInteger 进行窗口计数?你要求什么规则?
-
@jewelsea 问题已编辑;问题是,我什至不知道完全正确地表达我的问题......
-
您的应用程序不会创建任何额外的线程。这意味着一切都已经是应用程序线程的一部分,无需担心线程。