简体   繁体   English

出现在父级和子级JFrame / JDialog之间的新窗口

[英]New window appears sandwiched between parent and child JFrame/JDialog

New windows from other processes open behind a focused JDialog child but in front of the JDialog parent. 来自其他进程的新窗口将在重点突出的JDialog子级后面但在JDialog父级前面打开。 I would expect new windows to appear in front of the child. 我希望新窗口出现在孩子面前。 None of these windows are declared always on top. 这些窗口均未声明始终位于最上面。

Picture 图片

  • See that app 3 is between app 2 windows 看到应用程序3在应用程序2窗口之间
  • Does not matter that it is behind app 1 - always on top, this is expected 没关系,它位于应用1后面-始终位于最前面,这是预期的

应用程式2视窗之间3

Actual order 实际订单

JDialog (App 1 - always on top)
JFrame (App 2 non modal dialog child of app 2 main)
JDialog (App 3) <=== new window should appear on top of app 2
JFrame (App 2 - main window)

Expected order 预期订单

JDialog (App 1 - always on top)
JDialog (App 3) <=== new window should appear on top of app 2
JFrame (App 2 non modal dialog child of app 2 main)
JFrame (App 2 - main window)

This problem only happens if 此问题仅在以下情况下发生

  • there is an existing window from another process that is declared always-on-top, this doesn't have to be Java, I just used Java in the sample below - but issue also happens if you select always on top for say Firefox, gnome-terminal etc. 有一个来自另一个进程的现有窗口,该窗口被声明为永远在最上面,不必是Java,我只是在下面的示例中使用了Java-但是,如果您选择永远在最上面,例如Firefox,gnome,也会发生问题-终端等
  • The new window that is opened in a position that is behind the always on top application. 在始终位于顶部的应用程序后面的位置打开的新窗口。 Again, doesn't have to be Java application, repeated with Firefox, gnome-terminal. 同样,不必是Java应用程序,在gnome-terminal的Firefox中也可以重复使用。
  • Redhat Linux 6. Not repeatable on Ubuntu 16.04 or Windows 7 Redhat Linux6。在Ubuntu 16.04或Windows 7上不可重复

If the window is opened slightly to the right (change to newWindow.setBounds(**370**, 20, 0, 200) ) in the sample below, so that it is not behind the always on top window then it appears in front of child. 如果在下面的示例中该窗口稍微向右打开(更改为newWindow.setBounds(**370**, 20, 0, 200) ),则该窗口不在始终位于顶部的窗口后面,则它显示在前面的孩子。

3在2以上打开

To be clear, this problem occurs between three separate applications, however for simplicity I've recreated it below as a single Java application. 明确地说,此问题发生在三个单独的应用程序之间,但是为简单起见,我在下面将其重新创建为单个Java应用程序。

public class Combined {
    public static void main(String[] args) throws Exception {

        JFrame aot = new JFrame("App 1 - always on top");
        aot.setAlwaysOnTop(true);
        aot.setBounds(50, 50, 300, 40);
        aot.setVisible(true);

        JFrame frame = new JFrame("App 2 - main window");
        frame.setDefaultCloseOperation(WindowConstants.EXIT_ON_CLOSE);
        frame.setBounds(100, 100, 300, 200);
        frame.setVisible(true);

        JDialog child = new JDialog(frame, "App 2 - non-modal child dialog (child)");
        child.setBounds(150, 150, 300, 200);
        child.setVisible(true);

        Thread.sleep(1000);
        JFrame newWindow = new JFrame("App 3");
        newWindow.setDefaultCloseOperation(WindowConstants.EXIT_ON_CLOSE);

        newWindow.setBounds(200, 20, 300, 200);
        // newWindow.setBounds(370, 20, 300, 200);

        newWindow.setVisible(true);
    }
}

Is there any option that can be applied to the JDialog child such that it allows Windows appear above it. 是否可以将任何选项应用于JDialog子级,以便允许Windows显示在其上方。 The background is that I'm developing the "app 2" application, all the other parts and the Redhat Linux installation are all managed by other third-parties, so cannot be changed easily. 背景是我正在开发“ app 2”应用程序,所有其他部分和Redhat Linux安装都由其他第三方管理,因此不能轻易更改。

Tried using strict/smart window manager options, but no difference in behaviour 尝试使用严格/智能的窗口管理器选项,但行为没有差异

gconftool-2 --set /schemas/apps/metacity/general/focus_new_windows --type string smart
gconftool-2 --set /schemas/apps/metacity/general/focus_new_windows --type string strict

Hacky solutions 哈克解决方案

  • Show, hide and then show the App 3 window again. 显示,隐藏,然后再次显示App 3窗口。 In this case it appears above "App 2 child" correctly, although this causes a noticable flicker 在这种情况下,它会正确显示在“ App 2 child”上方,尽管这会引起明显的闪烁

Code

newWindow.setVisible(true);
newWindow.setVisible(false);
newWindow.setVisible(true);

In summary there are no nice solutions to this Linux windows management specific issue. 总之,对于此Linux Windows管理特定问题,没有好的解决方案。 All that can be done is to banish always-on-top windows from your application. 所有可以做的就是从应用程序中清除始终位于顶部的窗口。 This is best practice anyway, but difficult when dealing with legacy codebases. 无论如何,这都是最佳实践,但是在处理旧版代码库时却很难。

The only other solution of desparation is to do the setVisible() dance. 绝望的唯一其他解决方案是执行setVisible()舞蹈。

newWindow.setVisible(true);
newWindow.setVisible(false);
newWindow.setVisible(true);

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

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