2014-01-06 118 views
4

在我的应用程序中,我有几个独立的(非模态)阶段。将所有阶段带到前面

我想以下行为:

  • 主舞台最小化时,所有其他阶段应尽量减少
  • 当主舞台是未最小化,所有其他的各个阶段应取消最小化
  • 选择了任何的级的情况下,如果一些其它级是不可见的(隐藏在例如其他应用),它们应该被带到前面

的音响前两个要求是容易的(除非我错过了什么),是这样的:

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

但是我卡上的第三个。我尝试过使用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(); 
    } 
}); 

关于如何实现第三个要求的任何想法?

回答

6

解决方案

使用stage.initOwner(parentStage)

示例应用程序

这里是一个初始化所有创建阶段的业主初级应用阶段快速测试应用程序。

测试应用程序似乎满足您的所有要求(在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); } 
} 

测试应用程序是非常简单的,我没有尝试复制根据你的菜单的问题,所以我不知道是否会正确传递的基于菜单的处理,否则可能有其他的要求。

其他问题

所以基本上initOwner “链接” 孩子们的主要舞台?

是,MSDN explains how window ownage works on Windows。其他平台上的行为可能略有不同(这就是为什么JavaFX Javadoc在故意模糊的原因),但我认为大部分原则是相同的,它应该在OS X上运行,而Linux也是类似的方式。

从MSDN:

为了使您能够创建一个子窗口和父窗口之间的关系,窗口支持所有权的概念。当窗口的拥有者属性(拥有窗口)被设置为具有对另一个窗口(拥有者窗口)的引用时,所有权被建立。

一旦这种关系建立,以下行为都表现出:

  • 如果被最小化的所有者窗口,其拥有的所有窗口最小化也是如此。
  • 如果一个拥有的窗口被最小化,它的所有者不会被最小化。
  • 如果所有者窗口最大化,则所有者窗口及其拥有的窗口都将被恢复。
  • 拥有者窗口永远无法覆盖拥有的窗口。
  • 未使用ShowDialog打开的拥有窗口不是模态。用户仍然可以与所有者窗口进行交互。
  • 如果关闭所有者窗口,则其拥有的窗口也将关闭。
  • 如果一个拥有的窗口使用Show在其所有者窗口中打开,并且所有者窗口关闭,则不会引发拥有的窗口的Closing事件。

当您通过调用ShowDialog打开子窗口时,还应该设置子窗口的Owner属性。如果您不这样做,那么您的用户将无法通过按任务栏按钮来恢复子窗口和父窗口。相反,按任务栏按钮将产生一个窗口列表,包括子窗口和父窗口,供他们选择;只有选定的窗口被恢复。


可以与孩子如child = new Stage(UNDECORATED); child.initModality(Modality.NONE);工作?

是的,它的确如此。

+0

从甲骨文文档https://docs.oracle.com/javase/8/javafx/api/javafx/stage/Stage.html#initOwner-javafx.stage.Window- “A阶段可任选地有一个所有者窗口当一个窗口是一个阶段的所有者时,它被认为是该阶段的父代,当一个父窗口关闭时,所有的后代窗口都被关闭,同样的链式行为被应用于一个被图标化的父窗口。将始终位于其父窗口的顶部,所有者必须在舞台可见之前进行初始化。“ – Linuslabo