0

私の単純なコードの一部です。左ボタンをクリックした後、楕円をカーソルの X 軸の位置に移動したいと考えています。問題は、楕円の最後の位置しか表示されないことです (既に停止している場合)。私が望むように、楕円形の各動きがカーソルの位置に入るのを見たいと思います。提案をありがとう。

import java.awt.*;
import java.awt.event.MouseEvent;
import java.awt.event.MouseListener;
import javax.swing.*;

public class Testfile extends JPanel implements Runnable,MouseListener{
public static JFrame frame;
public int x;
public int y;
public int pointX;
public int pointY;

 public void paintComponent(Graphics g){
     super.paintComponent(g);

     g.fillOval(x, y, 20, 20);
 }

 public static void main(String args[])throws InterruptedException{
     Testfile z=new Testfile();
     z.setBackground(Color.cyan);

     frame=new JFrame("Test");
     frame.setSize(500,500);
     frame.add(z);
     frame.addMouseListener(z);
     frame.setVisible(true);
}
public void mouseClicked(MouseEvent e){
    pointX=(int)MouseInfo.getPointerInfo().getLocation().getX();
    pointY=(int)MouseInfo.getPointerInfo().getLocation().getY();

    try{
    while(x!=pointX){
        x=x+1;
        Thread.sleep(10);
        repaint();
        }
    }
        catch(InterruptedException v){System.out.println(v);}
}
4

2 に答える 2

3

.while ブロックの repaint メソッドが思い通りに機能しないと思います

あなたの問題は、再描画が「機能しない」こととは何の関係もありません。すべては、Swing イベントスレッドを結び付けることと関係があります。Swing Event Dispatch Thread (または EDT) (GUI の描画とユーザーとの対話を担当するスレッド) で実行時間の長いプロセスを実行すると、GUI がフリーズし、EDT が解放されるまで自分自身を描画したり応答したりしなくなります。

Thread.sleep(...)解決策: while (true) ループまたはSwing イベント スレッドを使用しないでください。また:

  • 代わりに Swing Timer を使用して、アニメーションの「ループ」として機能させます。
  • 別の可能な解決策は、バックグラウンド スレッドを使用しThread.sleep(...)て .

また:

  • MouseListener を JFrame に追加するのではなく、描画 JPanel に追加してください。そうしないと、タイトル バーの高さだけ y 方向にずれることがわかります。
  • 前者の方が寛容であるため、mousePressed(...)notの方法を使用してください。mouseClicked(...)
  • mousePressed で deltaX と deltaY を取得します。これは、pointX から x を減算し、pointY から y を減算することによって、円が進むべき方向です。
  • x と y および pointX ( manHattanDistance = Math.abs(x - pointX) + Math.abs(y - pointY);) と pointY の間のマンハッタン距離をチェックし、最小値を下回った場合はタイマーを停止することで、コードが機能するようになりました。また、以前のマンハッタンの距離を保存し、古いものと新しいものの違いをチェックして、楕円形がオーバーシュートしないようにしました。
  • double を使用して x、y、pointX、pointY などを保持し、描画時に int にキャストします。
  • Graphics オブジェクトを Graphics2D にキャストし、RenderingHints を使用してアンチエイリアスをオンにすることを忘れないでください。これにより、よりきれいなグラフィックが作成されます。
  • 「マジック」ナンバーは避けましょう。代わりに定数を使用してください。
  • 左上隅ではなく、円の中心に x と y を使用することを検討してください。

たとえば、私のpaintComponent(...)メソッドは次のようになります。

public void paintComponent(Graphics g) {
  super.paintComponent(g);
  Graphics2D g2 = (Graphics2D) g;
  g2.setRenderingHint(RenderingHints.KEY_ANTIALIASING,
        RenderingHints.VALUE_ANTIALIAS_ON);

  // RADIUS is an int const and = 10
  g.fillOval((int) x - RADIUS, (int) y - RADIUS, 2 * RADIUS, 2 * RADIUS);
}
于 2013-07-26T22:33:36.290 に答える