只有在调整窗口大小后才能更新JFrame

问题描述:

我正在尝试为学习目的制作自己的Snake版本。一切似乎工作正常,但如果我想要我的框架重新粉刷,我必须手动调整我的窗口。这里是我的代码:只有在调整窗口大小后才能更新JFrame

package snake; 

import java.awt.*; 
import javax.swing.JFrame; 
import javax.swing.JPanel; 

public class PlayGame extends JPanel implements Runnable{ 

    public boolean animate = false;   
    public final int FRAME_DELAY = 750; 

    PickupBall b = new PickupBall(); 
    Snake bob = new Snake(); 


    public synchronized void start() { 
     animate = true; 
    } 

    public synchronized void stop() { 
     animate = false; 
    } 
    private synchronized boolean animationEnabled() { 
     return animate; 
    } 

    @Override 
    public void run(){    
     while(true){  
      if (animationEnabled()){      
       repaint();      
      } 
      try { 
       Thread.sleep(FRAME_DELAY); 
      } 
      catch (InterruptedException e) { 
       throw new RuntimeException(e); 
      } 
     } 
    }   

    @Override 
    public void paintComponent(Graphics g){    
     super.paintComponent(g); 

     b.draw(g); 
     bob.draw(g);    
    }   

    public static void main(String[] args) {  
     JFrame jfr = new JFrame("Snake"); 
     jfr.setSize(640,640); 
     jfr.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);    
     jfr.setResizable(true); 

     PlayGame p = new PlayGame(); 

     jfr.setContentPane(p); 

     p.setBackground(Color.WHITE);    

     p.start();    

     new Thread(p).start();    
     jfr.setVisible(true);  

    } 


} 

为什么不重绘()触发没有改变帧的大小?我得到了相关性,但是它对于为什么当它处于while(true)循环时需要这样的触发器是没有意义的。

我在这里错过了什么?

编辑1: 删除线程对象 替换t.start()与p.start()

编辑2: 新增new Thread(p).start();和现在的作品!谢谢。

编辑3: 删除revalidate();

+0

PlayGame p = new PlayGame(); 线程t =新线程(p); t.start(); –

+1

't.start()',但从来没有'p.start()',所以'animate'总是'false'。 – kiheru

+0

好吧,这是否意味着线程对象是毫无意义的? –

新增new Thread(p).start();

仍然不知道如何或为何这是不同的,以 Thread t = new Thread(p); t.start();

但它的工作。

+0

它们没有区别,问题不在那里。问题是你从'Thread'类中调用'start',而不是'PlayGame'类中的'start'。他们都是完全不同的方法,你需要调用两者。 “Playgame”中的“开始”可以具有任何你想要的名称,误导它与“线程”中的方法具有相同的名称。 – Berger

您在工作线程执行repaint(),而不是在事件分派胎面(EDT)这实际上是绘制到屏幕上的唯一的一个。

您必须使用SwingUtilities静态方法invokeLater()invokeAndWait()在EDT中将呼叫排队到repaint()

+0

您能告诉我吗?我不知道在哪里放,谷歌没有帮助。 –

+0

'repaint'是线程安全的,因为它将实际的绘画事件发布到要处理的EDT上 – MadProgrammer