2016-04-11 12 views
0

アニメーションを表示するために円を連続的に再描画しています。私は、クリックすると円が異なる色になるようにしたいと思います。 MouseListenerを実装してmouseClickedイベントを取得しようとしたときに、動作しませんでした。私はそれが一定の再塗装に起因すると信じています。このサークルをバウンスさせてマウスクリックを捕まえる別の方法はありますか?私はテストするためにKeyEventを追加し、うまくいきました。これは別のプログラムから呼び出されたため、「メイン」はありません。キャンバス上でシェイプ上でmouseClickedイベントが頻繁に再描画される

import java.awt.*; 
import java.awt.event.KeyEvent; 
import java.util.Random; 
import java.util.Timer; 

public class Catch extends Canvas { 

    int xCor, yCor, xMove, yMove; 
    Color currentColor; 
    Random ranNumber; 
    boolean flashing = false; 

    public Catch() { 
     enableEvents(java.awt.AWTEvent.KEY_EVENT_MASK); 
     requestFocus(); 
     xCor = 500; 
     yCor = 350; 
     xMove = 5; 
     yMove = 5; 
     currentColor = Color.black; 
     ranNumber = new Random(); 
     Timer t = new Timer(true); 
     t.schedule(new java.util.TimerTask() { 
      public void run() { 
       animate(); 
       repaint(); 
      } 
     }, 10, 10); 

    } 

    public void paint(Graphics g) { 
     g.setColor(currentColor); 
     g.fillOval(xCor, yCor, 20, 20); 
    } 

    public void processKeyEvent(KeyEvent e) { 
     if (e.getID() == KeyEvent.KEY_PRESSED) { 
      if (e.getKeyCode() == KeyEvent.VK_SPACE) { 
       flashing = !flashing; 
      } 
     } 
    } 

    public void animate() { 
     xCor += xMove; 
     yCor += yMove; 

     // and bounce if we hit a wall 
     if (xCor < 0 || xCor + 20 > 1000) { 
      xMove = -xMove; 
     } 
     if (yCor < 0 || yCor + 20 > 700) { 
      yMove = -yMove; 
     } 

     if (flashing) { 
      int r = ranNumber.nextInt(256); 
      int g = ranNumber.nextInt(256); 
      int b = ranNumber.nextInt(256); 
      currentColor = new Color(r, g, b); 
     } 
    } 

    public boolean isFocusable() { 
     return true; 
    } 
} 
+1

