質問をすることでしか得られない、回答やアドバイスがある。

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

新規登録して質問してみよう
ただいま回答率
85.48%
Java

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

Q&A

解決済

2回答

3882閲覧

paintComponentメソッドについて

nakamura-

総合スコア48

Java

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

0グッド

1クリップ

投稿2016/10/07 05:53

前回と似た質問で申し訳ないですが、わからないので質問させていただきます。
下のプログラムはシューティングゲームを作っている途中のプログラムです。

コード public class Part01 extends JFrame{ /** * メインクラス */ public static void main(String args[]){ new Part01(); } /** * コンストラクタ */ public Part01(){ /**フレームの初期化*/ super("Shooting Game"); setBounds(0, 0, 500, 500); setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); setVisible(true); /**パネルの生成*/ MyPanel myPanel = new MyPanel(); add(myPanel); /**初期化を行う*/ myPanel.initialization(); } } public class MyPanel extends JPanel implements Runnable{ Title title; //Titleクラス変数 Score score; //Scoreクラス変数 /** * コンストラクタ */ public MyPanel(){ /*title = new Title(); score = new Score();*/ Thread thread = new Thread(this); thread.start(); } /** * 初期化 */ public void initialization(){ //score.initMyScore(); } /** * メインループ */ @Override public void run(){ while(true){ System.out.println("12345"); repaint(); try{ Thread.sleep(500); } catch(InterruptedException e){ } } } /** * 描画 */ @Override protected void paintComponent(Graphics g){ super.paintComponent(g); System.out.println("6789"); g.setColor(Color.RED); g.fillRect(100, 100, 100, 100); } }

プログラム内容
Part01クラスでフレームを作り、そこにパネルを貼り付けている。
0.5秒ごとに再描画をして、赤い四角形を描画している。

今MyPanelクラスのコンストラクタでScoreクラスとTitleクラスをインスタンス化したのをコメントアウトしています。
これで実行すると四角形がきちんと描画され、0.5秒ごとに”12345”と”6789”も表示されます。

次にコメントアウトをやめて
title = new Title();
score = new Score();
を記述した状態で実行すると四角形と”6789”は表示されず、”12345”だけ0.5秒ごとに表示されました。つまりpaintComponentメソッドが動いていませんでした。
フレームをいじると四角形も”6789”も表示されます。

下にScoreクラスとTitleクラスを載せておきますが、これをインスタンス化しただけでpaintComponentメソッドが呼ばれなくなるのはどうしてなのでしょうか?
ScoreクラスとTitleクラスにpaintComponentメソッドを妨げるような記述があるからだと予想はできるのですが原因が何かわかりません。
わかる方がいればよろしくお願いします!

ScoreクラスとTitleクラス

コード public class Score{ int myScore; //スコア int highScore; //ハイスコア Color scoreColor; //スコア表示の色 Font scoreFont; //スコア表示のフォント /** * コンストラクタ */ public Score(){ myScore = 0; highScore = 0; scoreColor = Color.BLACK; scoreFont = new Font(Font.MONOSPACED, Font.BOLD, 10); } /** * MyScoreのセッター */ public void setMyScore(int myScore){ this.myScore = myScore; } /** * MyScoreのゲッター */ public int getMyScore(){ return myScore; } /** * 得点加算 * @param point 追加する得点 */ public void addMyScore(int point){ myScore += point; } /** * highScore更新 */ public void cmpareScore(){ if(myScore > highScore){ highScore = myScore; } } /** * MyScore描画 * @param g グラフィック変数 */ public void drawMyScore(Graphics g){ g.setColor(scoreColor); g.setFont(scoreFont); g.drawString("score:" + myScore, 30, 30); } /** * highScore描画 * @param g グラフィック変数 */ public void drawHighScore(Graphics g){ g.setColor(scoreColor); g.setFont(scoreFont); g.drawString("highScore:" + highScore, 420, 30); } /** * MyScoreの初期化 */ public void initMyScore(){ myScore = 0; } } public class Title{ Color titleColor; //タイトル表示の色 Font mainTitleFont; //メインタイトル表示のフォント Font subTitleFont; //サブタイトル表示のフォント int blinkCount; //アニメーション用点滅カウンタ /** * コンストラクタ */ public Title(){ titleColor = Color.BLACK; mainTitleFont = new Font(Font.MONOSPACED, Font.BOLD, 30); subTitleFont = new Font(Font.MONOSPACED, Font.BOLD, 15); } /** * ゲームスタートタイトル表示 * @param g グラフィック変数 */ public void drawGameStartTitle(Graphics g){ g.setColor(titleColor); g.setFont(mainTitleFont); g.drawString("Shooting", 150, 150); blinkCount++; /**点滅処理(偶数の場合のみ表示)*/ if(blinkCount % 2 == 0){ g.setFont(subTitleFont); g.drawString("hit SPACE key", 200, 350); } } /** * ゲームオーバータイトル表示 * @param g グラフィック変数 */ public void drawGameOverTitle(Graphics g){ g.setColor(titleColor); g.setFont(mainTitleFont); g.drawString("GAMEOVER", 150, 150); } }

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

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

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

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

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

guest

回答2

0

質問者さんのコードだとフレームやパネルなどのコンポーネント階層の構築処理と並行して他のスレッドからrepaintを呼び出しているため、タイミング如何によって中途半端な状態のコンポーネントへrepaintをする可能性があると思います。それが動作を不安定にする要因になっているのでは?(なお自分はWindows10 2core, JDK1.8u101 64bit/Eclipse Debug実行でやってみましたが再現しません)

そういったことを防ぐにはComponent/JComponentを触る処理を全てEDT(Event Dispatch Thread)上で行うという原則に従うとよいと思います。以下の様に変えるとフレームやパネル、再描画の処理がすべてEDT上で行われるようになるのでそれでうまくいくかどうか試してみてはいかがでしょうか。

java

1// mainメソッドの中 2new Part01(); 3==> 4javax.swing.SwingUtilities.invokeLater(() -> { new Part01(); }); 5 6// MyPanel#runの中 7repaint(); 8==> 9javax.swing.SwingUtilities.invokeLater(() -> { repaint(); });

追記:上は一般的な解決法ではあると思うのですが、repaint自体は別スレッドから呼び出しても大丈夫なつくりになっているので、この件だと上の解決法よりも全てのコンポーネント階層を構築し終わってsetVisible(true)をした後で別スレッドを開始する方が良いかも知れません。

投稿2016/10/07 08:32

編集2016/10/07 08:43
KSwordOfHaste

総合スコア18394

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

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

0

ベストアンサー

「public void initialization()」の「score.initMyScore();」のコメントアウトを解除した結果、質問内容の現象が起きました。

フレーム表示とパネル描画のタイミングの問題だと思います。

Part01のコンストラクタのに記述している「setVisible(true);」の処理を一番最後に移動したら、画面に赤い四角形が表示され、コンソールに以下のように表示されました。

a 12345 6789 12345 6789 ・ ・ ・

投稿2016/10/07 06:51

java-beginner

総合スコア452

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

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

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

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

ただいまの回答率
85.48%

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

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

質問する

関連した質問