質問するログイン新規登録
Java

Javaは、1995年にサン・マイクロシステムズが開発したプログラミング言語です。表記法はC言語に似ていますが、既存のプログラミング言語の短所を踏まえていちから設計されており、最初からオブジェクト指向性を備えてデザインされています。セキュリティ面が強力であることや、ネットワーク環境での利用に向いていることが特徴です。Javaで作られたソフトウェアは基本的にいかなるプラットフォームでも作動します。

Eclipse

Eclipseは、IBM社で開発された統合開発環境のひとつです。2001年11月にオープンソース化されました。 たくさんのプラグインがあり自由に機能を追加をすることができるため、開発ツールにおける共通プラットフォームとして位置づけられています。 Eclipse自体は、Javaで実装されています。

Q&A

解決済

1回答

879閲覧

【Java】ボタンに画像が表示されない

Kob83

総合スコア2

Java

Javaは、1995年にサン・マイクロシステムズが開発したプログラミング言語です。表記法はC言語に似ていますが、既存のプログラミング言語の短所を踏まえていちから設計されており、最初からオブジェクト指向性を備えてデザインされています。セキュリティ面が強力であることや、ネットワーク環境での利用に向いていることが特徴です。Javaで作られたソフトウェアは基本的にいかなるプラットフォームでも作動します。

Eclipse

Eclipseは、IBM社で開発された統合開発環境のひとつです。2001年11月にオープンソース化されました。 たくさんのプラグインがあり自由に機能を追加をすることができるため、開発ツールにおける共通プラットフォームとして位置づけられています。 Eclipse自体は、Javaで実装されています。

1グッド

0クリップ

投稿2023/10/20 14:43

1

0

実現したいこと

・ボタンに画像を表示したい

前提

JavaでGUIアプリケーションを作ってみようと思い、下記リンクを参考に製作をしました。
https://original-game.com/java-janken-game-program/

次はこれに画像を追加しようと思い、まずはボタンに画像とテキストを表示するコードを追加したのですが、画像が表示されません。

ソースコードを何度見直してもどこに問題があるかわからず困っています。

下記コードの問題点を指摘頂けると幸いです。

発生している問題・エラーメッセージ

ボタンにテキストと画像を表示したいが、画像が表示されない。
テキストは表示される

該当のソースコード

Java

