当具有相同的所有者时,Swing multiple始终在顶部对话框上不能独立工作

时间:2015-12-24 09:57:27

标签: java swing always-on-top

我们有一个请求,根据某些控件,某些对话框应始终位于顶部。必须在每个对话框的基础上打开/关闭它。 在我看来,使用以下代码并执行以下步骤就像Java错误一样:

  1. 将dialog1设置在顶部。检查它是否保持在最顶层。
  2. 将dialog2设置在顶部。检查两个对话框是否保持最佳状态。
  3. 将dialog1设置为不在顶部。
  4. 预期:dialog2保持在最顶层,dialog1不在

    实际:没有任何对话框保留在最顶层。

    这与对话框的所有者有一些联系。如果取消注释块注释,一切都按预期工作,但我认为这不是正常行为,因为Always on Top不应该连接到父级。这是正常的还是Swing的问题?不幸的是,为每个对话框设置新的所有者会引入其他问题。

    public static void main(String[] args) {
        final JFrame rahan = new JFrame("Rahan");
        rahan.setSize(new Dimension(1000,1000));
        rahan.setVisible(true);
    
    
        JDialog d1 = getJDialog(/*new JFrame()*/);
        JDialog d2 = getJDialog(/*new JFrame()*/);
    }
    
    private static JDialog getJDialog(/*JFrame owner*/) {
        final JDialog jDialog = new JDialog(/*owner*/);
        final JButton onTop = new JButton("OnTop");
        onTop.addActionListener(new ActionListener() {
            @Override
            public void actionPerformed(ActionEvent e) {
                jDialog.setAlwaysOnTop(!jDialog.isAlwaysOnTop());
            }
        });
        jDialog.add(onTop);
        jDialog.setVisible(true);
        jDialog.pack();
        return jDialog;
    }
    

3 个答案:

答案 0 :(得分:1)

如果我像这样运行您的应用程序:

public static void main(String[] args) {
    final JFrame rahan = new JFrame("Rahan");
    rahan.setSize(new Dimension(1000,1000));
    rahan.setVisible(true);


    JDialog d1 = getJDialog(rahan);
    JDialog d2 = getJDialog(rahan);
}

    private static JDialog getJDialog(JFrame owner) {
        final JDialog jDialog = new JDialog(owner);
        final JButton onTop = new JButton("OnTop");
        onTop.addActionListener(new ActionListener() {

            @Override
            public void actionPerformed(java.awt.event.ActionEvent e) {
                 jDialog.setAlwaysOnTop(!jDialog.isAlwaysOnTop());       
            }
        });
        jDialog.add(onTop);
        jDialog.setVisible(true);
        jDialog.pack();
        return jDialog;
    }

    }

完美无缺。这两个对话框始终位于顶部,并且它不是模态的,因此您可以单击该框架。

您可以尝试将对话框设置为模态,如下所示:

jDialog.setModal(true);

但这与你正在实现的目标背道而驰?

答案 1 :(得分:1)

查看setAlwaysOnTop的代码,将这些代码直接发送到窗口对等体,因此这可能是依赖于操作系统的问题。

其次,您是否尝试在事件派发线程上进行所有创建?在此问题的前一篇文章中提出了这一点。

JDialog.setAlwaysOnTop(true) brings all dialogs to the front under Windows

答案 2 :(得分:1)

不确定此问题是否仍然相关,但我发现了该问题的潜在解决方法。如果您保留每次创建新窗口时所添加的所有可能“永远在线”的窗口的列表,您可以返回并关闭它们然后再打开以将它们放回原位。 / p>

ArrayList<Window> = new ArrayList<Window>();
.
.
.
void createWindow() {
    Window w = new Window();
    windowList.add(w);
}

然后,当其中一个窗口的“Always on Top”按钮关闭时,您将返回到windowList并切换所有设置为始终位于顶部的窗口。以下内容应该在动作监听器的actionPerformed函数中切换“Always on Top”:

if (!windowAlwaysOnTopButton.isSelected()) {
    ArrayList<Window> turnedOff = new ArrayList<Window>();
    for (Window w : windowList) {
        if (w.isAlwaysOnTop()) {
            w.setAlwaysOnTop(false);
            turnedOff.add(w);
        } 
    } 
    for (Window w : turnedOff) {
        w.setAlwaysOnTop(true);
    } 
}

你需要两个for循环和turnOff列表,因为如果你在同一个循环中再关闭然后再打开,你会遇到原始问题,如果Windows A和B总是在顶部,那么Window A被关闭,Window B也将关闭。这就是为什么你需要将它们全部关闭,然后再次循环以重新打开它们。我意识到这可能是一个hackey解决方案,但如果它对我有用,它可能只对你有用。干杯!