今回珍しく Applet(Swing) + RMI の仕事でした。 Swing 自体は専門的によく知っているわけではないですが、 以前の仕事でも暗号化ツールを Swing で試作してみたりなど、 普段からよく使っているので何の抵抗もなく利用できました。 …なのですが、1つだけ「何でこうなってんの?」とつまったのが表題の件です。
例えば普通にダイアログを作成すると、下の図のようになります。
import java.awt.Container; import java.awt.Dimension; import java.awt.Font; import java.awt.event.ActionEvent; import java.awt.event.ActionListener; import javax.swing.ImageIcon; import javax.swing.JButton; import javax.swing.JDialog; import javax.swing.JFrame; import javax.swing.JLabel; import javax.swing.SwingConstants; import javax.swing.UIManager; public class DialogIconTest extends JFrame { static Font font = new Font("SansSerif", Font.PLAIN, 12); final JButton button; public void openDialog() { final JDialog dialog = new JDialog(this, "テスト用ダイアログ"); Container pane = dialog.getContentPane(); JLabel label = new JLabel(); label.setText("テスト用のダイアログです。"); label.setFont(font); label.setPreferredSize(new Dimension(240, 120)); label.setHorizontalAlignment(SwingConstants.CENTER); pane.add(label); dialog.setBounds(14, 14, 240, 120); dialog.pack(); dialog.setVisible(true); } public DialogIconTest() { super("テスト用JFrame"); Container pane = getContentPane(); // ダイアログを開くボタン button = new JButton(); button.addActionListener(new ActionListener() { public void actionPerformed(ActionEvent e) { openDialog(); } }); button.setText("open dialog"); button.setFont(font); pane.add(button); setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); pack(); setBounds(0, 0, 240, 120); } public static void main(String[] args) { try { UIManager .setLookAndFeel( "com.sun.java.swing.plaf.windows.WindowsLookAndFeel"); } catch (Exception e) { e.printStackTrace(); } JFrame frame = new DialogIconTest(); frame.setVisible(true); } }
ダイアログのアイコンを消したかったので、少し調べてみたところ、こうすると消えました。
...(前略)... public void openDialog() { final JDialog dialog = new JDialog(this, "テスト用ダイアログ"); Container pane = dialog.getContentPane(); JLabel label = new JLabel(); label.setText("テスト用のダイアログです。"); label.setFont(font); label.setPreferredSize(new Dimension(240, 120)); label.setHorizontalAlignment(SwingConstants.CENTER); pane.add(label); dialog.setResizable(false); // ←ここ dialog.setBounds(14, 14, 240, 120); dialog.pack(); dialog.setVisible(true); } ...(後略)...
アイコンは消えるのですが…かなり疑問のある動作です。 あくまで「サイズ変更不可にする」と指定しているのに、 アイコンまで消えてしまう…。
Sun Microsystems の Bug Parade を閲覧すると、やはり同じように 「こんな副作用的な動作は変なんじゃないの?」 と指摘している人がいました。私もそう思うのですが、このようになっている理由は「 Windows では “resizable dialogs have an icon, not-resizable dialogs don’t” と推奨してあるから」だそうです。
たしかに他のプラットフォームと比べてみても、ウィンドウのタイトルバーにアイコンを表示するのは Windows だけなんですね。しかしだからと言って
- デフォルトのアイコンイメージが Java Cup になっている
- あえてアイコン指定を null にすると、やはり Java Cup になる
- Windows だけしか使わないような API は用意しない
ちなみに上述の Forum では 「アイコンは消したくないけど、サイズ変更不可にしたい!」 という投稿もあって、それにはこうしなさいと回答がありました。
dialog.addComponentListener(new ComponentAdapter() { public void componentResized(ComponentEvent e) { dialog.pack(); } });
動かしてみるとサイズ変更は出来るものの、マウスを放したとたんに元の大きさに戻る…という感じです。 結果的にサイズ変更は出来ませんが、あまり根本的な解決策ではないですね。 やはりこういう問題が出てくること自体が問題だと思います。