higa_24
@higa_24

Are you sure you want to delete the question?

Leaving a resolved question undeleted may help others!

java swing ファイルの画像が表示されない

Q&A

Closed

プログラミング初心者です。pcはmac book。テキストエディタはvs codeを使っています。
swingを使ってゲームを作ろうと思い、JLebelでフリー素材の画像(歩行ドットキャラ.psd)をコンパイル時に出るようにしたいのですが、出てこないのを改善したいです。以下がソースコードです。

import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.JPanel;
import jdk.swing.interop.SwingInterOpUtils;
import java.awt.Font;
import java.awt.Color;
public class part18
{
public static void main(String[] args)
{
System.out.println("獺祭");
   //ウィンドウフレームを作成、表示
JFrame jf=new JFrame();
jf.setBounds(50, 100, 750, 400);
jf.setVisible(true);
jf.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);

//親パネルを作成してフレームに貼り付け
JPanel jp=new JPanel();
jp.setBackground(Color.BLACK);
jf.add(jp); 

//ラベルを作成して親パネルに貼り付け
JLabel jl=new JLabel("魔王が世界を滅ぼそうとしています");
Font f=new Font(Font.SERIF,
                Font.BOLD | Font.ITALIC,
                40);//文字のサイズ
jl.setFont(f);
jl.setForeground(new Color(255,128,0));
jp.add(jl);

//子パネルを作成し、親パネルに貼り付け
JPanel jpChild=new JPanel();
jpChild.setBackground(Color.RED);
jp.add(jpChild);

//ラベルを作成して子パネルに貼り付け
JLabel jlChild=new JLabel("八海山 Lv99 HP999/999"); 
jlChild.setFont(f);
jlChild.setForeground(Color.WHITE);
jpChild.add(jlChild);

//画像付きラベルを作成し、親パネルに貼り付け
JLabel jlImage=new JLabel(new javax.swing.ImageIcon("歩行ドットキャラ.psd"));
jlImage.setBounds(100, 100, 480, 256);
jp.add(jlImage);

}
}

歩行ドットキャラ.psd(480×256)ファイルがあるのはDesktop→Myjava→fantasy→歩行ドットキャラ.psdという順番です。

現在の状況ですとコンパイルするとこうなります。
スクリーンショット 2020-08-05 3.41.22.png

質問の仕方がわかりにくかったら申し訳ございません。ご教授の方よろしくお願い致します。

0

3Answer

お使いの環境がわからないので、ある程度推測になってしまいますが、
標準では psd 形式に対応していないはずなので、
まずは事前に画像編集ソフト等で png や bmp 等の他の形式に変換してみては。

Java 8 時点での標準対応の画像フォーマットは、以下で確認できます。
javax.imageio (Java Platform SE 8 )

それでもうまく行かない場合は、実行方法や使用されている JDK のバージョン、
(表示されていれば)エラーメッセージ等も併記した方が情報が集まるかと思います。

0Like

Comments

  1. @higa_24

    Questioner

    拡張子を変更しても変わらずです。
    jdk14.0.1
    エラー文の記載はなし
    知識不足で御恥ずかしいのですが、
    使っている環境を伝えるのはどうすればよろしいでしょうか?

コメントの方だとコードが載せられないようで、
2件目になってしまいますが回答の方で失礼します。

使っている環境を伝えるのはどうすればよろしいでしょうか?

とりあえず不足しているのは、ビルド・実行環境ですね。

java は書いただけで実行できるわけではありませんから、
なにがしかの方法でコンパイル・実行しているはずです。

javac/java コマンドを自分で入力していることもあれば、
vs-code の拡張機能 Java Extension Pack を導入して
使っていることもあるでしょう。
他の方法かもしれません。

記事に書かれている情報(テキストエディタが vs-code)だけでは、
回答者にはわかりませんので。

また、

Desktop→Myjava→fantasy→歩行ドットキャラ.psd

と画像ファイルの場所が書かれていますが、
問題を特定するにはプログラムの実行されている場所の情報も
あると良いです。

現状だと Myjava を基準に実行されているのか
Myjava/fantasy を基準に実行されているのか、
他の場所なのか判別がつきません。

プログラムの実行されている場所によって、
ファイルの指定方法も変わってきます。


