0

以前の投稿に基づいて変更を加えた後、シングル/ダブルクリック認識を導入することで、次のコードにさらにいくつかの手順を実行しました。マウスがクリックされた場所ではなく、左上隅にボールが作成されるのはなぜですか?

BounceBalls.java

import java.awt.BorderLayout;
import java.awt.Dimension;
import java.awt.Graphics;
import java.awt.Toolkit;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.event.MouseEvent;
import java.awt.event.MouseListener;
import java.util.ArrayList;
import java.util.List;

import javax.swing.JFrame;
import javax.swing.JPanel;
import javax.swing.Timer;

public class BouncingBalls extends JPanel implements MouseListener {

    protected List<RandomBall> randomBalls = new ArrayList<RandomBall>(20);
    protected List<VerticalBall> verticalBalls = new ArrayList<VerticalBall>(20);
    private Container container;
    private DrawCanvas canvas;
    private Boolean doubleClick = false;
    private final Integer waitTime = (Integer) Toolkit.getDefaultToolkit()
            .getDesktopProperty("awt.multiClickInterval");
    private static int canvasWidth = 500;
    private static int canvasHeight = 500;
    public static final int UPDATE_RATE = 30;
    int count = 0;

    public static int random(int maxRange) {
        return (int) Math.round((Math.random() * maxRange));
    }

    public BouncingBalls(int width, int height) {
        canvasWidth = width;
        canvasHeight = height;

        container = new Container();

        canvas = new DrawCanvas();
        this.setLayout(new BorderLayout());
        this.add(canvas, BorderLayout.CENTER);
        this.addMouseListener(this);

        start();

    }

    public void start() {

        Thread t = new Thread() {

            public void run() {

                while (true) {

                    update();
                    repaint();
                    try {
                        Thread.sleep(1000 / UPDATE_RATE);
                    } catch (InterruptedException e) {
                    }
                }
            }
        };
        t.start();
    }

    public void update() {

        for (RandomBall ball : randomBalls) {
            ball.ballBounce(container);

        }
        for (VerticalBall ball : verticalBalls) {
            ball.verticalBounce(container);

        }
    }

    class DrawCanvas extends JPanel {

        public void paintComponent(Graphics g) {

            super.paintComponent(g);
            container.draw(g);
            for (RandomBall ball : randomBalls) {
                ball.draw(g);
            }
            for (VerticalBall ball : verticalBalls) {
                ball.draw(g);
            }
        }

        public Dimension getPreferredSize() {

            return (new Dimension(canvasWidth, canvasHeight));
        }
    }

    public static void main(String[] args) {

        javax.swing.SwingUtilities.invokeLater(new Runnable() {

            public void run() {

                JFrame f = new JFrame("Stack Answer 2");
                f.setDefaultCloseOperation(f.EXIT_ON_CLOSE);
                f.setContentPane(new BouncingBalls(canvasHeight, canvasWidth));
                f.pack();
                f.setVisible(true);
            }
        });
    }

    @Override
    public void mouseClicked(MouseEvent e) {
        // TODO Auto-generated method stub

    }

    @Override
    public void mouseEntered(MouseEvent e) {
        // TODO Auto-generated method stub

    }

    @Override
    public void mouseExited(MouseEvent e) {
        // TODO Auto-generated method stub

    }

    @Override
    public void mousePressed(MouseEvent e) {
        if (e.getClickCount() >= 2) {
            doubleClick = true;
             verticalBalls.add(new VerticalBall(getX(), getY(), canvasWidth, canvasHeight));
            System.out.println("double click");
        } else {
            Timer timer = new Timer(waitTime, new ActionListener() {

                public void actionPerformed(ActionEvent e) {
                    if (doubleClick) {

                        /* we are the first click of a double click */
                        doubleClick = false;
                    } else {
                        count++;
                        randomBalls.add(new RandomBall(getX(), getY(), canvasWidth, canvasHeight));
                        /* the second click never happened */
                        System.out.println("single click");
                    }
                }
            });
            timer.setRepeats(false);
            timer.start();
        }
    }

    @Override
    public void mouseReleased(MouseEvent e) {
        // TODO Auto-generated method stub

    }
}

RandomBall.java

import java.awt.Color;
import java.awt.Graphics;

public class RandomBall {

    public static int random(int maxRange) {
        return (int) Math.round((Math.random() * maxRange));
    }

    private int x;
    private int y;
    private int canvasWidth = 500;
    private int canvasHeight = 500;
    private boolean leftRight;
    private boolean upDown;
    private int deltaX;
    private int deltaY;
    private int radius = 20;
    private int red = random(255);
    private int green = random(255);
    private int blue = random(255);

    RandomBall(int x, int y, int width, int height) {
        this(x, y, width, height, false, false);
    }

    RandomBall(int x, int y, int width, int height, boolean leftRight, boolean upDown) {
        this.x = x;
        this.y = y;
        this.canvasWidth = width;
        this.canvasHeight = height;
        this.leftRight = leftRight;
        this.upDown = upDown;
        updateDelta();
    }

    public void draw(Graphics g) {

        g.setColor(new Color(red, green, blue));
        g.fillOval((int) (x - radius), (int) (y - radius), (int) (2 * radius),
                (int) (2 * radius));
    }

