2

問題は、このボールをドラッグしてクリックを終了した後、指定された新しい y コンポーネントに従って再描画することになっていることです。これは最終的な重力から計算され、ループ内の既存の y コンポーネントに追加される速度に追加されます。

私は何度もデバッグしましたが、頭にぶつけることができません。

そのはず.. ドラッグした場所に移動 >>> 離すと、地面にぶつかるまで落下するはずです。

よろしくお願いします。

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

public class DragBallPanel extends JPanel implements MouseListener, MouseMotionListener
{
     private static final int BALL_DIAMETER = 40;
     private int screen_size_x = 300;
     private int screen_size_y = 300;
     private int ground_lvl = screen_size_y - 15;

     private int _ballX     = ground_lvl/2;
     private int _ballY     = ground_lvl - BALL_DIAMETER;
     private final double GRAVITY = -9.8;
     private double velocity;
     private static final double TERM_VEL = -100;

     private int _dragFromX = 0;
     private int _dragFromY = 0;

     private boolean _canDrag  = false;


     public DragBallPanel() throws InterruptedException
     {
        setPreferredSize(new Dimension(screen_size_x, screen_size_y));
        setBackground(Color.darkGray);
        setForeground(Color.darkGray);

        this.addMouseListener(this); 
        this.addMouseMotionListener(this);
    }

    public void paintComponent(Graphics g)
     {
        super.paintComponent(g);   // Required for background.
          g.setColor (Color.green);
          g.fillRect (0, 280, 400, 50 );
          g.setColor (Color.black);
        g.fillOval(_ballX, _ballY, BALL_DIAMETER, BALL_DIAMETER);

    }

    public void mousePressed(MouseEvent e)
    {
        int x = e.getX();
        int y = e.getY();

        if (x >= _ballX && x <= (_ballX + BALL_DIAMETER)
                && y >= _ballY && y <= (_ballY + BALL_DIAMETER))\
          {
            _canDrag = true;
            _dragFromX = x - _ballX;
            _dragFromY = y - _ballY;
        } else
          {
            _canDrag = false;
        }
    }

    //===== mouseDragged ======
    /** Set x,y  to mouse position and repaint. */
    public void mouseDragged(MouseEvent e)
    {
        if (_canDrag)
          {   // True only if button was pressed inside ball.
            //--- Ball pos from mouse and original click displacement
            _ballX = e.getX() - _dragFromX;
            _ballY = e.getY() - _dragFromY;

            //--- Don't move the ball off the screen sides
            _ballX = Math.max(_ballX, 0);
            _ballX = Math.min(_ballX, getWidth() - BALL_DIAMETER);

            //--- Don't move the ball off top or bottom
            _ballY = Math.max(_ballY, 0);
            _ballY = Math.min(_ballY, getHeight() - BALL_DIAMETER);

            this.repaint();
        }
    }

    public void mouseExited(MouseEvent e)
    {
          while(_ballY < ground_lvl)
          {
                 simulateGravity();
          }   
    }

     public void simulateGravity()
     {
         if(_canDrag)
         {
             try{
                 velocity = velocity + GRAVITY;

               if (velocity < TERM_VEL)
                 {
                    velocity = TERM_VEL;
                 }

                if (_ballY >= ground_lvl - BALL_DIAMETER)
                {
                   velocity = velocity/4; 
                } 
                _ballY += velocity;
                 Thread.sleep(400);
                 this.repaint();//**problem occurs here**

              }catch(InterruptedException ie)
              {
              }
         }
     }

    public void mouseMoved   (MouseEvent e){}
    public void mouseEntered (MouseEvent e){}
    public void mouseClicked (MouseEvent e){}
    public void mouseReleased(MouseEvent e){}
}

main() クラス

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


public class DragDemo extends JApplet
{
    public static void main(String[] args) throws InterruptedException
    {
        JFrame window = new JFrame();
        window.setTitle("Drag Demo");
        window.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
          //window.add(new DragBallPanel());
        window.setContentPane(new DragBallPanel());
          window.setResizable(false);
        window.pack();
        window.show();
    }

    public DragDemo() throws InterruptedException
    {
        new DragBallPanel();
    }
}
4

2 に答える 2

4

このSSCCEは、コードの問題を示し始めます。

  1. コードをコンパイルします。
  2. それを実行します。
  3. ボールを上にドラッグします。
  4. ボールを離します。
  5. 作図領域からマウスを離すと、..
  6. ボールが上に落ちる!

Y 値を逆さまに取得したようです。それらは画面の上部から始まり、下に向かって進みます。また、コードは無限ループで EDT をブロックしていました。これを解決するには、 Swing を使用してアニメーションを実行しTimerます。

SSCCE のドキュメントを読んで、わからないことがあれば質問してください。私は説明するのに適しています。:)


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