で、とりあえずなのですが、
ちゃんとエラーが出るように一部書き換えたほうが、
問題を特定しやすいかもしれないので、書き換えてみます。
ImageIcon を直接使う方法だと、エラー情報を出力してくれないようなので。
画像ファイルは PNG 形式で "歩行ドットキャラ.png" にしておきます。

import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.JPanel;
import java.awt.Font;
import java.awt.Color;
import java.io.IOException;
import java.awt.image.BufferedImage;
import javax.imageio.ImageIO;
import javax.swing.ImageIcon;
import java.io.File;

public class part18 {
    public static void main(String[] args) {
        System.out.println("獺祭"); // ウィンドウフレームを作成、表示

        JFrame jf = new JFrame();
        jf.setBounds(50, 100, 750, 400);
        jf.setVisible(true);
        jf.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);

        // 親パネルを作成してフレームに貼り付け
        JPanel jp = new JPanel();
        jp.setBackground(Color.BLACK);
        jf.add(jp);

        // ラベルを作成して親パネルに貼り付け
        JLabel jl = new JLabel("魔王が世界を滅ぼそうとしています");
        Font f = new Font(Font.SERIF, Font.BOLD | Font.ITALIC, 40);// 文字のサイズ
        jl.setFont(f);
        jl.setForeground(new Color(255, 128, 0));
        jp.add(jl);

        // 子パネルを作成し、親パネルに貼り付け
        JPanel jpChild = new JPanel();
        jpChild.setBackground(Color.RED);
        jp.add(jpChild);

        // ラベルを作成して子パネルに貼り付け
        JLabel jlChild = new JLabel("八海山 Lv99 HP999/999");
        jlChild.setFont(f);
        jlChild.setForeground(Color.WHITE);
        jpChild.add(jlChild);

        // 画像付きラベルを作成し、親パネルに貼り付け
        try {
            File file = new File("歩行ドットキャラ.png");
            BufferedImage image = ImageIO.read(file);
            ImageIcon icon = new ImageIcon(image);
            JLabel jlImage = new JLabel(icon);
            jlImage.setBounds(100, 100, 480, 256);
            jp.add(jlImage);
        } catch (IOException e) {
            System.out.println("ファイル名の指定等がおかしい");
            e.printStackTrace();
        } catch (NullPointerException e) {
            System.out.println("画像ファイルのフォーマットがおかしい");
            e.printStackTrace();
        }
    }
}
0Like