    private void updateDelta() {
        final int minimumMovement = 5;
        final int maxExtra = 10;
        deltaY = minimumMovement + (int) (Math.random() * maxExtra);
        deltaX = minimumMovement + (int) (Math.random() * maxExtra);
    }

    public void ballBounce(Container container) {
        // controls horizontal ball motion
        if (leftRight) {
            x += deltaX;
            if (x >= getWidth()) {
                leftRight = false;
                updateDelta();
            }
        } else {
            x += -deltaX;
            if (x <= 0) {
                leftRight = true;
                updateDelta();
            }
        }
        // controls vertical ball motion
        if (upDown) {
            y += deltaY;

            if (y >= getHeight()) {
                upDown = false;
                updateDelta();
            }
        } else {
            y += -deltaY;
            if (y <= 0) {
                upDown = true;
                updateDelta();
            }
        }

    }

    public void verticalBounce(Container container) {

        // controls vertical ball motion
        if (upDown) {
            y += deltaY;

            if (y >= getHeight()) {
                upDown = false;
                updateDelta();
            }
        } else {
            y += -deltaY;
            if (y <= 0) {
                upDown = true;
                updateDelta();
            }
        }

    }

    public int getX() {
        return x;
    }

    public int getY() {
        return y;
    }

    public int getWidth() {
        return canvasWidth;
    }

    public int getHeight() {
        return canvasHeight;
    }
}

VerticalBall.java

import java.awt.Color;
import java.awt.Graphics;

public class VerticalBall {

    public static int random(int maxRange) {
        return (int) Math.round((Math.random() * maxRange));
    }

    private int x;
    private int y;
    private int canvasWidth = 500;
    private int canvasHeight = 500;
    private boolean upDown;
    private int deltaY;
    private int radius = 20;
    private int red = random(255);
    private int green = random(255);
    private int blue = random(255);

    VerticalBall(int x, int y, int width, int height) {
        this(x, y, width, height, false);
    }

    VerticalBall(int x, int y, int width, int height, boolean upDown) {
        this.x = x;
        this.y = y;
        this.canvasWidth = width;
        this.canvasHeight = height;
        this.upDown = upDown;
        updateDelta();
    }

    public void draw(Graphics g) {

        g.setColor(new Color(red, green, blue));
        g.fillOval((int) (x - radius), (int) (y - radius), (int) (2 * radius),
                (int) (2 * radius));
    }

    private void updateDelta() {
        final int minimumMovement = 5;
        final int maxExtra = 10;
        deltaY = minimumMovement + (int) (Math.random() * maxExtra);
    }

    public void verticalBounce(Container container) {

        // controls vertical ball motion
        if (upDown) {
            y += deltaY;

            if (y >= getHeight()) {
                upDown = false;
                updateDelta();
            }
        } else {
            y += -deltaY;
            if (y <= 0) {
                upDown = true;
                updateDelta();
            }
        }

    }

    public int getX() {
        return x;
    }

    public int getY() {
        return y;
    }

    public int getWidth() {
        return canvasWidth;
    }

    public int getHeight() {
        return canvasHeight;
    }
}

コンテナ.java

import java.awt.Color;
import java.awt.Graphics;

    public class Container {

        private static final int HEIGHT = 500;
        private static final int WIDTH = 500;
        private static final Color COLOR = Color.WHITE;

        public void draw(Graphics g) {

            g.setColor(COLOR);
            g.fillRect(0, 0, WIDTH, HEIGHT);
        }
    }
4

2 に答える 2

2

からではなく、からgetXおよびを使用する必要があります。getYMouseEventJPanel

補足として、個別のスレッドを使用してスイングメソッドを呼び出すことができないため、定期的にGUIを更新するために個別のスレッドを使用することは悪いことです。代わりにスイングタイマーを使用してください。

于 2013-09-23T02:46:35.130 に答える
2

基本的に、それはあなたがそれらを作成するように言っている場所だからです...

verticalBalls.add(new VerticalBall(getX(), getY(), canvasWidth, canvasHeight));

getX()コンポーネントの場所をgetY()取得しています(引数のために0x0に十分近いことがわかります)...

代わりに、MouseEvent情報を使用する必要があります...

public void mousePressed(MouseEvent e) {
    if (e.getClickCount() >= 2) {
        doubleClick = true;
         verticalBalls.add(new VerticalBall(e.getX(), e.getY(), canvasWidth, canvasHeight));
        System.out.println("double click");
    }
}

これにより、問題が発生しますTimer...

代わりに、位置情報を保持するためにいくつかの変数を導入する必要がある場合があります...

final int x = e.getX();
final int y = e.getX();
if (e.getClickCount() >= 2) {
    ...
} else {
    Timer timer = new Timer(waitTime, new ActionListener() {
        public void actionPerformed(ActionEvent e) {
            if (doubleClick) {
                /* we are the first click of a double click */
                doubleClick = false;
            } else {
                count++;
                randomBalls.add(new RandomBall(x, y, canvasWidth, canvasHeight));
                /* the second click never happened */
                System.out.println("single click");
            }
        }
    });
    timer.setRepeats(false);
    timer.start();
}
于 2013-09-23T02:46:59.063 に答える