Swing中模式对话框的正确父级



我在Java 8u151/8u152中遇到了一个模式对话框错误,这在8u112中不是问题,我不确定我是在做一些固有的错误,还是JRE错误。据我所知,这只会影响Mac操作系统(我运行的是OS 10.12.6),所以尽管我的问题不是针对Mac的,但如果你不是Mac用户,你将无法观察到这个错误。

我创建了一个以主JFrame作为其父框架的模式对话框。然后,我创建了一个新的模态对话框,该对话框是从对话框#1创建的。将对话框#2的父级也设置为主JFrame是错误的吗?还是必须是对话#2?

另一种方式被问到:如果两个对话框共享同一个父级(主JFrame),但对话框#2是最后创建的,那么期望对话框#2位于顶部是否合理,或者行为是否未定义?

使用8u112时,对话框#2被聚焦并位于顶部。使用8u151时,对话#2是聚焦的,但在后面。如果我点击任何一个对话框,对话框#2都会抓住焦点,并且在大多数情况下表现得很好。然而,有时对话框#2会保留在其他应用程序的顶部(我相信如果我点击主窗口,然后回到模式对话框,就会发生这种情况……这部分肯定是一个错误)。

注意:对于Java 8u121到(我认为)8u144,模式对话框还有其他问题,这些问题本应在8u152中得到修复(几个月前我记录了一份错误报告,并检查了早期的访问构建,当时确实修复了)。

一些示例代码来说明我正在做什么:

import javax.swing.*;
import java.awt.*;
public class Main extends JFrame {
MyPanel panel;
public Main() {
setTitle("This is a frame");
setSize(300, 200);
panel = new MyPanel(this);
add(panel);
setLocationRelativeTo(null);
setDefaultCloseOperation(EXIT_ON_CLOSE);
}
public static void main(String[] args) {
EventQueue.invokeLater(() -> {
Main frame = new Main();
frame.pack();
frame.setVisible(true);
});
}
private static class MyPanel extends JPanel {
int dialogCounter = 1;
final JFrame theParent;
public MyPanel(JFrame parent) {
super();
theParent = parent;
setPreferredSize(new Dimension(300, 200));
JButton button = new JButton("Press the button");
button.addActionListener(e -> showDialog(theParent));
add(button);
}
private void showDialog(Frame parent) {
JDialog dialog = new JDialog(parent, "This is dialog " + dialogCounter, true);
setupDialog(dialog);
}
private void setupDialog(JDialog dialog) {
JPanel dialogPanel = new JPanel();
dialogPanel.setPreferredSize(new Dimension(300, 200));
dialogPanel.add(new JLabel("Current dialog count: " + dialogCounter++));
JButton button = new JButton("Open a new modal dialog");
button.addActionListener(e -> showDialog(theParent));
dialogPanel.add(button);
dialog.add(dialogPanel);
dialog.pack();
dialog.setVisible(true);
}
}
}

这是8u151中引入的一个错误。它已经被修复,应该被后移植到下一个OpenJDK8更新版本。以下是您可以使用的解决方法:

dialog.addWindowListener(new WindowAdapter() {
@Override
public void windowOpened(WindowEvent e) {
dialog.removeWindowListener(this);
dialog.toFront();
}
});

最新更新