Comments

  1. @higa_24

    Questioner

    とても助かります。ありがとうございます。

    エディタ:vscord 拡張パック:Java Extension Pack
    コンパイル手順:vscord上でターミナルを開きソースの下に出てくるターミナルでcd Desktop→cd Myjavaの状態からjavac part18.java→java part18で実行しています。
    つまり、プログラムの実行されている場所はMyjavaという認識で間違ってないでしょうか?
    この状況で実行環境を伝えるときの簡潔なのべ方もご教授のいただけると幸いです。

    こんな使い方があるのに感動した、送っていただいたソースを実行してみたところ

    獺祭
    ファイル名の指定等がおかしい
    javax.imageio.IIOException: Can't read input file!
    at java.desktop/javax.imageio.ImageIO.read(ImageIO.java:1308)
    at plactice.main(plactice.java:47)

    となりました。
    質問に質問を重ねてしまってすみません。よろしくおねがいします。

  2. > プログラムの実行されている場所はMyjavaという認識で間違ってないでしょうか?

    このやり方ならそれで合っています。
    この場合は画像ファイルは Myjava を基準に指定しなければなりませんから、

    File file = new File("歩行ドットキャラ.png");

    の部分は、

    File file = new File("fantasy/歩行ドットキャラ.png");

    と修正する必要があります。
    エラーの内容も、Can't read input file! (ファイルが読み込めない)
    と言っていますから、まさにそのことを指しています。

    他に誤りがなければ次は動くのではないでしょうか。

    > この状況で実行環境を伝えるときの簡潔なのべ方もご教授のいただけると幸いです。

    今回コメントで書いていただいた内容でも伝わると思いますが、
    敢えて書くなら、

    ---
    ファイル構成

    Desktop/
     Myjava/
      part18.java
      part18.class
      fantasy/
       歩行ドットキャラ.png

    javac コマンドでコンパイルし、
    Myjava ディレクトリで java コマンドから実行しています。
    ---

    のような感じでしょうか。

    ポイントがあるとすれば、回答者が同等の状況を再現するのに十分であれば、
    それで良いかと思います。
    (と、言っても慣れるまでは中々難しいかもしれませんが)
  3. @higa_24

    Questioner

    何から何までありがとうございます。
    実行環境の伝え方も理解できました。
    送っていただいたソースで無事画像が出てきました。感動です。

    今回のエラーは
    JLabel jlImage=new JLabel(new javax.swing.ImageIcon("歩行ドットキャラ.png"));
    だと動かない理由がわからない。
    そのためエラーが出ないImageIconをやめ、try・catch文で何が問題なのかを調べ、それに合わせファイルの指定場所を記入した。というのは理解できました。
    しかし結局のところ何故
    File file = new File("歩行ドットキャラ.png");
    BufferedImage image = ImageIO.read(file);
    ImageIcon icon = new ImageIcon(image);
    JLabel jlImage = new JLabel(icon);
    jlImage.setBounds(100, 100, 480, 256);
    jp.add(jlImage);
    にすると、
    ImageIcon icon = new ImageIcon(image);でなんで型かえてるんだろう?とか
    import文を入れ直してみたりしたのですが、なんで出力できたのかがわかりません。どう調べればいいのかもわからずモヤモヤが残っています。勉強足らずで的はずれな発言をしていたらすみません。

    独学で進めているため、解説や問題が起きた時の調べ方も最後に教えていただけると後学のために助かります。慣れなのかなと思っていますが......
    宜しくお願いします。
    本当にありがとうございます。

また回答の方で失礼します(地味に使いにくい qiita の質問)

なんで出力できたのかがわかりません。どう調べればいいのかもわからずモヤモヤが残っています。

直接的に変更した部分は、

  • 「画像フォーマットを Java で扱えるものに変換したこと」
  • 「ファイルの指定を正しいものに変更したこと」

ですが、途中で色々コード変えちゃいましたね。

私が問題を特定するまでの整理をしてみます。

問題個所の最初の状態は、こうでした

JLabel jlImage = new JLabel(new javax.swing.ImageIcon("歩行ドットキャラ.psd"));

とりあえず、JLabel は import して使っているのに、
ImageIcon は import されていないようだったので追加しました。
(これは単にソースコードの見栄えの問題です)

// import javax.swing.ImageIcon; を追加
JLabel jlImage = new JLabel(new ImageIcon("歩行ドットキャラ.psd"));

問題解決する際には、複数の処理が一文に纏まっていると、
どこがおかしいのかわからなくなりがちなので、
文を分けました。
ここまではやっていること自体は変わりません。

// まず、ImageIcon を生成して、
ImageIcon icon = new ImageIcon("歩行ドットキャラ.psd");
// icon を設定した JLabel を作る。
JLabel jlImage = new JLabel(icon);

コンパイル時にエラーが出ていないので、文法は問題ないはず。
何がおかしいのだろうと考えて、いくつか当たりを付けました。

  • ファイルが読み込めていない (可能性1)
  • ファイルは読み込めても、画像フォーマットが対応していない (可能性2)

で、実際に手元でわざと、間違ったファイル名や、
画像でないファイルを読み込ませてみました。
画像は表示されず、エラーも出ない、という似たような状況を再現できました。
ですが、エラーが出ていないので、
どちらが問題なのか(あるいは両方か)特定できません。

ここで、ImageIcon の API を調べに行きます。
(実際にはある程度事前に知っていた、のですが)。
ImageIcon (Java Platform SE 8 )

説明文に、

サポートされているGIF、JPEG、PNG (1.3以降)などのイメージ形式

と書かれているので、まず psd ではだめなようです。
なので最初に png 等に変換してみては?、とコメントしました

// psd → png に変換してみる

// 変換したファイルを読み込むように変更
// ImageIcon icon = new ImageIcon("歩行ドットキャラ.psd");
ImageIcon icon = new ImageIcon("歩行ドットキャラ.png");
JLabel jlImage = new JLabel(icon);

