Warning: file_get_contents(/data/phpspider/zhask/data//catemap/9/java/376.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
JavaFX模态stage在MAC上的行为异常_Java_Javafx_Javafx 8 - Fatal编程技术网

JavaFX模态stage在MAC上的行为异常

JavaFX模态stage在MAC上的行为异常,java,javafx,javafx-8,Java,Javafx,Javafx 8,我有一个JavaFX应用程序,它有子窗口或阶段。我处理所有阶段如何相互交互的方式如下:在我的主类中有一个名为GuiContainer的静态类集合。GUI容器如下所示: public class GuiContainer { private final Stage stage; private final Scene scene; private final FXMLLoader loader; private final Controller controller

我有一个JavaFX应用程序,它有子窗口或阶段。我处理所有阶段如何相互交互的方式如下:在我的主类中有一个名为GuiContainer的静态类集合。GUI容器如下所示:

public class GuiContainer {
    private final Stage stage;
    private final Scene scene;
    private final FXMLLoader loader;
    private final Controller controller;
    private final Parent parent;

    public GuiContainer(Stage stage, Scene scene, FXMLLoader loader, Controller controller, Parent parent) {
        this.stage = stage;
        this.scene = scene;
        this.loader = loader;
        this.controller = controller;
        this.parent = parent;
    }

    public Stage getStage() {
        return stage;
    }

    public Scene getScene() {
        return scene;
    }

    public FXMLLoader getLoader() {
        return loader;
    }

    public Controller getController() {
        return controller;
    }

    public Parent getParent() {
        return parent;
    }

    public static final GuiContainer createMain(Stage stage, String title, int width, int height, String pathToView) throws Exception {
        FXMLLoader loaderInner = new FXMLLoader(GuiContainer.class.getResource(pathToView));

        Parent parentInner = loaderInner.load();
        final Controller controllerInner = loaderInner.getController();

        Scene sceneInner = new Scene(parentInner, width, height);

        stage.setTitle(title);
        stage.setScene(sceneInner);

        GuiContainer guiContainer = new GuiContainer(
                stage, sceneInner, loaderInner, controllerInner, parentInner
        );

        controllerInner.start(guiContainer);

        return guiContainer;
    }

    public static final GuiContainer createModal(Window owner, String title, int width, int height, String pathToView) throws Exception {
        if (owner == null) {
            Log.error(GuiContainer.class.getSimpleName(), "Unable to create instance, missing window owner!");
            return null;
        }

        Stage stageInner = new Stage();

        FXMLLoader loaderInner = new FXMLLoader(GuiContainer.class.getResource(pathToView));

        Parent parentInner = loaderInner.load();
        Controller controllerInner = loaderInner.getController();

        Scene sceneInner = new Scene(parentInner, width, height);

        stageInner.setTitle(title);
        stageInner.setScene(sceneInner);

        stageInner.initStyle(StageStyle.DECORATED);
        stageInner.initModality(Modality.WINDOW_MODAL);
        stageInner.initOwner(owner);

        GuiContainer guiContainer = new GuiContainer(
                stageInner, sceneInner, loaderInner, controllerInner, parentInner
        );

        controllerInner.start(guiContainer);

        return guiContainer;
    }
}
这样我就可以从任何地方访问任何舞台或控制器

所有可能的GUI容器在启动时只创建一次(在static main(String[]args)中),然后任何人都可以从任何地方静态访问

现在。。。在主应用程序(初级阶段内的场景)中,我有一个具有自定义单元格工厂的树视图,当右键单击单元格时,将显示相应的上下文菜单。在这个上下文菜单中,我打开了一个child/modal阶段,如下所示:

String containerName = "guiName";
GuiContainer container = Main.getGuiContainers().getOrDefault(containerName, null);
if(container == null) {
    Log.error(getClass().getSimpleName(), "Unable to find GuiContainer: " + containerName);
    return;
}

container.getStage().showAndWait();
现在,问题来了。JavaFX不要求关注子阶段。例如,我无法输入文本字段(在子阶段),因为我在主阶段注册了onKeyPressed事件,它捕获了我按下的所有键。在这个子阶段,我也有一个组合框,当我从该组合框中选择一个项目时,子阶段最终进入焦点,主阶段不再捕获我按下的键

我还尝试将模式更改为所有可能的值,并在oracle.com上阅读它们所做的操作,但没有任何信息对我有帮助

我的代码有问题吗?或者这可能是JavaFX的一个问题?有什么想法吗

编辑:这是我的应用程序覆盖启动方法:(我希望这能提供更多信息)

EDIT2:这是注册onKeyPressed侦听器的方式:(在父控制器init()方法中)

EDIT3:这就是我的抽象控制器类的样子-我希望这能提供更好的洞察力

public abstract class Controller {

    private GuiContainer guiContainer;

    public final GuiContainer getGuiContainer() {
        return guiContainer;
    }

    public final void start(GuiContainer guiContainer) {
        this.guiContainer = guiContainer;

        init();
    }

    public abstract void init(); // this is where the onKeyPressed is registered, when extending the abstract class

    public abstract void reset();

    public abstract void refresh();

}

重要编辑:这只发生在MAC平台上,我在windows上运行了相同的应用程序,没有此类问题。

你能发布你的舞台构造器的代码吗

只需一张便条,来自:

请注意,显示模态阶段并不一定会阻止调用者。 show()方法立即返回,而不考虑 舞台。如果需要阻止,请使用showAndWait()方法 调用者,直到模态阶段被隐藏(关闭)。这种方式必须是 在舞台可见之前初始化


编辑-我的错误,我没有注意到createModal()方法。 在我的一些定制阶段,我最终做的是:

    Platform.runLater(() -> somecontrol.requestFocus());
(显然,如果lambda在当前语言级别(<8)中不可用,java 8将重写run()方法)

但我只在非模态阶段这样做。模态阶段应自动聚焦

根据的文档,应用程序_MODAL应该执行您期望的操作(包括阻止其他窗口的事件):

APPLICATION_MODAL定义了一个模式窗口,用于阻止事件的发生 传递到任何其他应用程序窗口


在调用initOwner之前,使用WINDOW_MODAL调用initmodal。请参阅:

窗口\模态公共静态最终模态窗口\模态定义模态 阻止事件传递给其整个所有者的窗口 窗口层次结构。注:模态设置为WINDOW_模态的阶段,但 其所有者为空,被视为其模态设置为无


如果requestFocus()(在显示模式阶段之后调用,并且在UI线程中对吗?)没有获得焦点,我猜您的主窗口会自动将其取回

我首先初始化模态,然后使用showAndWait()方法。你说的阶段构造器是指控制器构造器?我不使用构造函数。我创建了一个start(parameters)方法(在某种程度上它取代了构造函数),您可以在GuiContainer类中看到它。另外,当我在启动时初始化所有GUI容器时,我不会显示它们。。。GuiContainer显示了启动阶段发生的一切。我对帖子进行了编辑,如果有帮助,我添加了我的开始方法。我还尝试使用您建议的代码,但没有成功,父阶段仍然捕获我的所有键。还尝试将模式更改为应用程序模式-仍然不起作用。您好,请参阅第二次编辑。requestFocus()应该为模式窗口提供焦点。如何在主窗口中收听关键事件?
public abstract class Controller {

    private GuiContainer guiContainer;

    public final GuiContainer getGuiContainer() {
        return guiContainer;
    }

    public final void start(GuiContainer guiContainer) {
        this.guiContainer = guiContainer;

        init();
    }

    public abstract void init(); // this is where the onKeyPressed is registered, when extending the abstract class

    public abstract void reset();

    public abstract void refresh();

}
    Platform.runLater(() -> somecontrol.requestFocus());