有 Java 编程相关的问题?

你可以在下面搜索框中键入要查询的问题!

多线程java线程+弹跳球

提前谢谢你的帮助 我创建了一个程序,当用户点击屏幕时,会产生多个弹跳球,一个新球会出现并在屏幕上移动。但当我点击屏幕时,一个球出现了,而且根本没有移动。当再次点击时,先前创建的球立即跳到另一个位置

这是ball类:用于创建球

import java.awt.Color;
import java.awt.Graphics2D;
import java.awt.geom.Ellipse2D;
import java.util.Random;
import javax.swing.JComponent;

public class Ball extends JComponent implements Runnable{
    private final int DIAMETER = 25;
    private final int v1 = 5;
    private final int v2 = -5;
    private final Random rnd = new Random();
    private int posX;
    private int posY;
    private Color color;
    private int xVelocity;
    private int yVelocity;
    
    public Ball(int posX, int posY) {
        this.posX = posX;
        this.posY = posY;
        this.color = randomColor(); 
        this.xVelocity = rnd.nextBoolean()?v1:v2;
        this.yVelocity = rnd.nextBoolean()?v1:v2;
    }
    
    public void move() {
        if (posX < 15) {
            xVelocity = -xVelocity;
        } else if(posX > 475) {
            xVelocity = -xVelocity;
        }
        
        if (posY < 0) {
            yVelocity = -yVelocity;
        } else if(posY > 475) {
            yVelocity = -yVelocity;
        }
        posX +=xVelocity;
        posY +=yVelocity;

    }
    
    public void draw(Graphics2D g2) {
        g2.setColor(color);
        g2.fill(new Ellipse2D.Double(posX,posY,DIAMETER,DIAMETER));
    }
    
    private static Color randomColor() {
        int r = (int)(Math.random()*255);
        int g = (int)(Math.random()*255);
        int b = (int)(Math.random()*255);
        Color rColor = new Color(r,g,b);
        return rColor;
    }

    @Override
    public void run() {
            while(!Thread.interrupted()) {
            move();
            repaint();
            try {
                Thread.sleep(60);
            } catch (InterruptedException ex) {}
            }

        
    }
}

这是ballcomponent类:用于创建面板&;展示球

import java.awt.Color;
import java.awt.Dimension;
import java.awt.Graphics;
import java.awt.Graphics2D;
import java.awt.event.MouseAdapter;
import java.awt.event.MouseEvent;
import java.util.ArrayList;

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

public class BallComponent extends JPanel{
    private ArrayList<Ball> bList;
    
    public BallComponent() {
        bList = new ArrayList<Ball>();
        this.setPreferredSize(new Dimension(500,500));
        this.setBackground(Color.BLACK);
        this.addMouseListener(new ClickListener());
    }
    
    public void paintComponent(Graphics g) {
        Graphics2D g2 = (Graphics2D)g;
        super.paintComponent(g2);
        for (Ball a : bList) {
            a.draw(g2);
        }
    }
    
    private class ClickListener extends MouseAdapter{
        public void mouseClicked(MouseEvent e) {
            Ball a = new Ball(e.getX(),e.getY());
            bList.add(a);
            repaint();
            Thread gameThread = new Thread(a);
            gameThread.start();
        }
    }
    
    public static void main(String[] args) {
        JFrame frame = new JFrame();
        frame.setTitle("Bouncing Balls");
        frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
        frame.add(new BallComponent());
        frame.pack();
        frame.setVisible(true);
    }
}

共 (1) 个答案

  1. # 1 楼答案

    因为你有一堆线程在做随机的事情。你也可以自己更新JPanel

    在你的主要方法的末尾

    new Thread( ()->{
        while(true){
            frame.repaint();
            try{
                Thread.sleep(60);
            } catch(Exception e){
                break;
            }
        }
    }).start();
    

    通常你会用一个定时器任务来完成这个任务,但既然你说你不能用定时器,我就写了一个线程版本

    我认为repaint()可以安全地从关闭EDT调用,因为它只是计划重新绘制。paintComponent方法和click方法将仅在EDT上调用。所以你不应该得到CCME。多线程有很多比赛条件,但唯一的问题似乎是球被拉离了位置