Javaに関する様々な情報をご紹介します。

Javaに関する様々な情報をご紹介します。
評価

0

threadの使い方について

絵画した黒丸を上から下に流すというプログラムを、指定した時間差(例えば5秒後に2つ、7秒後に1つ、10秒後に2つといった感じ)で動かしたいのですが、Threadがうまく使えず、表示もされなくなってしまいました。
どうすればいいのかわからないので、教えていただけますでしょうか。

//game.java
import javax.swing.*;
import java.awt.*;
import java.awt.event.*;
import java.util.concurrent.*;


class MovingFrame extends JFrame{

    public MovingFrame(){
        this.setTitle("Random Frame");
        this.setSize(900,600);

    this.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
    this.setVisible(true);
    }
    public static void main(String argv[]) {
    
    Thmove mv1 = new Thmove();
    Thmove mv2 = new Thmove();    
    
    mv1.start();
    mv2.start();
    }

}


//Thmove.java
import javax.swing.*;
import java.awt.*;
import java.awt.event.*;

public class Thmove extends Thread{
    public void run(){
            try{
                sleep(5000);
            }catch(InterruptedException e){
        }        
        MovingPanel amv = new MovingPanel();
    }
}
class MovingPanel extends JPanel implements ActionListener{
    private Timer timer;
  private int x,y;
  MovingPanel(){
    x=30; y=0;
    timer = new Timer(1, this);
  }
  public void paintComponent(Graphics g) {
    super.paintComponent(g);
    g.fillOval(x,y,30,30);
  }
 
  public void actionPerformed(ActionEvent e){
    y=y+5;
    if (y>600) timer.stop();
    this.repaint();  
  }
    }

2

回答

91994

閲覧

2件の回答

評価

0

(1)質問者さんのコードではJPanelをnewしているだけで
JFrameのcontentPaneに配置していません。なのでこの
JPanelに何を描画しても画面に表示されません。

(2)基本的にawt/swing関連の処理(コンポーネントの生成
やコンポーネントへのメソッド呼び出し)はEDT(Event 
dispatch thread)上でしかやってはいけません。アプリケ
ーション開始時にJFrame(やそのcontentPane)の初期化と
JFrameの可視化(setVisible(true))をmainスレッドでやっ
たりしますがそれはあくまで例外と考えたほうがよいと思
います。

質問者さんがやりたいことを実現するにはスレッドを起こ
す必要性はないです。一般にアニメーションを行うために
は描画状態を更新する契機があればよいので質問者さんの
コードにあるTimerを使ってその契機を作ってやれば済み
ます。このプログラムでの描画状態は黒丸ですから、黒丸
をオブジェクトにしてそこへ以下のような状態を持たせま
す。

(A)プログラム開始時からどのくらい時間が経過すれば表
示状態になるか
(B)表示状態になったときどの座標に表示させるか
(C)表示状態になってから1回毎に(あるいは経過時間に応
じて)どの程度移動させるか
(D)いつ非表示にするか(座標がある位置に到達したらと
か、ある経過時間をすぎたらとか)

Timerのイベントハンドラーでは複数の黒丸オブジェクト
の状態を更新してMovingPanelへrepaintします。
MovingPanelでは全ての黒丸をその状態に応じて描画して
やります。(状態の更新や描画を黒丸自身のメソッドにし
てやる方が自然かな...)

蛇足ですがTimerのインターバルが1ミリ秒というのは不必
要に高い頻度になると思います。通常のディスプレーでは
1秒にせいぜい100フレーム程度ですしTVですと24フ
レームですからもっとずっと長くしても充分な品質のアニ
メーションになると思います。

評価

0

ありがとうございます!
教えてもらった通り書いて試してみます!

質問から6ヶ月以上経過しているので、回答を書き込むことはできません。