それでも変わらず、と言うことなので、
問題を特定する方向に変更しました。

ImageIcon (Java Platform SE 8 )を見てみると
ImageIcon には、「ファイル名」ではなく「画像データ(Image)」から作成する方法もあります。

画像データを自力で読み込むようなコードに変換すれば、
間違いがあれば、そこでエラーが出る(問題を特定できる)だろうと考えて、
コード書き直しました。

// 必要な import 文は適宜追加
try {
	// ファイルオブジェクトを作成して
	File file = new File("歩行ドットキャラ.png");

	// 画像データ (BufferedImage) を読み込む
	BufferedImage image = ImageIO.read(file);

	// 画像データから ImageIcon 生成
	ImageIcon icon = new ImageIcon(image);

	// 略
} catch(IOException e) {
	// ファイル読み込みに問題がある
} catch(NullPointerException e) {
	// 画像フォーマットが対応していない
}

で、試していただいたところ、IOException の方だったので、
じゃあファイルの指定がおかしいね、
ファイルの位置を変えるか、ファイル名の指定を変えよう
と言うことになるわけです。

ImageIO.read で画像データ (BufferedImage) が読み込めるのはどこで調べるのか、
と言う話なのですが、
これに関しては「前に使ったことがあって知ってたから」になってしまいますね...。

Java で画像処理などを行う際に使用します。
キーワードとしては Java2D とか。


独学で進めているため、解説や問題が起きた時の調べ方も最後に教えていただけると後学のために助かります。

中々難しい話ですが、あくまで私個人の考えとして。

一般的な話としては、まず問題を分割して考えることでしょうか。

変数等分けて、どこまでは大丈夫なのか確認する。

また「今のコード」を弄るのではなくて、
「問題が発生する部分」だけを抜き出した、より小さなプログラムを作ってみるのも手です。
検討しやすくなりますし、それで問題が発生しなければ他の部分に疑いを向けることができます。

勉強中ということであれば、まず動くプログラムを入門書などから持ってきて、
目的のものになるように変更していく、というのも良いかと思います。
問題が起きても、何を変えたときに問題起きたのか特定しやすいので。
まあ、入門書のプログラムがまず動かせない、とかいうことも往々にしてありますが...。

ある程度、その言語に習熟した後ならば、デバッガの使い方覚えると楽ですかね。


調べると言う部分では、やはり正式なリファレンスを参照すること、でしょうか。

Java SE API &ドキュメント | Oracle 日本

ただ、Java の場合ちょっと面倒なのですが。

  • 日本語の資料は追加が遅いので最新版だと「無い」ことがある。
  • Java 9 以降モジュールシステムが導入され、API ドキュメントもモジュールに分かれてしまったので、関連するものを探すのに結構コツが要る。
    • 例えば swing 関連は java.sejava.desktop と辿って行かないと見つけられません。
    • 検索機能を活用すれば、多少マシにはなります。

私は Java 8 の頃の古い資料見てしまうことが多いです。
(あまりよくはないですが、変わっている可能性を考慮した上で)


他に鉄板の方法としては「エラーメッセージでググれ」なのですが、
今回はメッセージが出ない厄介なケースでしたからね。
Qiita で質問、が大正解なのかも?

ただ、今回ソースコードが崩れてしまっているので、
スルーされがちかもしれません。

Qiita の markdown 記法を便利そうなところだけ覚えて、
コードが見やすいようにしておくと、
回答が付きやすいかなと思います。

Markdown記法 チートシート - Qiita


\`\`\`言語
コード
コード
コード
\`\`\`

Java の場合


\`\`\`java
public class MyClass {
  public static void main(String[] args) {
    System.out.println("Hello!");
  }
}
\`\`\`

↓表示

public class MyClass {
  public static void main(String[] args) {
    System.out.println("Hello!");
  }
}
0Like

Comments

  1. @higa_24

    Questioner

    とてもシンプルに教えていただきとても分かり易い説明ありがとうございます。
    理解できました。プロの方の思考を知れたのもとても有り難いです。

    一歩一歩がんばっていこうと改めて強く思いました。
    参考のサイトまで細かい疑問に付き合っていただき、本当にありがとうございました。

Your answer might help someone💌