Warning: file_get_contents(/data/phpspider/zhask/data//catemap/6/multithreading/4.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
java线程&x2B;弹跳球_Java_Multithreading_Swing - Fatal编程技术网

java线程&x2B;弹跳球

java线程&x2B;弹跳球,java,multithreading,swing,Java,Multithreading,Swing,提前谢谢你的帮助 我创建了一个程序,当用户点击屏幕时,会产生多个弹跳球,一个新球会出现并在屏幕上移动。但是当我点击屏幕时,一个球出现了,并且根本没有移动。当再次单击时,先前创建的球立即跳到另一个位置 这是ball类:用于创建球 import java.awt.Color; import java.awt.Graphics2D; import java.awt.geom.Ellipse2D; import java.util.Random; import javax.swing.JComponen

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

这是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) {}
            }

        
    }
}
导入java.awt.Color;
导入java.awt.Graphics2D;
导入java.awt.geom.Ellipse2D;
导入java.util.Random;
导入javax.swing.JComponent;
公共类Ball扩展JComponent实现Runnable{
专用最终内径=25;
私人最终整数v1=5;
私有最终整数v2=-5;
私有最终随机rnd=新随机();
私有int-posX;
私家车;
私人色彩;
私人网络速度;
私人城市;
公共球(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;
}
公开作废动议(){
if(posX<15){
xVelocity=-xVelocity;
}否则如果(posX>475){
xVelocity=-xVelocity;
}
if(posY<0){
yVelocity=-yVelocity;
}否则如果(posY>475){
yVelocity=-yVelocity;
}
posX+=xVelocity;
posY+=yVelocity;
}
公共空白绘图(图形2D g2){
g2.设置颜色(颜色);
g2.填充(新椭圆2D.双(posX、posY、直径、直径));
}
私有静态颜色randomColor(){
int r=(int)(Math.random()*255);
int g=(int)(Math.random()*255);
intb=(int)(Math.random()*255);
颜色r颜色=新颜色(r、g、b);
返回颜色;
}
@凌驾
公开募捐{
而(!Thread.interrupted()){
move();
重新油漆();
试一试{
睡眠(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);
    }
}
导入java.awt.Color;
导入java.awt.Dimension;
导入java.awt.Graphics;
导入java.awt.Graphics2D;
导入java.awt.event.MouseAdapter;
导入java.awt.event.MouseEvent;
导入java.util.ArrayList;
导入javax.swing.JFrame;
导入javax.swing.JPanel;
公共类组件扩展了JPanel{
私人ArrayList bList;
公共组件(){
bList=newarraylist();
此.setPreferredSize(新尺寸(500500));
这个.背景(颜色.黑色);
这个.addMouseListener(新的ClickListener());
}
公共组件(图形g){
图形2d g2=(图形2d)g;
超级组件(g2);
对于(球a:bList){
a、 绘制(g2);
}
}
私有类ClickListener扩展了MouseApter{
公共无效mouseClicked(MouseEvent e){
球a=新球(e.getX(),e.getY());
b.添加(a);
重新油漆();
线程gameThread=新线程(a);
gamesthread.start();
}
}
公共静态void main(字符串[]args){
JFrame=新JFrame();
帧。设置标题(“弹跳球”);
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.add(新的BallComponent());
frame.pack();
frame.setVisible(true);
}
}

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

在主要方法的末尾

new Thread( ()->{
    while(true){
        frame.repaint();
        try{
            Thread.sleep(60);
        } catch(Exception e){
            break;
        }
    }
}).start();
通常你会用一个定时器任务来完成这项任务,但既然你说你不能用定时器,我就写了一个线程版本


我认为repaint()可以安全地从EDT的off调用,因为它只是计划重新绘制。paintComponent方法和click方法将仅在EDT上调用。所以你不应该得到CCME。多线程之间存在着一系列的竞争条件,但似乎唯一的问题是球被抽离了位置。

因为有很多线程在做随机的事情。您也可以自己进行JPanel更新

在主要方法的末尾

new Thread( ()->{
    while(true){
        frame.repaint();
        try{
            Thread.sleep(60);
        } catch(Exception e){
            break;
        }
    }
}).start();
通常你会用一个定时器任务来完成这项任务,但既然你说你不能用定时器,我就写了一个线程版本


我认为repaint()可以安全地从EDT的off调用,因为它只是计划重新绘制。paintComponent方法和click方法将仅在EDT上调用。所以你不应该得到CCME。多线程之间存在一系列竞争条件,但似乎唯一的问题是球被拉出了位置。

我最近多次看到同样的错误,您让图形类不必要地扩展GUI组件,这对您造成了伤害。答案是不要。不要这样做。Ball类绝对不应该扩展JComponent(也不应该实现Runnable)。它应该是一个逻辑类(非组件类),并且图形中应该只涉及一个GUI组件,可能是一个JPanel。另外,应该有一个游戏线程,而不是多个,最好用一个Swing定时器来实现。不要一直创建多个线程。相反,您的应用程序应该使用单个Swing计时器。当计时器启动时,您对BallComponent类调用move()和repaint(),列表中的所有球都应该被绘制。球不应该是实际的组件。相反,只需使用图形来绘制每个球。请参阅此方法的示例。Thx伙计们,但是创建多个线程&不使用计时器是我被要求做的,所以我别无选择……您正在调用“立即重新绘制”。这不需要在面板上用球重新喷漆。事实上,您的球是一个JComponent,这是完全没有使用过的。您需要调用BallComponent.repaint。当你有一个