2012/05/15

SwingのJFrameのアイコンに null を入れるとアプリのGUIが表示されない

SwingのJFrameのアイコンに null を入れるとアプリのGUIが表示されませんでした。


JFrame frame = new JFrame( "title" );
JPanel panel = new JPanel();
URL url = panel.getClass().getResource( "logo.png" );
frame.setIconImage( Toolkit.getDefaultToolkit().createImage( url ) );

■対策
urlに null だった場合、GUIが表示されないままメモリに常駐してしまう。
なので、null チェックを入れておくことでGUIが表示されない状況を防ぐことができる。

if ( url != null ) { frame.setIconImage( Toolkit.getDefaultToolkit().createImage( url ) );
}
else {
  // どうしても固有のアイコンが表示したい場合は別のアプローチでアイコンを設定する
}

■誘因
今回、urlに null が入ってしまったきっかけはpanel.getClass().getResource()を呼び出した際、ダブルクリックでjarを起動する場合と、eclipse上またはコマンドプロンプトから起動する場合で挙動が変わったためでした。

jarファイル内は
  • example.SamplePanel
  • logo.png
というようにexampleパッケージ内にSamplePanelクラスがあり、logo.pngはjarファイル直下に配置してありました。
そして、下のようにlogo.pngを読み込みました。

JPanel panel = new SamplePanel();
URL url = panel.getClass().getResource( "../logo.png" );

この場合、eclipse上で実行を行った場合と、コマンドプロンプト上で
java -cp sample.jar example.SamplePanel

と入力して実行した場合は、GUIも表示されて起動する。しかし、jarファイルをダブルクリックした場合はGUIが表示されないがメモリには常駐している状況が発生する。そして、jarファイルと同じフォルダ上にlogo.pngがある場合、GUIが表示された。
つまり、ダブルクリックした場合とeclipse上での起動の場合の参照位置が異なるようだ。

■実験結果により推測されること(panel.getClass().getResource())

・eclipse上またはコマンドプロンプトから起動する場合
 ・exampleパッケージが起点

・jarファイルをダブルクリックで起動するの場合
 ・jarファイル直下が起点

という違いがあること。
もし、パッケージを使用せずデフォルトパッケージであれば差異は発生ないが、デフォルトパッケージは推奨されていないことからpanel.getClass().getResource()は使用しないのが良いと思う。


getClassLoader()を使用する
ここで、getClassLoader()を使用した場合、
URL url = panel.getClass().getClassLoader().getResource( "logo.png" );

・eclipse上またはコマンドプロンプトから起動する場合、jarファイルをダブルクリックで起動するの場合、ともに
jarファイル直下が起点であった。
このことから、JFrameのアイコンを読み込む場合はgetClassLoader()を使用すると良い。

ClassLoaderについては以下のサイトを参考にしてほしい。

■その他
できれば、res/logo.pngと配置したいのですが、Antを使わずにeclipseの設定のみでできる方法があれば教えてほしいです。

0 件のコメント:

コメントを投稿