1package jp.hoge.fuga.foo; 2 3(略) 4 5public class Main { 6 7 //プレイヤー側手配列 8 private static String[] hands = {"グー","チョキ","パー"}; 9 private static ImageIcon[] buttonHands = new ImageIcon[3]; 10 //初期化ブロック 11 { 12 buttonHands[0] = new ImageIcon("../../../../../img/image1.png"); 13 buttonHands[1] = new ImageIcon("../../../../../img/image2.png"); 14 buttonHands[2] = new ImageIcon("../../../../../img/image3.png"); 15 } 16 17(略) 18 public static void main(String[] args) { 19 //Main Window 20 JFrame frame = new JFrame("じゃんけんゲーム"); 21 frame.setSize(900, 650); 22 frame.setLocationRelativeTo(null); 23 frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); 24 frame.setResizable(false); 25(略) 26 //FooterPanel 27 JPanel footerPanel = PanelMaker.makePanel(Color.BLACK,900,200); 28 footerPanel.setLayout(new GridLayout()); 29 30 //ボタン生成 31 for(int i=0; i<hands.length; i++) { 32 JButton button = new JButton(hands[i],buttonHands[i]); 33 button.setFont(new Font("Meiryo", Font.PLAIN, 24)); 34 button.setHorizontalTextPosition(JButton.CENTER); 35 button.setVerticalTextPosition(JButton.BOTTOM); 36 button.addActionListener(new ButtonActionListener()); 37 footerPanel.add(button); 38 } 39 40 frame.add(footerPanel, BorderLayout.SOUTH); 41 42 frame.setVisible(true); 43 44 } 45(以下略)

試したこと

画像のパスに問題があるのかと思い、プロジェクトフォルダからの相対パスに変更してみましたが、解決しませんでした。

32行目を

Java

1JButton button = new JButton(buttonHands[i]);

にしたところ、ボタンには何も表示されませんでした。

ボタンのサイズに問題がある可能性も考え、footerpanelの高さを変えてみましたが、改善しませんでした。

補足情報(FW/ツールのバージョンなど)

開発環境はeclipseを使用しています。
Main.javaファイルと画像ファイルのフォルダ構造は下記の通りです。

プロジェクトフォルダ---src--jp---hoge---fuga---foo--Main.java
|
└--img---image1.png(以下image2.png及びimage3.pngも同じ)

よろしくお願いいたします。

TN8001👍を押しています

気になる質問をクリップする

クリップした質問は、後からいつでもMYページで確認できます。

またクリップした質問に回答があった際、通知やメールを受け取ることができます。

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

guest

回答1

0

ベストアンサー

パスの指定がダメなようです。
まず、パッケージのフォルダ構造は実行には関係ありません。
そして、 src フォルダは eclipse の開発環境としての構造で、実行は src フォルダのある位置つまり 「プロジェクトフォルダ」がカレントフォルダになります。
従って、(プロジェクトフォルダ)\img\image1.png を指定するなら相対パスとしては "img/image1.png" となります。

↓のようなプログラムを作って確認してみては如何でしょうか。

java

1package jp.hoge.fuga.foo; 2 3import java.io.File; 4 5public class Test { 6 public static void main(String[] args) { 7 File file = new File("img/image1.png"); 8 System.out.println(file.getAbsolutePath()); //絶対パス 9 System.out.println(file.exists()); //有るか無いか 10 } 11}

じゃんけんの "手" に関わるものを enum Hand に集約してみます。
クラス分けも、パネルをレフリー/コンピュータ/プレイヤーに見立ててみました。

java

1import java.awt.*; 2import java.util.Random; 3import java.util.function.Consumer; 4 5import javax.swing.*; 6 7public class MainFrame extends JFrame { 8 public static void main(String[] args) { 9 SwingUtilities.invokeLater(() -> new MainFrame().setVisible(true)); 10 } 11 12 MainFrame() { 13 super("じゃんけんゲーム"); 14 setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); 15 setResizable(false); 16 17 RefereePanel refereePanel = new RefereePanel(); 18 add(refereePanel, BorderLayout.NORTH); 19 20 ComputerPanel computerPanel = new ComputerPanel(); 21 add(computerPanel, BorderLayout.CENTER); 22 23 add(new PlayerPanel(playerHand -> 24 refereePanel.finish(playerHand, computerPanel.getHand()) 25 ), BorderLayout.SOUTH); 26 27 pack(); 28 setLocationRelativeTo(null); 29 } 30 31 private static enum Hand { 32 グー("image1.png"), チョキ("image2.png"), パー("image3.png"); 33 34 String imagefile; 35 Hand(String imagefile) { 36 this.imagefile = imagefile; 37 } 38 /** 39 * 勝敗 40 * @param other 相手 41 * @return 0=引き分け, 1=負け, 2=勝ち 42 */ 43 int judge(Hand other) { 44 return (ordinal() - other.ordinal() + 3) % 3; 45 } 46 } 47 48 private static class RefereePanel extends JPanel { 49 private static final String[] TEXTS = { "あいこかよ!", "お前の負けかよ!", "お前の勝ちかよ!" }; 50 private JLabel label; 51 RefereePanel() { 52 super(new BorderLayout()); 53 setBackground(Color.BLACK); 54 setSize(640, 50); 55 setPreferredSize(getSize()); 56 57 add(label = new MyLabel("「さあ、じゃんけんで勝負だ!」", 24, Color.WHITE)); 58 } 59 void finish(Hand playerHand, Hand computerHand) { 60 label.setText(TEXTS[playerHand.judge(computerHand)]); 61 } 62 } 63 64 private static class ComputerPanel extends JPanel { 65 private Random random = new Random(); 66 private JLabel label; 67 ComputerPanel() { 68 super(new BorderLayout()); 69 setBackground(Color.WHITE); 70 setSize(640, 380); 71 setPreferredSize(getSize()); 72 73 add(label = new MyLabel("じゃんけん……", 54, Color.BLACK)); 74 } 75 Hand getHand() { 76 Hand computerHand = Hand.values()[random.nextInt(3)]; 77 label.setText(computerHand.toString()); 78 return computerHand; 79 } 80 } 81 82 private static class PlayerPanel extends JPanel { 83 PlayerPanel(Consumer<Hand> referee) { 84 super(new GridLayout()); 85 setBackground(Color.BLACK); 86 setSize(640, 50); 87 setPreferredSize(getSize()); 88 89 for(Hand hand : Hand.values()) { 90 JButton button = new JButton(hand.toString(), new ImageIcon("img/" + hand.imagefile)); 91 button.setFont(new Font("MS ゴシック", Font.PLAIN, 24)); 92 button.addActionListener(v -> referee.accept(hand)); 93 add(button); 94 } 95 } 96 } 97 98 private static class MyLabel extends JLabel { 99 MyLabel(String str, int size, Color color) { 100 super(str); 101 setForeground(color); 102 setFont(new Font("MS ゴシック", Font.PLAIN, size)); 103 setHorizontalAlignment(JLabel.CENTER); 104 setVerticalAlignment(JLabel.CENTER); 105 } 106 } 107}

投稿2023/10/20 16:48

編集2023/10/20 19:31
jimbe

総合スコア13357

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

TN8001

2023/10/20 17:26 編集

「初期化ブロック」も原因です。 Mainクラスのインスタンスを作っていないので実行されません。 [Java static初期化ブロックと初期化ブロック | ITSakura](https://itsakura.com/java_block) handsと同様に普通に初期化すればいいでしょう(「static初期化ブロック」にしてもいいでしょうが^^; private static ImageIcon[] buttonHands = { new ImageIcon("img/image1.png"), new ImageIcon("img/image2.png"), new ImageIcon("img/image3.png"), };
Kob83

2023/10/20 18:16

お二方の指摘通りに修正したところ、解決しました!ありがとうございます。 最初は普通に初期化しようとしていたのですが、今思うと配列なのに,ではなく;で区切るアホなことをしてエラーが出たので、何も考えず初期化ブロックにしてしまっていました。 今回指摘を受けて改めてコードを見直していたところ、クラスの最初のほうで記述しているbuttonHandsはボタンに画像を配置する以外では使用しないので、mainメソッド内で記述した方が良いような気がしてきました。 この場合、この場合、どちらの方が望ましいのでしょうか。
jimbe

2023/10/20 19:32 編集

buttonHands は hands とセットですので、私なら グーチョキパーと各画像ファイル名で1つとなる enum にして、ついでに判定ロジックも組み込みます。 (回答にコード追加)
Kob83

2023/10/21 00:41

ありがとうございます。 enumはまだ勉強中でしたが、このように使うのですね。 勉強してから改めて取り組んでみたいと思います。
jimbe

2023/10/21 05:03

enum は class のちょっと特別な書き方・使い方というだけで、 enum Hand も普通のクラスで書けます。 トランプのスートや麻雀牌の種類のような「有限で増減せず同時に使うモノの集まりで、それぞれに何か(表示順とか)関係があるもの」を表すのに適切かと思います。 まぁ100とか1000とかあまりに数が多いのをグーチョキパーみたいに全部書くのは大変で間違えやすいですので、その場合は別のテを使った方が良いでしょうね。
Kob83

2023/10/22 23:33

ありがとうございます。 修正されたコードを眺めていてふと思ったのですが、列挙子(でいいんですよね?)が「 グー("image1.png")」のような書き方になっていますが、素人からすると「GU("グー", "image1.png")」のほうが適切に感じてしまいます。前者の方が何か利点があるのでしょうか。 >「有限で増減せず同時に使うモノの集まりで、それぞれに何か(表示順とか)関係があるもの」を表すのに適切かと思います。 ということは、Javaの作例でよく配列で格納しているデータは結構enumに置き換え可能そうですね。 >「有限で増減せず同時に使うモノの集まりで、それぞれに何か(表示順とか)関係があるもの」を表すのに適切かと思います。 プログラミング自体初学者なのであまり詳しくないのですが、そういう場合は別途データベースを作って読み込ませる、などのほうが良いのでしょうか……
jimbe

2023/10/23 04:42 編集

>「 グー("image1.png")」のような書き方になっていますが、素人からすると「GU("グー", "image1.png")」のほうが適切に感じてしまいます "適切" の基準は何でしょうか。(責めているのでは無くて単なる質問です。) 言ってしまえば今回は私はどちらでも良いと思います。 enum は toString() がそのオブジェクト自身の名前を返すことになっていますので、 Hand.グー.toString() は "グー" を返しますから、間接的に利用されます。対して GU("グー", " image.png") と定義する場合、 "GU" は何にも利用されません。 また、将来国際化するとかいう類なら、"GU" というのも適当かどうかわかりません("Rock"/"Scissors"/"Paper"となるかもしれません)し、 toString() メソッドは override 可能ですから必要なら "GU" に変えて toString() で "グー" を返したり、設定ファイルを作って最初に読ませることも可能です。(そしてその場合でも Hand クラス以外に修正はありません。そのほうが案件としては重要です。) Hand に必要なのは "グー" か "GU" かでは無く、じゃんけんのテを 3 つ定義し、表示用文字列と画像ファイル名が得られ、各テ間の勝敗の判定が出来る事としましたので、"グー" か "GU" かはどちらでも…なのです。(後付けですけど^^; ) もし「一般的なのか」という問いでしたら、ネットや書籍のコードを見る限りクラスやメソッド、フィールド/変数、オブジェクト名等に日本語を使うのは少ないかもしれません。 でも個人的には、日本人が書いた日本人向けのサンプルコードで "これくらい" は話のネタとしても面白いのではという感じです。 そもそも(?) 英語圏の人が「if(Hand.toString().equals("Rock")) ~」というコードを見たら、それは日本人が「もし手を文字列にしたのが "石"(グー) と同じだったら」と書いてあるように見えるのと同じはずで、英語圏の人には自然言語的に読める(ようにする)のに日本語圏の人には読めるようにしてはダメということは無いでしょう。(確信犯?) >別途データベースを作って読み込ませる、などのほうが良いのでしょうか 「案件に因ります」というのが大前提です。 この質問のコード規模・機能・将来の想定(これは私の想像ですが)ならそもそもデータベースどころか設定ファイルを使うのも必要性がありませんから、コードで完結するように書きました。 もし国際化やローカルルールの取り込みやオンライン化までも見据えたポーカーゲームだったら、役をデータベース化してその中に全ての情報を入れることになるかもしれませんね。
guest

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

15分調べてもわからないことは
teratailで質問しよう!

ただいまの回答率
85.30%

質問をまとめることで
思考を整理して素早く解決

テンプレート機能で
簡単に質問をまとめる

質問する

関連した質問