回复人:bootcool(bootcool) (2001-3-23 14:28:00)  得10分 
As far as I know, all repainting is done by the AWT-Event-Queue.
However, you can't join to this thread as it will never finish.
Any updates you do to to GUI should be done in the event thread
by using SwingUtilities.invokeLater or
SwingUtilities.invokeAndWait.For example, in the thread that draws onto the panel:SwingUtilities.invokeLater( new Runnable() {
  public void run() {
    // do your drawing stuff here
  }
}); 

解决方案 »

  1.   

    这个问题好!!!
    首先 事件派发线程,它特只Swing(Awt)中专门用来派发事件的线程.
    Swing要求(也许说推荐比较合适)我们:不要在事件派发线程之外派发事件
    为了达到这个目的,在类SwingUtilities中有两个方法,就是上面两个方法.
    然后怎么说呢,也许只能意会,无法言传.以下是我翻译的一部分,看看先:class javax.swing.SystemEventQueueUtilities [package private]
    当SwingUtilities通过invokeLater()收到一个Runnable对象时,它立刻去调用类SystemEventQueueUtilities的postRunnable()方法.
    如果Runnable对象通过invokeAndWait()收到:
    首先,当前线程会检查自己不是事件派发线程(如果允许
    invokeAndWait()被事件派发线程自己调用,那将是致命的).如果是,会抛一个错误.否则,构造一个对象当作提供锁的临界对象.传递Runnable对象至SystemEventQueueUtilities类的postRunnable()方法,还有锁对象的引用.
    第二,调用线程在所对象上等待,直到锁对象通告”invoke and wait”;postRunnable()方法首先和私有的SystemEventQueue (SystemEventQueueUtilities的一个内部类)通讯,返回一个system event queue的引用.然后我们封装Runnable在一个RunnableEvent(另一个内部类)实例中.RunnableEvent构造器取得一个Runnable 和用来当锁的对象 (当 invokeLater()被调用时为null)作为参数.RunnableEvent类是AWTEvent的一个,且定义了自己的int型的EVENT_ID. (注意,无论何时当我们定义自己的事件时,我们最好用一个比AWTEvent.RESERVED_ID_MAX.大的event ID.) RunnableEvent的 EVENT_ID 是 AWTEvent.RESERVED_ID_MAX + 1000. RunnableEvent 还包含一个静态的RunnableTarget,实例,也是内部类. RunnableTarget 是一个Component的自类,它的唯一目的就是 扮演RunnableEvents的源和目标.RunnableTarget如何工作呢? 它的构造器使能了和RunnableEvent的 ID匹配的事件:     enableEvents(RunnableEvent.EVENT_ID);它还覆盖了Component的可见性为保护的processEvent()方法.在这个方法中,首先检查参数传进来的event是否为RunnableEvent的实例.如果是,就去执行SystemEventQueueUtilities的 processRunnableEvent()方法(这发生在RunnableEvent被从system event queue派发出来之后.)现在回到RunnableEvent. RunnableEvent 构造子调用父类AWTEvent的构造子,传递它的静态的RunnableTarget 实例作为事件源, EVENT_ID作为作为事件ID.它还把所给的Runnable和所对象的引用保存起来.