我们收到一个请求,要求一些对话框始终位于基于某些控件的顶部。这必须在每个对话框的基础上打开/关闭。在我看来,使用以下代码并完成以下步骤就像一个Java错误:
- 将dialog1设置在顶部。检查它是否保持在顶部
- 将dialog2设置在顶部。检查两个对话框是否保持在顶部
- 将dialog1设置为不在顶部
预期:对话2保持在顶部,对话1没有
实际:没有一个对话框保持在顶部。
这与对话框的所有者有某种联系。如果取消对块注释的注释,一切都会按预期进行,但我认为这不是正常行为,因为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;
}
如果我这样运行您的应用程序:
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);
但这有点违背了你正在实现的目标,对吧?
查看setAlwaysOnTop
的代码,这些代码被直接调度到窗口对等端,因此这可能是一个依赖于操作系统的问题。
其次,您是否尝试过在事件调度线程上进行所有创建?这是在之前关于这个问题的帖子中提出的。
JDialog.setAlwaysOnTop(true)将Windows 下的所有对话框置于最前面
不确定这个问题是否仍然相关,但我找到了解决这个问题的潜在方法。如果你保留了一个列表,列出了每次创建新窗口时添加到的所有潜在的"始终在顶部"窗口,你可以返回并关闭它们,然后再次打开,将它们重新放回顶部。
ArrayList<Window> = new ArrayList<Window>();
.
.
.
void createWindow() {
Window w = new Window();
windowList.add(w);
}
然后,当窗口的"始终在顶部"按钮之一关闭时,您将返回到窗口列表并切换所有设置为始终在顶部的按钮。以下内容应该在动作侦听器中的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循环和turnedOff列表,因为如果你在同一个循环中关闭每一个,然后再打开,你会遇到最初的问题,如果Windows A和B总是在顶部,那么窗口A被关闭,窗口B也会被关闭。这就是为什么你需要将它们全部关闭,然后再次循环打开。我意识到这可能是一个很好的解决方案,但如果它对我有效,可能只对你有效。干杯