Java 2D Game: repaint(); makes window grey

时间秒杀一切 提交于 2019-11-28 13:13:55
Sage

What is EDT ?

Swing event handling code runs on a special thread known as the event dispatch thread. Most code that invokes Swing methods also runs on this thread. This is necessary because most Swing object methods are not "thread safe". All GUI related task, any update should be made to GUI while painting process must happen on the EDT, which involves wrapping the request in an event and processing it onto the EventQueue. Then the event are dispatched from the same queue in the one by one in order they en-queued, FIRST IN FIRST OUT. That is, if That is, if Event A is enqueued to the EventQueue before Event B then event B will not be dispatched before event A.

Any task you perform which may take a while, likely to block the EDT, no dispatching will happen, no update will be made and hence your application FREEZES. You will have to kill it to get rid of this freezing state.

In your program, aside from creating your JFrame and making it to visible from the main thread (which we also should not do):

    while(true) {
        if (up) {
            player.moveUp();
        } else if (down) {
            player.moveDown();
        }
        repaint();
    try {
        Thread.sleep(20);
    } catch (InterruptedException ex) {
        Logger.getLogger(Spaceshooter.class.getName()).log(Level.SEVERE, null, ex);
    }
    }

you are posting repaint() request from the thread which you sent to sleep right immediately after that.

SwingUtilities.invokeLater():

Swing provides a nice function SwingUtilities.invokeLater(new Runnable(){}) for posting repaint request to the EDT. All you have to do is to write:

    SwingUtilities.invokeLater(new Runnable()
       {
         public void run()
         {
               repaint();
         }
   });

Now some more thing to mention:

  1. We should not implements a GUI component with Runnable. Make another class implementing Runnable, make your computation inside that then use SwingUtilities to post the component update request.
  2. we should not made custom painting on JFrame directly. JFrame is a top level component. It is more like a container which contains your whole app. If you want custom painting use a custom component MyCanvas extends JComponent.
  3. we should not override paint() function. Instead paintComponent(g) will serve our custom painting purposes nicely.
  4. Learn to use Swing Timer class for timely repeated GUI rendering task.

Tutorial Resource and References:

  1. The Event Dispatch Thread
  2. EventQueue
  3. How to Use Swing Timers
  4. Lesson: Performing Custom Painting
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!