public class DragBallPanel extends JPanel implements MouseListener, MouseMotionListener
{

    private static final int BALL_DIAMETER = 40; // Diameter of ball

    private int screen_size_x = 300;
    private int screen_size_y = 300;
    private int ground_lvl = screen_size_y - 15;

    private int _ballX     = ground_lvl/2;
    private int _ballY     = ground_lvl - BALL_DIAMETER;
    private final double GRAVITY = -9.8;
    private double velocity;
    private static final double TERM_VEL = 100;

    private int _dragFromX = 0;    // pressed this far inside ball's
    private int _dragFromY = 0;    // bounding box.

    /** true means mouse was pressed in ball and still in panel.*/
    private boolean _canDrag  = false;

    public DragBallPanel()
    {
        setPreferredSize(new Dimension(screen_size_x, screen_size_y));
        setBackground(Color.darkGray);
        setForeground(Color.darkGray);

        this.addMouseListener(this);
        this.addMouseMotionListener(this);
    }

    public void paintComponent(Graphics g)
     {
        super.paintComponent(g);   // Required for background.
          g.setColor (Color.green);
          g.fillRect (0, 280, 400, 50 );
          g.setColor (Color.black);
        g.fillOval(_ballX, _ballY, BALL_DIAMETER, BALL_DIAMETER);

    }

    public void mousePressed(MouseEvent e)
    {
        int x = e.getX();   // Save the x coord of the click
        int y = e.getY();   // Save the y coord of the click

        if (x >= _ballX && x <= (_ballX + BALL_DIAMETER)
                && y >= _ballY && y <= (_ballY + BALL_DIAMETER)) {
            _canDrag = true;
            _dragFromX = x - _ballX;  // how far from left
            _dragFromY = y - _ballY;  // how far from top
        } else {
            _canDrag = false;
        }
    }

    //========= mouseDragged =================
    /** Set x,y  to mouse position and repaint. */
    public void mouseDragged(MouseEvent e)
    {
        if (_canDrag) {   // True only if button was pressed inside ball.
            //--- Ball pos from mouse and original click displacement
            _ballX = e.getX() - _dragFromX;
            _ballY = e.getY() - _dragFromY;

            //--- Don't move the ball off the screen sides
            _ballX = Math.max(_ballX, 0);
            _ballX = Math.min(_ballX, getWidth() - BALL_DIAMETER);

            //--- Don't move the ball off top or bottom
            _ballY = Math.max(_ballY, 0);
            _ballY = Math.min(_ballY, getHeight() - BALL_DIAMETER);

            this.repaint(); // Repaint because position changed.
        }
    }

    //====================================================== method mouseExited
    /** Turn off dragging if mouse exits panel. */
    public void mouseExited(MouseEvent e)
     {
         System.out.println("Exited: " + e);
        //_canDrag = false;
        runGravity();
        /*  while(_ballY < ground_lvl)
          {
             simulateGravity();
          }*/
    }

    Timer timer;
    ActionListener animate;

    public void runGravity() {
        if (animate==null) {
            animate = new ActionListener() {
                public void actionPerformed(ActionEvent ae) {
                    System.out.println("Ground: " + (_ballY-ground_lvl));
                    if (_ballY > ground_lvl) {
                        timer.stop();
                    } else {
                        simulateGravity();
                    }
                }
            };
            timer = new Timer(100,animate);
        }
        timer.start();
    }

     public void simulateGravity()
     {
         System.out.println("_canDrag: " + _canDrag);
         if(_canDrag)
         {

             velocity = velocity + GRAVITY;

           if (velocity > TERM_VEL)
             {
                velocity = TERM_VEL;
             }

            if (_ballY >= ground_lvl - BALL_DIAMETER)
            {
                //We have hit the "ground", so bounce back up. Reverse
                //the speed and divide by 4 to make it slower on bouncing.
                //Just change 4 to 2 or something to make it faster.
               velocity = velocity/4;
            }
            _ballY += velocity;
             //this.revalidate();
             this.repaint();
         }
    }

    public void mouseMoved   (MouseEvent e){}
    public void mouseEntered (MouseEvent e){}
    public void mouseClicked (MouseEvent e){}
    public void mouseReleased(MouseEvent e){}

    public static void main(String[] args) {
        SwingUtilities.invokeLater( new Runnable() {
            public void run() {
                DragBallPanel dbp = new DragBallPanel();
                JOptionPane.showMessageDialog(null, dbp);
            }
        });
    }
}
于 2012-05-20T23:27:23.300 に答える
0

updateUI()の代わりに試してくださいrepaint()

効果がない場合は、コンポーネントを削除して再度追加します。

于 2012-05-20T22:37:57.640 に答える