何故かうまくいかない、JOptionPaneでのフォント設定について。 JDK1.3のWindows版でございます。
JAVA言語で例外オブジェクトのハンドリングをせかせかとコーディングしていました。 そのときにユーザーにメッセージを伝えるために、自分でダイアログを新規に作るのは面倒だと思い、JAVAのクラスライブラリにあるjavax.swing.JOptionPaneを使用することにしました。
単純に使おうとすると、JOptionPaneの構築するダイアログのアイコンがJAVAの標準のアイコンでかっこ悪いというか個性が無いので、自分で指定したイメージをアイコンに使うことにしました。 無事アイコンのカスタムが完了し、メッセージのダイアログをみると文字が変です。 JAVAの標準の日本語のフォントは明朝体なのですが、おそらくSUNのミスでSwingのMetalテーマの場合だけ、明朝体の表示がおかしいのです(これがJAVAでのGUIの標準だというのに)。
そこで私は、他のウィンドウでもしているように、setFont(Font)をコールしてダイアログのフォントを設定しようとしました。 しかし、全く効果がありません。 何故? Dialog系のクラスではだめで、Frame系のクラスでないといけないのかなー。
このソースコードには、アイコンのカスタムの為のコードは混入していません。 また、本来のコードはアプリケーションに依存している箇所があるので、その部分は変更してあります。 MS ゴシックというフォントは、システム内に実在し、実際このようにしてフォントオブジェクトを生成して別のウィンドウで設定すると、きちんと表示されることを確認しています。
1: JOptionPane PANE = null; 2: String MSG = "これはテストです。ててすすとと。動作確認用。"; 3: String TITLE = "てすと。"; 4: JDialog DLG = null; 5: Font f = new Font("MS ゴシック" Font.PLAIN, 12); 6: 7: 8: PANE = new JOptionPane(); 9: PANE.setFont(f); 10: PANE.setMessage(MSG); 11: PANE.setMessageType(JOptionPane.WARNING_MESSAGE); 12: DLG = PANE.createDialog(null, TITLE); 13: DLG.setFont(f); 14: Component[] c = DLG.getContentPane().getComponents(); 15: DLG.getContentPane().setFont(f); 16: for(int i=0;c.length > i;i++){ 17: c[i].setFont(f); 18: } 19: DLG.validate(); 20: DLG.invalidate(); 21: DLG.setVisible(true);
フォントがおかしいね。 ほんとに。
まず、JDKのリファレンスをみて、JOptionPaneを使うにあたっての注意点を見つけました。 それは、静的なメソッド(JAVA専門用語ではクラスメソッドと呼ぶのでしょうか)でダイアログ表示まで行うのではなく、JOptionPaneのインスタンスを構築し、そこからJDialogを取得し、それをカスタマイズして表示するというものでした。
実際に私も試しています。 ソースコードの12行目にあるJOptionPane.this.createDialog(Component,String)がJDialogを取得するコードです。 それからそのJDialogのインスタンスにフォントの設定を、それでもだめだったのでContentペインを取得し、それらの全てのフォントを設定しています(それはつまり、ダイアログを構成しているラベルやボタンにフォント設定をしているという事)。 さらに、それらを完全に再認識させる為のコードが後に続き、ダイアログを表示しています。
もしかしたらデータが書き換わっているのかと思い、デバッガでダイアログ表示寸前のタイミングでダイアログのインスタンス内をみたら、どこもかしこも設定したフォントが格納されています。 つまり、データは正しいのにそのとおりに動いていないのです。 それとも、これは仕様なのだろうか。 むー。
めげずに打開策を探りました。 そして、どうやらフォントは親ウィンドウのContainerの設定を受け継いで作成されるそうです。 つまり、親ウィンドウを指定してあげれば、自動的にフォントは親と同じフォントが使われるのです。 これを裏付ける事実として、タイトルバーのアイコンがあります。 こいつは親ウィンドウと同じアイコンが使われるのです(実験済み)。
方法は簡単です。 12行目のJOptionPane.this.createDialog(Component,String)の引数にnullではなく親ウィンドウを渡してやればよいのです。
それでもやっぱりだめでした。 アイコンは親ウィンドウと同じになりますがフォントがどうしても変りません。 何かが、本当に何かが足りないのかなー。