简体   繁体   English

将所有阶段都带到前面

[英]Bring all Stages to the front

In my application, I have several independent (non modal) Stages. 在我的应用程序中,我有几个独立(非模态)阶段。

I would like the following behaviour: 我想要以下行为:

  • when the main Stage is minimised, all other Stages should be minimised 当主舞台最小化时,所有其他阶段应最小化
  • when the main Stage is un-minimised, all other Stages should be un-minimised 当主舞台未被最小化时,所有其他阶段应该是未最小化的
  • when any of the Stages is selected, if some other Stages are not visible (hidden behind other applications for example), they should be brought to the front 当选择任何阶段时,如果某些其他阶段不可见(例如隐藏在其他应用程序后面),则应将它们带到前面

The first two requirements are easy (unless I missed something), something like: 前两个要求很简单(除非我遗漏了一些东西),例如:

mainStage.iconifiedProperty().addListener((observable, oldValue, newValue) -> {
    if (newValue != null && newValue != oldValue) {
        for (Stage s : otherStages) { s.setIconified(newValue); }
    }
});

However I'm stuck on the third one. 但是我坚持第三个。 I have tried using the focusedProperty but it does not work (if I click on a menu in one of the stages, for example, because it first brings the other stages to the front, it loses focus and the menu does not open)... 我已经尝试使用focusedProperty但它不起作用(例如,如果我点击其中一个阶段的菜单,因为它首先将其他阶段带到前面,它会失去焦点而菜单无法打开).. 。

//do this for each stage
stage.focusedProperty().addListener((observable, oldValue, newValue) -> {
    if (Boolean.TRUE.equals(newValue) && newValue != oldValue) {
        for (Stage s : otherStages) {
            s.setIconified(false);
            s.toFront();
        }
        //request the focus back, but that creates issues
        stage.requestFocus();
    }
});

Any ideas on how to implement the third requirement? 关于如何实施第三项要求的任何想法?

Solution

Use stage.initOwner(parentStage) . 使用stage.initOwner(parentStage)

Sample App 示例应用程序

Here is quick test application which initializes the owners of all of the created stages to the primary application stage. 这是一个快速测试应用程序,它将所有创建阶段的所有者初始化为主应用程序阶段。

The test app seems to fulfill all of your requirements (tested on Windows 7, JavaFX 8b122). 测试应用程序似乎满足您的所有要求(在Windows 7,JavaFX 8b122上测试)。

import javafx.application.Application;
import javafx.scene.*;
import javafx.scene.paint.Color;
import javafx.scene.shape.Rectangle;
import javafx.stage.Stage;
import javafx.stage.StageStyle;

public class LotsaStages extends Application {
    private static final Color[] STAGE_COLORS = { 
        Color.RED, Color.GREEN, Color.BLUE, Color.YELLOW 
    };
    private static final double  STAGE_OFFSET = 50;

    @Override
    public void start(Stage primaryStage) throws Exception {
        addContent(primaryStage, Color.LIGHTBLUE);
        primaryStage.show();

        double offset = STAGE_OFFSET;
        for (Color color: STAGE_COLORS) {
            Stage child = new Stage();
            child.initOwner(primaryStage);
            child.initStyle(StageStyle.UTILITY);

            child.setX(primaryStage.getX() + offset);
            child.setY(primaryStage.getY() + offset);

            addContent(child, color);

            child.show();

            offset += STAGE_OFFSET;
        }
    }

    private void addContent(Stage child, Color color) {
        child.setScene(
            new Scene(
                new Group(
                    new Rectangle(150, 70, color)
                )
            )
        );
    }

    public static void main(String[] args) { launch(args); }
}

The test app is pretty simple and I didn't try to replicate your menu based issues, so I'm not sure if it will pass correctly for the menu based processing or other requirements you may have. 测试应用程序非常简单,我没有尝试复制基于菜单的问题,因此我不确定它是否会正确传递基于菜单的处理或您可能具有的其他要求。

Additional Questions 其他问题

So basically initOwner "links" the children to the main stage? 所以基本上initOwner将孩子们“链接”到主舞台?

Yes, MSDN explains how window ownage works on Windows . 是的, MSDN解释了Windows在Windows上的工作原理 Behaviour may differ slighty on other platforms (which is why the JavaFX Javadoc on the matter is deliberately vague), but I think most of the principles are the same and it should work on OS X and Linux is a similar manner. 在其他平台上行为可能略有不同(这就是JavaFX Javadoc在此问题上故意模糊的原因),但我认为大多数原则都是相同的,它应该适用于OS X和Linux的方式类似。

From MSDN: 来自MSDN:

To allow you to create a relationship between a child window and a parent window, Window supports the notion of ownership. 为了允许您在子窗口和父窗口之间创建关系,Window支持所有权的概念。 Ownership is established when the Owner property of a window (the owned window) is set with a reference to another window (the owner window). 当窗口的所有者属性(拥有的窗口)设置为引用另一个窗口(所有者窗口)时,建立所有权。

Once this relationship is established, the following behaviors are exhibited: 建立此关系后,将展示以下行为:

  • If an owner window is minimized, all its owned windows are minimized as well. 如果所有者窗口最小化,则其所有拥有的窗口也会最小化。
  • If an owned window is minimized, its owner is not minimized. 如果拥有的窗口最小化,则其所有者不会最小化。
  • If an owner window is maximized, both the owner window and its owned windows are restored. 如果所有者窗口最大化,则还原所有者窗口及其拥有的窗口。
  • An owner window can never cover an owned window. 所有者窗口永远不能覆盖拥有的窗口。
  • Owned windows that were not opened using ShowDialog are not modal. 使用ShowDialog未打开的拥有窗口不是模态的。 The user can still interact with the owner window. 用户仍然可以与所有者窗口进行交互。
  • If you close an owner window, its owned windows are also closed. 如果关闭所有者窗口,其拥有的窗口也将关闭。
  • If an owned window was opened by its owner window using Show, and the owner window is closed, the owned window's Closing event is not raised. 如果所有者窗口由其所有者窗口使用Show打开,并且所有者窗口关闭,则不会引发拥有窗口的Closing事件。

When you open a child window by calling ShowDialog, you should also set the Owner property of the child window. 通过调用ShowDialog打开子窗口时,还应设置子窗口的Owner属性。 If you don't, then your users won't be able to restore both child window and parent window by pressing the task bar button. 如果不这样做,那么您的用户将无法通过按任务栏按钮来恢复子窗口和父窗口。 Instead, pressing the task bar button will yield a list of windows, including both child and parent window, for them to select; 相反,按任务栏按钮将生成一个窗口列表,包括子窗口和父窗口,供他们选择; only the selected window is restored. 仅恢复选定的窗口。


Can that work with children such as child = new Stage(UNDECORATED); child.initModality(Modality.NONE); 这可以与孩子一起工作,如child = new Stage(UNDECORATED); child.initModality(Modality.NONE); child = new Stage(UNDECORATED); child.initModality(Modality.NONE); ?

Yes, it does. 是的,它确实。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM