前提・実現したいこと
Swingのコンポネント描画やイベント処理などは、イベントディスパッチスレッド(EDT)上で行なうルールとされていますが、
「コンポネント描画」や「イベント処理」をEDT上で行う具体的な手順・方法がわからず、次項「発生している問題」欄のとおり行き詰ってしまいました。
発生している問題・エラーメッセージ
『該当のソースコード』を実行すると、「choicel」「choice2」「choice3」「textArea」の表示に不具合が発生します。
例えば、「マイホーム」で「本を読む」を選択すると、テキストエリアには「何を読もう。」というテキストが表示され、choicel〜3もそれぞれの表示に変更されます。
そこまでは良いのですが、本を読むのをやめてマイホームへ戻ってみると、メッセージウィンドウもchoice1〜3の表示も「本を読む」の状態のまま変化してくれません。
他の選択肢「何か食べる」「買い物に行く」も同様です。表示されないか、表示されたとしても、描写にもたつきが発生します。
該当のソースコード
import java.awt.Color; import java.awt.Container; import java.awt.Font; import java.awt.GridLayout; import java.awt.event.ActionEvent; import java.awt.event.ActionListener; import javax.swing.ImageIcon; import javax.swing.JButton; import javax.swing.JFrame; import javax.swing.JLabel; import javax.swing.JPanel; import javax.swing.JTextArea; import javax.swing.UIManager; public class HogeQuest extends JFrame{ JFrame frame; Container contentPane; JPanel titleNamePanel; //ゲームのタイトル画面 JLabel titleNameLabel; JPanel startButtonPanel; //スタートボタン JPanel textPanel; //メッセージウィンドウ JTextArea textArea; //メッセージを表示 Font titleFont = new Font(Font.SERIF, Font.PLAIN, 100); //ゲームタイトル用のフォント Font normalFont = new Font(Font.SERIF, Font.PLAIN, 20); String position, text; JPanel choiceButtonPanel; //選択肢のコマンドボタンを格納 JButton choice1, choice2, choice3, startButton; //コマンドボタン、スタートボタン JPanel imagePanel; //画像を表示 JLabel imageLabel; ImageIcon image; StartButtonHandler startButtonHandler = new StartButtonHandler(); //スタートボタンを押したときの動作 ChoiceHandler choiceHandler = new ChoiceHandler(); //コマンドボタン(選択肢)を押したときの動作 public static void main(String[] args){ new HogeQuest(); } public HogeQuest(){ //macで起動した場合に発生する表示の不具合(ボタンの背景色が設定通りに反映されない)を防ぐためのもの try { UIManager.setLookAndFeel( UIManager.getCrossPlatformLookAndFeelClassName() ); } catch (Exception e) { e.printStackTrace(); } frame = new JFrame("HogeQuest"); frame.setBounds(0,0,1300,950); frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); frame.getContentPane().setBackground(Color.black); frame.setLayout(null); frame.setVisible(true); contentPane = frame.getContentPane(); //// ゲーム開始直後のタイトル画面。スタートボタンを押すと「マイホーム」に画面遷移 titleNamePanel = new JPanel(); titleNamePanel.setBounds(100,300,1000,200); titleNamePanel.setBackground(Color.black); titleNameLabel = new JLabel("Hoge Quest"); //ゲームタイトル titleNameLabel.setForeground(Color.white); titleNameLabel.setFont(titleFont); titleNamePanel.add(titleNameLabel); startButtonPanel = new JPanel(); startButtonPanel.setBounds(485, 600, 200, 120); startButtonPanel.setBackground(Color.black); startButton = new JButton("Start"); startButton.setBackground(Color.black); startButton.setForeground(Color.white); startButton.setBorder(null); //ボタンの枠線を消す startButton.setFont(normalFont); startButton.addActionListener(startButtonHandler); startButton.setFocusPainted(false); startButtonPanel.add(startButton); contentPane.add(titleNamePanel); contentPane.add(startButtonPanel); } ////////////////////////////////////////////// ここからはマイホーム public void myHome(){ position = "myHome"; titleNamePanel.setVisible(false); //タイトル画面を消す startButtonPanel.setVisible(false); //スタートボタンも消す imagePanel = new JPanel(); //画像が表示されるエリア imagePanel.setBounds(40,40,720,480); imagePanel.setBackground(Color.black); imageLabel = new JLabel(); image = new ImageIcon("./image01.jpg"); imageLabel.setIcon(image); imagePanel.add(imageLabel);// contentPane.add(imagePanel); textPanel = new JPanel(); //メッセージが表示されるエリア textPanel.setBounds(60, 540, 680, 200); textPanel.setBackground(Color.black); textArea = new JTextArea(); textArea.setBounds(60, 520, 680, 200); textArea.setBackground(Color.black); textArea.setForeground(Color.white); textArea.setFont(normalFont); textArea.setLineWrap(true); //テキストをパネル内に収まるよう折り返す textPanel.add(textArea); contentPane.add(textPanel); choiceButtonPanel = new JPanel(); //コマンドボタン choiceButtonPanel.setBounds(800, 550, 380, 200); choiceButtonPanel.setBackground(Color.black); choiceButtonPanel.setLayout(new GridLayout(3,1)); contentPane.add(choiceButtonPanel); choice1 = new JButton("本を読む"); choice1.setBackground(Color.black);//ボタンの色は背景と同じ黒 choice1.setForeground(Color.white);//文字の色は白 choice1.setFont(normalFont); choice1.setFocusPainted(false); choice1.addActionListener(choiceHandler); choice1.setActionCommand("c1"); choiceButtonPanel.add(choice1); choice2 = new JButton("何か食べる"); choice2.setBackground(Color.black); choice2.setForeground(Color.white); choice2.setFont(normalFont); choice2.setFocusPainted(false); choice2.addActionListener(choiceHandler); choice2.setActionCommand("c2"); choiceButtonPanel.add(choice2); choice3 = new JButton("買い物に行く"); choice3.setBackground(Color.black); choice3.setForeground(Color.white); choice3.setFont(normalFont); choice3.setFocusPainted(false); choice3.addActionListener(choiceHandler); choice3.setActionCommand("c3"); choiceButtonPanel.add(choice3); } /////////////////////////////////////////////////////// 本を読む public void book(){ position = "book"; textArea.setText("何を読もう。"); choice1.setText("スッキリわかるJava入門"); choice2.setText("オブジェクト指向でなぜつくるのか"); choice3.setText("やめる"); } /////////////////////////////////////////////////////// 何か食べる public void eat(){ position = "eat"; textArea.setText("何か食べよう。"); choice1.setText("ラーメン"); choice2.setText("カレーライス"); choice3.setText("ああ、おなかいっぱい"); } ///////////////////////////////////////////////////// 買い物に行く public void shop(){ position = "shop"; image = new ImageIcon("./image02.jpg"); imageLabel.setIcon(image); textArea.setText("何をお買い求めになられますか?"); choice1.setText("ラーメン"); choice2.setText("カレーライス"); choice3.setText("店を出る"); } /////////////////////////////////////// スタートボタンを押した時の動作 public class StartButtonHandler implements ActionListener{ public void actionPerformed(ActionEvent event){ myHome(); } } /////////////////////////////////////// 選択肢のボタンを押した時の動作 public class ChoiceHandler implements ActionListener{ public void actionPerformed(ActionEvent event){ String yourChoice = event.getActionCommand(); switch(position){ case "myHome": //マイホーム switch(yourChoice){ case "c1": book();break; case "c2": eat();break; case "c3": shop();break; } break; case "book": //本を読む switch(yourChoice){ case "c1": textArea.setText("ふむふむ。"); break; //「スッキリわかるJava入門」を選択 case "c2": textArea.setText("なるほどわからん。"); break; //「オブジェクト指向でなぜつくるのか」を選択 case "c3": myHome();break; //「やめる」を選択 } break; case "eat": //何か食べる switch(yourChoice){ case "c1": textArea.setText("おいしい!"); break; //「ラーメン」を選択 case "c2": textArea.setText("からい!"); break; //「カレーライス」を選択 case "c3": myHome();break; //「ああ、おなかいっぱい」を選択 } break; case "shop": //買い物に行く switch(yourChoice){ case "c1": textArea.setText("ラーメンですね。ありがとうございます。"); break; //「ラーメン」を選択 case "c2": textArea.setText("カレーですね。ありがとうございます。"); break; //「カレーライス」を選択 case "c3": myHome();break; //「店を出る」を選択 } break; } } } }
試したこと
ネットにて症状を検索。どうやら複数の別個のスレッドから描写の変更を命令したことによる競合が原因であると推測し、SwingUtilities、SwingWorker、EDTなど調べてみたのですが、それらを当該コードにどう適用すればいいのか分からず独学の限界を感じております。
補足情報(FW/ツールのバージョンなど)
■参考にしたもの:
How to Make Text Adventure Game with GUI in Java FINAL - Complete the game
https://www.youtube.com/watch?v=AyB3LiF-XyA&list=PL_QPQmz5C6WUMB0xEMZosWbyQo_Kil0Fb&index=6
■環境:
java 1.8
回答2件
あなたの回答
tips
プレビュー
バッドをするには、ログインかつ
こちらの条件を満たす必要があります。
2020/08/14 01:00
2020/08/14 07:00
2020/08/14 07:14
2020/08/14 08:17