- ベストアンサー
マウスクリックで別のスレッドを動かしたい
- マウスクリックで別のスレッドを動かしたい場合、JavaのAppletクラスを使用して実現することができます。
- このコードでは、マウスクリックイベントを検知して画像を表示し、別のスレッドで画像を移動させています。
- Appletクラスを継承し、RunnableとMouseListenerのインターフェースを実装し、init()、mouseClicked()、run()、move()、paint()などのメソッドを定義しています。
- みんなの回答 (5)
- 専門家の回答
質問者が選んだベストアンサー
> 見た目は同じですが 同じではないです。マウスボタンをクリックしたときにx2,y2の値が違うので、最初の表示位置が違います。それを気にするかどうかは質問者さん次第。 元の質問文にあるコードだとth2が実行を開始するまでx2,y2を更新しないようになっていると思ったので、ANo.3ではそれに合わせました。
その他の回答 (4)
- salsberry
- ベストアンサー率69% (495/711)
> という、今までの内容のままでいいという意味でしょうか。 質問文に書かれていたのとmove()メソッドの中身が異なるので、「今までの内容のまま」というのが何を指すのかが分かりません。 あと、私の案の「mouseIsClickedがtrueのときだけvx2,vy2,x2,y2の更新を行う」の「mouseIsClickedがtrueのときだけ」の部分が反映されていませんが、マウスボタンをクリックする前からx2やy2の座標を動かしたいのであればそのままでもいいです。
お礼
salsberryさん、有難うございます。 確かに、「mouseIsClickedがtrueのときだけvx2,vy2,x2,y2の更新を行う」の意味が理解出来て いませんでした。 「マウスボタンをクリックする前からx2やy2の座標を動かしていて」、イメージの表示だけを [boolean]でとっていました。 見た目は同じですが、プログラム的には何か変わるのでしょうか。 宜しくお願いします。 =========================================================================== public class ImgMove4 extends Applet implements Runnable , MouseListener { private int width , height ; private Thread th1 , th2 ; private boolean bLoopEnd = false ; private int x1 = 30 , y1 = 100 ; private int x2 = 80 , y2 = 150 ; Image img1 , img2 ; AudioClip sound , sound2 ; private int vx1 = 2 , vy1 = 1 ; private int vx2 = 1 , vy2 = 1 ; Dimension d ; boolean flag = false ; public void init() { d = getSize() ; width = d.width ; height = d.height ; this.addMouseListener(this) ; img1 = getImage( getDocumentBase() , "ambulance.jpg" ) ; img2 = getImage( getDocumentBase() , "firecar.jpg" ) ; // オーディオの獲得 sound = getAudioClip( getDocumentBase() , "UFO.wav" ) ; sound.play() ; } public void mouseEntered( MouseEvent e) { sound.play() ; } public void mouseClicked(MouseEvent e) { flag = true ; } public void start() { if(th1 == null) { th1 = new Thread(this); th1.start(); } } public void stop() { if( th1 != null ) { th1 = null ; } } public void run() { while(bLoopEnd == false) { move() ; repaint() ; try{ Thread.sleep( 10 ) ; } catch (InterruptedException e ) {} } } private void move() { if( x1 >= width - 130 ) { vx1 =- vx1 ; } if( y1 >= height - 110 ) { vy1 =- vy1 ; } if( x1 < 0 ) { vx1 =- vx1 ; } if( y1 < 0 ) { vy1 =- vy1 ; } x1 += vx1 ; y1 += vy1 ; if(flag == true) { if( x2 >= width - 130 ) { vx2 =- vx2 ; } if( y2 >= height - 110 ) { vy2 =- vy2 ; } if( x2 < 0 ) { vx2 =- vx2 ; } if( y2 < 0 ) { vy2 =- vy2 ; } x2 += vx2 ; y2 += vy2 ; } } public void update( Graphics g1 ) { paint( g1 ) ; } public void paint( Graphics g1 ) { g1.drawImage( img1 , x1 , y1 , this ) ; if(flag == true) { g1.drawImage( img2 , x2 , y2 , this ) ; } } public void mouseExited(MouseEvent e) { } public void mousePressed(MouseEvent e) { } public void mouseReleased(MouseEvent e){ } }
- salsberry
- ベストアンサー率69% (495/711)
> 今の状態は、「アプレットは初期化されていません」とコメントが出るだけです。 きっとthis.addMouseListener(new MyImage3(this));のところで例外が出ているのでしょう。 MyImage3はAppletのサブクラスとして定義されていますが、Appletの中から他のAppletをnewしてもダメです。 また、MyImage3のstart()を呼んでくれる人はどこにもいないのでth2が実行を開始することもありません。 > もしシングルスレッドでこのプログラムを実行させるにはどこをどのように、 > 修正してやれば良いのでしょう。 私だったらこうします。 ・ImgMove3にmouseIsClickedというboolean型のインスタンス変数を追加して、初期値をfalseとしておく。 ・ImgMove3のx2,y2,vx2,vy2のコメントを外す ・ImgMove3のinit()メソッドの中のthis.addMouseListener(new MyImage3(this));を消す ・ImgMove3のmouseClicked()メソッドの中で、mouseIsClicked=true;とする ・ImgMove3のpaint()メソッドの中で、mouseIsClickedがtrueのときだけimg2の描画を行う。img1の描画は元のまま。 ・ImgMove3のmove()メソッドの中で、vx1,vy1の更新に加えてx1,y1の更新も行う。 ・ImgMove3のmove()メソッドの中で、mouseIsClickedがtrueのときだけvx2,vy2,x2,y2の更新を行う。 ・要らなくなったMyImage3クラスを消す
お礼
salsberryさん、有難うございます。 何とかうまく実行出来ました。 ところで >・ImgMove3のmove()メソッドの中で、vx1,vy1の更新に加えてx1,y1の更新も行う。 >・ImgMove3のmove()メソッドの中で、mouseIsClickedがtrueのときだけvx2,vy2,x2,y2の 更新を行う。 というのは、 ================================================ private void move() { if( x1 >= width - 130 ) { vx1 =- vx1 ; } if( y1 >= height - 110 ) { vy1 =- vy1 ; } if( x1 < 0 ) { vx1 =- vx1 ; } if( y1 < 0 ) { vy1 =- vy1 ; } x1 += vx1 ; y1 += vy1 ; if( x2 >= width - 130 ) { vx2 =- vx2 ; } if( y2 >= height - 110 ) { vy2 =- vy2 ; } if( x2 < 0 ) { vx2 =- vx2 ; } if( y2 < 0 ) { vy2 =- vy2 ; } x2 += vx2 ; y2 += vy2 ; } ================================================ という、今までの内容のままでいいという意味でしょうか。 宜しくお願いします。
- covachan
- ベストアンサー率38% (46/120)
>後からの画像の追加・移動には、別のスレッドを立てていますが、そのやり方が正しいのか どうか自信がありません。 結論をいうと、そんなのわかりません。 マルチスレッドの目的は並行処理です。 つまり、複数の処理を同時に実行する場合に有効ですが、 そのケースに当たるかどうかは今のところ主しかわかりえません。 ただ、処理はそれほど時間がかからないのであれば シングルスレッドでよいと思います。 マルチスレッドはデッドロックなどの副作用を生みやすくし、 いきなりハードルが上がるものです。
お礼
covachanさん、レスあリがとうございます。 ところで、もしシングルスレッドでこのプログラムを実行させるにはどこをどのように、 修正してやれば良いのでしょう。 今の状態は、「アプレットは初期化されていません」とコメントが出るだけです。 宜しくお願いします。
- SherlockHolmes2
- ベストアンサー率40% (175/429)
どううまく動かないのか詳しく書いて頂かないと・・・。 ただソースリストを貼っただけで、「デバッグして下さい」と言っているようなものですよ。
お礼
SherlockHolmes2さん、回答有難うございます、確かに仰る通りかもです。 最初はある画像をごく普通にウインドウ内の任意の座標を取得して動かしています。 マウスクリックにより、もう1個の画像を追加して同じように任意の座標を取得して動かした い、というプログラムです。 後からの画像の追加・移動には、別のスレッドを立てていますが、そのやり方が正しいのか どうか自信がありません。 また、このような場合には、必ず別のスレッドを立てる必要があるのでしょうか。 最初から2個の画像を動かす場合には、1本のスレッドでエラーなく動きました。 他のプログラムも参考にして調べてみましたが少なくとも、最初から複数個の画像が動いてい ても、スレッドは1本しか立てていません。 問題は後から画像移動とかを追加する場合の考え方(同じスレッドにするのか、別スレッドに するのか、どちらでもよいのか、その場合にはどのような処理(同期をとるとか、そのやり方) をするのか)、が良く理解出来ていない所です。 未だ未だ初心者の域を出ないことを実感しています、皆様のご教示宜しくお願いします。
お礼
salsberryさん 有り難うございました。今後ともよろしくお願いします。