Java多线程

时间:2013-09-20 13:58:19

标签: java multithreading swing

根据用户建议进行更改后,我通过引入单/双击识别,进一步采用了以下代码。为什么在左上角创建球而不是在鼠标点击的位置?

BouncingBalls.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;
    }
}

Container.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 个答案:

答案 0 :(得分:2)

使用此类更改Ball类中的移动方法(条件不正确):

public void move(Container container) {
        if (leftRight) {
            x += deltaX;
            if (x >= canvasWidth) {
                leftRight = false;
                updateDelta();
            }
        } else {
            x += -deltaX;
            if (x <= 0) {
                leftRight = true;
                updateDelta();
            }
        }

        if (upDown) {
            y += deltaY;

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

我运行它并且有效

答案 1 :(得分:2)

你的动作逻辑对于简单地移动球来说过于复杂,如果你想让它从墙上反弹,你应该考虑保留动量。

问题是

x >= (Ball.this.getWidth() - canvasWidth / 2)` and `y >= (Ball.this.getHeight() - canvasHeight / 2)

您正在使用第一个构造函数

创建球
balls.add(new Ball(x, y, canvasWidth, canvasHeight));

所以你只是检查是否x>=0 and y>=0,它会继续在+ - deltax / deltay位置反弹。

让它从墙上反弹的简单方法是

  public void move(Container container) {
      if(x>=canvasWidth || x<=0){
        deltaX = -1*deltaX;
      }
      if(y>=canvasHeight || y<=0){
        deltaY = -1*deltaY;
      }

      x+= deltaX;
      y+= deltaY;

}

答案 2 :(得分:2)

更改

public void move(Container container) {
    if (leftRight) {
        x += deltaX;
        if (x >= (Ball.this.getWidth() - canvasWidth / 2)) {
            leftRight = false;
            updateDelta();
        }
    } else {
        x += -deltaX;
        if (x <= 0) {
            leftRight = true;
            updateDelta();
        }
    }

    if (upDown) {
        y += deltaY;

        upDown = !(y >= (Ball.this.getHeight() - canvasHeight / 2));
        if (y >= (Ball.this.getHeight() - canvasHeight / 2)) {
            upDown = false;
            updateDelta();
        }
    } else {
        y += -deltaY;
        if (y <= 0) {
            upDown = true;
            updateDelta();
        }
    }
}

public void move(Container container) {
    if (leftRight) {
        x += deltaX;
        if (x >= getWidth()) {
            leftRight = false;
            updateDelta();
        }
    } else {
        x += -deltaX;
        if (x <= 0) {
            leftRight = true;
            updateDelta();
        }
    }

    if (upDown) {
        y += deltaY;

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

答案 3 :(得分:1)

这是因为您正在使用Ball.this.getWidth()getHeight() ...在构造函数中设置为画布高度。如果您使用radius代替它,它会起作用。例如:

if ( x >= ( canvasWidth - radius ) )
{
  leftRight = false;
  updateDelta();
}

if ( y >= ( canvasHeight - radius ) )
{
  upDown = false;
  updateDelta();
}