を見ている必要があります[マウスリスナーの作成方法](http://docs.oracle.com/javase/tutorial/uiswing/events/mouselistener.html) 'Canvas'を使用している理由は何ですか? 'java.awt.Canvas'を使用する主な理由は' BufferStrategy'を使うことです。そうでなければ、おそらく 'JPanel'を使用して空きのためにダブルバッファリングを得るべきです。 – MadProgrammer

+0

また、イベント処理は本当にです実際には日付が – MadProgrammer

+0

となっています。基本的な問題は、タイマーとイベントディスパッチスレッド間の競合状態になる可能性があります。マウスイベントについて通知された時点で、その位置は既に更新されています。クリティカルエリアの周りのスイングタイマーや同期ブロックを使用している可能性があります – MadProgrammer

答えて

1

あなたのアプローチは少し古くなって、私たちはこれ以上enableEventsを使用する傾向があるが、代わりに特定のイベントに関する通知を提供する異なる「オブザーバー」の数を使用しません。

私はまたKeyListenerの使用を避け、代わりにKeyListenerのshortcommingsの多くを克服するために設計されたKey Bindings APIを使用すると思いPainting in AWT and SwingPerforming Custom Paintingを見て、How to Write a Mouse Listener

を持つことから始めたいです。

カッティングエッジを使用すると、AWTの知識を持っているならば、Swingにステップアップ、JavaFXのを使用するのであろうが単純だろう、例えば:

import java.awt.Color; 
import java.awt.Dimension; 
import java.awt.EventQueue; 
import java.awt.Graphics; 
import java.awt.Graphics2D; 
import java.awt.Point; 
import java.awt.Rectangle; 
import java.awt.event.ActionEvent; 
import java.awt.event.ActionListener; 
import java.awt.event.MouseAdapter; 
import java.awt.event.MouseEvent; 
import java.awt.geom.Ellipse2D; 
import java.awt.geom.Rectangle2D; 
import java.util.Random; 
import javax.swing.JFrame; 
import javax.swing.JPanel; 
import javax.swing.Timer; 
import javax.swing.UIManager; 
import javax.swing.UnsupportedLookAndFeelException; 

public class Test { 

    public static void main(String[] args) { 
     new Test(); 
    } 

    public Test() { 
     EventQueue.invokeLater(new Runnable() { 
      @Override 
      public void run() { 
       try { 
        UIManager.setLookAndFeel(UIManager.getSystemLookAndFeelClassName()); 
       } catch (ClassNotFoundException | InstantiationException | IllegalAccessException | UnsupportedLookAndFeelException ex) { 
        ex.printStackTrace(); 
       } 

       JFrame frame = new JFrame("Testing"); 
       frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); 
       frame.add(new TestPane()); 
       frame.pack(); 
       frame.setLocationRelativeTo(null); 
       frame.setVisible(true); 
      } 
     }); 
    } 

    public class TestPane extends JPanel { 

     private Ball ball; 

     public TestPane() { 
      ball = new Ball(); 
      Timer timer = new Timer(40, new ActionListener() { 
       @Override 
       public void actionPerformed(ActionEvent e) { 
        ball.update(getSize()); 
        repaint(); 
       } 
      }); 
      timer.start(); 

      addMouseListener(new MouseAdapter() { 
       @Override 
       public void mousePressed(MouseEvent e) { 
        ball.setHighlighted(ball.wasClicked(e.getPoint())); 
       } 
      }); 
     } 

     @Override 
     public Dimension getPreferredSize() { 
      return new Dimension(200, 200); 
     } 

     @Override 
     protected void paintComponent(Graphics g) { 
      super.paintComponent(g); 
      Graphics2D g2d = (Graphics2D) g.create(); 
      ball.paint(g2d); 
      g2d.dispose(); 
     } 

    } 

    public class Ball { 

     private int radius = 10; 
     private int xDelta, yDelta; 
     private Ellipse2D shape = new Ellipse2D.Double(0, 0, radius * 2, radius * 2); 
     private boolean highlighted; 
     private int cycleCount; 

     public Ball() { 
      Random rnd = new Random(); 
      xDelta = rnd.nextInt(3) + 1; 
      yDelta = rnd.nextInt(3) + 1; 
     } 

     public void update(Dimension bounds) { 
      Rectangle shapeBounds = shape.getBounds(); 
      shapeBounds.x += xDelta; 
      shapeBounds.y += yDelta; 
      if (shapeBounds.x + shapeBounds.width > bounds.width) { 
       shapeBounds.x = bounds.width - shapeBounds.width; 
       xDelta *= -1; 
      } else if (shapeBounds.x < 0) { 
       shapeBounds.x = 0; 
       xDelta *= -1; 
      } 
      if (shapeBounds.y + shapeBounds.height > bounds.height) { 
       shapeBounds.y = bounds.height - shapeBounds.height; 
       yDelta *= -1; 
      } else if (shapeBounds.y < 0) { 
       shapeBounds.y = 0; 
       yDelta *= -1; 
      } 
      shape.setFrame(shapeBounds); 

      if (highlighted) { 
       cycleCount++; 
       if (cycleCount > 12) { 
        highlighted = false; 
       } 
      } 
     } 

     public boolean wasClicked(Point p) { 
      return shape.contains(p); 
     } 

     public void setHighlighted(boolean value) { 
      highlighted = value; 
      cycleCount = 0; 
     } 

     public void paint(Graphics2D g) { 
      if (highlighted) { 
       g.setColor(Color.RED); 
      } else { 
       g.setColor(Color.BLUE); 
      } 
      g.fill(shape); 
     } 
    } 

} 

またHow to use Swing Timers

+0

スイングタイマーは間違いなくマウスイベントに役立ちました。私はそれをプロジェクトに組み込んでいます。ありがとう! – AnotherJones

+0

サンプルコードを書き留めていただきありがとうございます。そこには私が以前に使ったことのないものがいくつかありますので、何が起こっているのかを確実に把握するために、私はそれを1行ずつ調べています。リソースリンクに加えてサンプルを持っていることは助けになりました...そして私はそれを得ています。しかし、キーバインディングの資料を読んだ後、私は以前よりももっと近く感じることはありません。 'KeyListener'は時代遅れだと信じていますが、理解するのがずっと簡単です。私はKey Bindingsに関するいくつかの記事を探しましたが、私の脳ではクリックしていません。 – AnotherJones

+0

キーバインドには時間がかかりますが、再利用可能な大きなコード要素である「アクション」の部分を表しているので、メニュー項目、ボタン、キーバインディングに同じ「アクション」を使用して非常に便利 – MadProgrammer

関連する問題