Java Swing –ダイアログウィンドウを上に保つ
アプリケーションにダイアログを実装する最も一般的な(and simple)の方法は、JOptionPaneクラスです。 この記事では、ユーザーがJOptionPaneで作成されたボタンをクリックしたときにダイアログウィンドウを閉じるJOptionPaneのデフォルトの動作を「上書き」する方法について説明します。
例に進む前に知っておく必要があるのは、アプリケーションでJOptionPaneを使用する場合、実際に舞台裏で実行されるのはモーダルJDialogであるということです。 JOptionPaneは、JDialogを自動的に作成し、それ自体をcontent paneに追加するコンテナです。
1. 基本的な例
この例では、ダイアログウィンドウが自動的に閉じるのを停止し、代わりにPropertyChangeリスナーを実装して独自に処理します。 次の例は、ユーザーインタラクションや入力チェックの処理がないため、コードにこのメカニズムを実装する絶対的な基盤です。
KeepDialogUp.java
package com.techfou.stayup;
import java.beans.PropertyChangeEvent;
import java.beans.PropertyChangeListener;
import javax.swing.ImageIcon;
import javax.swing.JDialog;
import javax.swing.JFrame;
import javax.swing.JOptionPane;
public class KeepDialogUp {
public static void main(String[] args) {
JFrame frame = new JFrame();
ImageIcon icon = new ImageIcon("src/images/turtle64.png");
Object[] options = {"I DO LOVE TURTLES"};
JOptionPane jop = new JOptionPane("Admit your love for turtles\nor you shall not pass!!"
, JOptionPane.ERROR_MESSAGE, 0, icon, options, options[0]);
JDialog dialog = new JDialog(frame, "You LOVE turtles", true);
dialog.setDefaultCloseOperation(JDialog.DO_NOTHING_ON_CLOSE);
dialog.setContentPane(jop);
jop.addPropertyChangeListener(new PropertyChangeListener() {
@Override
public void propertyChange(PropertyChangeEvent evt) {
if (JOptionPane.VALUE_PROPERTY.equals(evt.getPropertyName())) {
dialog.dispose();
JOptionPane.showMessageDialog(null, "Good for you >:P");
System.exit(0);
}
}
});
dialog.pack();
dialog.setLocationRelativeTo(frame);
dialog.setVisible(true);
}
}
出力:

ユーザーがウィンドウを閉じようとしても、何も起こりません。 ユーザーが「I DO LOVE TURTLES」ボタンをクリックすると、プログラムは次のダイアログを表示して終了します。

2. リスナーを使用した例
さて、前の例をスパイスアップしましょう。 ユーザーがダイアログを閉じようとする試みを処理するためにwindowListenerを追加し、propertyChangeListenerでのユーザーの入力を確認します。
KeepDialogUpExtended.java
package com.techfou.stayup;
import java.awt.event.WindowAdapter;
import java.awt.event.WindowEvent;
import java.beans.PropertyChangeEvent;
import java.beans.PropertyChangeListener;
import javax.swing.ImageIcon;
import javax.swing.JDialog;
import javax.swing.JFrame;
import javax.swing.JOptionPane;
public class KeepDialogUpExtended {
public static void main(String[] args) {
JFrame frame = new JFrame();
ImageIcon icon = new ImageIcon("src/images/turtle64.png");
Object[] options = {"I DO LOVE TURTLES"};
JOptionPane jop = new JOptionPane("Admit your love for turtles\nor you shall not pass!!",
JOptionPane.ERROR_MESSAGE, 0, icon, options, options[0]);
JDialog dialog = new JDialog(frame, "You LOVE turtles", true);
dialog.setDefaultCloseOperation(JDialog.DO_NOTHING_ON_CLOSE);
dialog.setContentPane(jop);
dialog.addWindowListener(new WindowAdapter() {
public void windowClosing(WindowEvent evt) {
JOptionPane.showMessageDialog(frame, "YOU SHALL NOT PASS", "!!",
JOptionPane.ERROR_MESSAGE);
}
});
jop.addPropertyChangeListener(new PropertyChangeListener() {
@Override
public void propertyChange(PropertyChangeEvent evt) {
if (JOptionPane.VALUE_PROPERTY.equals(evt.getPropertyName())) {
if (jop.getValue().equals(options[0])) {
dialog.dispose();
JOptionPane.showMessageDialog(null, "Good for you >:P");
System.exit(0);
} else {
JOptionPane.showMessageDialog(frame, "There is no\n>> ESC <<",
"You little shenanigan...", JOptionPane.ERROR_MESSAGE);
}
}
}
});
dialog.pack();
dialog.setLocationRelativeTo(frame);
dialog.setVisible(true);
}
}
出力:

ユーザーがウィンドウを閉じようとした場合:

ユーザーがEscボタンを押した場合:

これは、このメカニズムをほぼまとめたものです。 JOptionPaneの戻り値をチェックする従来の方法でユーザー入力を処理する方が、リソースの効率が高いと主張する人もいるかもしれません。 多分そうでないかもしれません。コードの残りの部分によっては、このメカニックが欠落している可能性があります。 確かなことは、あなたが知っているほど正しい選択をする可能性が高くなるということです。