ガラス ペインを使用して、JFrame 内にモーダル ダイアログを作成しました。私の表示方法は非常に単純です。アルファ背景を持つガラス ペインとして JPanel を作成し、JLabel と [OK] ボタンと [閉じる] ボタンを追加します。次に、ガラス ペインが設定され、 で表示されますframe.getGlassPane().setVisible(true);
。
すべて正常に動作します。メソッドを呼び出すと、ペインが表示され、[OK] または [キャンセル] をクリックするとガラス ペインが非表示になります。ただし、このメソッドはガラス ペインを表示した直後に戻ります。しかし、メソッドのように動作するようにしたいJOptionPane
: ダイアログが閉じられるまでブロックします。
しかし、show メソッドの最後にビジー待機を挿入しようとするたびに、開くボタンをクリックすると GUI がフリーズします。私もメカニズムを取得しようとしましたJDialog#show()
が、それは私にとって少し複雑です。
では、ガラス ペインが表示されている間に show メソッドをブロックするにはどうすればよいでしょうか。
簡単な例を次に示します。
public class GlassPaneSSCE extends JPanel {
private JFrame parentFrame;
public GlassPaneSSCE(JFrame parent) {
parentFrame = parent;
addKeyListener(new KeyAdapter() {});
addMouseListener(new MouseAdapter() {});
setBackground(new Color(0, 0, 0, 100));
initGui();
}
@Override
protected void paintComponent(Graphics g) {
g.setColor(getBackground());
g.fillRect(0, 0, getWidth(), getHeight());
super.paintComponent(g);
}
private void initGui() {
setLayout(new FlowLayout(FlowLayout.CENTER));
setOpaque(false);
final JPanel content = new JPanel(new BorderLayout(4, 4));
content.setOpaque(true);
content.setBorder(new EmptyBorder(8, 8, 8, 8));
JLabel top = new JLabel("Title of this little modal dialog");
content.add(top, BorderLayout.NORTH);
JPanel inner = new JPanel(new BorderLayout());
content.add(inner, BorderLayout.CENTER);
inner.add(new JScrollPane(new JList(new String[] {
"Item 1 ",
"Item 2", "Item 3"
})));
Box ctrlButtons = Box.createHorizontalBox();
ctrlButtons.setBorder(new EmptyBorder(0, 4, 4, 4));
ctrlButtons.add(Box.createHorizontalGlue());
ctrlButtons.add(new JButton(new AbstractAction("OK") {
@Override
public void actionPerformed(ActionEvent e) {
parentFrame.getGlassPane().setVisible(false);
parentFrame.setGlassPane(new JPanel());
}
}));
content.add(ctrlButtons, BorderLayout.SOUTH);
add(content);
}
public void display() {
SwingUtilities.invokeLater(new Runnable() {
@Override
public void run() {
parentFrame.setGlassPane(GlassPaneSSCE.this);
parentFrame.getGlassPane().setVisible(true);
// Set the focus on the glass pane
requestFocus();
setFocusCycleRoot(true);
}
});
// The next line should be executed only if
// the ok button is clicked and not before
System.out.println("End of display()");
}
public static void main(String[] args) {
final JFrame f = new JFrame();
f.setLayout(new FlowLayout(FlowLayout.CENTER));
JTextArea tp = new JTextArea(10, 10);
for (int i = 0; i < 20; i++) {
JButton b = new JButton("Open");
b.addActionListener(new ActionListener() {
@Override
public void actionPerformed(ActionEvent e) {
GlassPaneSSCE gp = new GlassPaneSSCE(f);
gp.display();
}
});
f.add(b);
tp.append("Item " + (i+1) + "\n");
}
f.add(new JScrollPane(tp));
f.setSize(600, 600);
f.setVisible(true);
}
}