有 Java 编程相关的问题?

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

java为什么JPanel从不调用reapint

嗨,我想写一个简单的神秘游戏,但出于某种原因,我的JPanel。永远不会调用repaint(),我的球也不会移动。因此,在我的主类中将JPanel扩展到JPanel中,我添加了一个监听器,当用户想要开始游戏时调用该监听器,因此会触发一个线程。该线程会更改球的位置,并且(理想情况下)应该在我的JPanel类上调用重新绘制。我检查了球的位置变化,但从未调用repait方法。有人能帮忙吗?提前感谢这是我的代码:

public class test extends JPanel{
int x=250;
int y=470;
int width=100;
int height=20;
Ball b=new Ball();
public static void main(String[] args){
    test t=new test();
    t.draw();
}
public void draw(){
    JFrame frame=new JFrame();
    frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
    frame.setSize(520, 520);
    frame.setResizable(false);
    this.setSize(500,500);
    frame.add(this);
    this.addMouseListener(new mouseL());
    frame.setVisible(true);
}
public void paintComponent(Graphics g){
    super.paintComponent(g);
    System.out.println("Yeah I am called");

    Graphics2D g2d=(Graphics2D) g;
    g2d.setColor(Color.blue);
    g2d.fillRect(x, y, width, height);
    g2d.setColor(b.getColor());
    g2d.fillOval(b.x1, b.y1, b.width1, b.height1);
}
class Ball{
    Random rand=new Random();
    int x1=300;
    int y1=450;
    int height1=20;
    int width1=20;
    Color c;
    public Color getColor(){
        return new Color(rand.nextInt(255), rand.nextInt(255), rand.nextInt(255));
    }
}
class mouseL implements MouseListener{
    Thread t=new Thread(new MyRun());

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


    }

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

    }

    @Override
    public void mouseReleased(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

    }

}
class MyRun implements Runnable{

    @Override
    public void run() {
        // TODO Auto-generated method stub
        try{
        while(true){
            //System.out.println("Yeah I work");
            test.this.b.x1=test.this.b.x1-1;
            test.this.b.y1=test.this.b.y1-1;
            System.out.println("the values are: "+test.this.b.x1+" and "+test.this.b.y1);
            Thread.sleep(2000);
            test.this.repaint();
        }
        }catch(Exception e){
            e.printStackTrace();
        }

    }

}

}


共 (1) 个答案

  1. # 1 楼答案

    t.run();调用(在您的情况下)Runnabe#run,这是从事件调度线程的上下文中执行的,从而永久冻结您的UI

    你应该用t.start()

    因为Swing是单线程的,所以在变量之间存在争用条件和脏读写的风险。一个更安全、更简单的解决方案是使用Swing Timer,请参见How to use Swing Timers,它在EDT中调度它的通知,从而确保从

    另外,看看How can I set in the midst?,了解为什么不应该使用JFrame#setSize,而是应该覆盖JPanelgetPreferredSize方法,并调用JFrame#pack