非IT企業に勤める中年サラリーマンのIT日記

非IT企業でしかもITとは全く関係ない部署にいる中年エンジニア。唯一の趣味がプログラミングという”自称”プログラマー。

Java:Jar実行ファイルを配布するとアイコン画像が消えてしまう!その対処法は?

   

Javaでコンパイルしたclassファイルをマウスクリックで実行ファイルにする方法として、以下のコマンドで実行可能な1つのjarファイルにすることができます。

jar cmf mani.mani out.jar *.class

この中で「mani.mani」とはマニフェストファイルで、別途用意する必要があります。ファイルの中身は以下のようになります。

Manifest-Version: 1.0
Main-Class: ここにメインクラス名を入れる(.classなし)

 

まず、ここまでが前提。

[ad#top-1]

アイコン付きのボタン

ここからが本題なのですが、こんなプログラムを作りました。

import java.awt.*;
import javax.swing.*;

public class IconTest extends JFrame{
  protected Container pane;

  public static void main(String[] args){
    IconTest f = new IconTest("Icon Test");
    f.setLocationRelativeTo(null);
    f.setVisible(true);
  }

  IconTest(String t){
    super(t);
    setSize(400, 300);
    pane = getContentPane();
    pane.setLayout(new FlowLayout());

    JButton btn = new JButton( new ImageIcon("icon.png") );
    pane.add(btn);
  }
}
 

 

実行するとこんな感じです。画像付きボタンを表示させるためのなんてことのないプログラムです。(Look&FeelをWindows風にしていますが、上記プログラムには反映されていませんのであしからず。)

 

これを前述の通り、マニフェストファイルを作って以下のコマンドで実行可能なjarファイルを作りました。

jar cmf mani.mani IconTest.jar *.*

拡張子を.*としたのは、アイコン画像ファイルも同梱させるつもりのためです。

 

jarファイルを移動してみる

実行可能なjarファイルは配布できます。

配布を模擬するつもりで、jarファイルを別のフォルダに移動してみます。

 

それを実行すると・・・、なぜかアイコン画像が現れません。これが今回のテーマです。

 

あくまで指定フォルダ内の画像にアクセスする

アイコン画像はjarファイル内に入っているのですが、プログラムからのアクセスはあくまで指定フォルダの画像ファイルを探しに行くため、このような現象が起きるんです。

 

なので、配布時に画像ファイルも一緒に配布すればOKなのですが、できればjarファイルだけの配布にしたいですよね。

どのようにしてjar内の画像ファイルにアクセスできるようになるでしょうか?

 

ImageIconクラスを拡張してメインクラスを紐づけする

これを解決するために、以下のようにImageIconクラスを拡張してメインクラスに紐づけしました。これを、ImageIcon2.javaというファイル名にして保存します。残念ながら標準APIでは解決できず、拡張して自作するしかないんです。

import javax.swing.*;
import java.awt.*;
import java.awt.image.*;
import java.net.*;

public class ImageIcon2 extends ImageIcon{
  public ImageIcon2(String f, Window own){
    super();
    Image image;
    try {
      Toolkit tk = own.getToolkit();
      URL url = own.getClass().getResource(f);
      image = tk.createImage((ImageProducer)url.getContent());
      setImage(image);
    } catch (Exception e) {
      System.out.println("Image not Found!");
    }
  }
}
 

 

メインクラスからの使い方は以下の通りです。

import java.awt.*;
import javax.swing.*;

public class IconTest extends JFrame{
  protected Container pane;

  public static void main(String[] args){
    IconTest f = new IconTest("Icon Test");
    f.setLocationRelativeTo(null);
    f.setVisible(true);
  }

  IconTest(String t){
    super(t);
    setSize(400, 300);
    pane = getContentPane();
    pane.setLayout(new FlowLayout());

    JButton btn = new JButton( new ImageIcon2("icon.png", this) ); //ココ
    pane.add(btn);
  }
}
 

 

これをコンパイルして、jarファイルだけ別のフォルダに移動した上で実行すると、以下の通りちゃんと画像が現れました。

.

[ad#ad-1]

スポンサーリンク

 - Java