其实java里设置属性后会导致重绘的,只不过由于这个重绘事件也被放在事件派发线程里的,因此就导致了事件派发线程被Idle了,要避免这种情况,将这个堵塞动作放到另外的线程里面完成。
    repaint是出发重绘动作,当调用repaint后,会通知repaintManager增加一个重绘区域,repaintManager在一定条件下会合并一些重绘区域,然后派发一个绘制动作到事件派发线程(EventQueue)。
    事件派发线程执行到这个绘制事件时,就会调用组件的paint,在paint方法里会先调用update来将重绘区域清空(默认情况下是填充白色),然后再调用paintComponent来绘制自身,最后调用paintChildren来绘制所有的子。具体流程可以参考JComponent里的paint方法。

解决方案 »

  1.   

    谢谢楼上的回答,不过还是有点不明白
       1  既然设置属性之后重绘事件是被放在派发线程里,那么应该说本线程的阻塞并不会造成派发线程
    的阻塞呀,那为什么会设置的视觉结果要等到方法返回时再改变呢?关键是我用paintComponent(getGraphics())就能够立刻得到结果,如果是派发线程重绘事件的问题,那这时能成功又是什么原因呢
       2  至于repaint不行而paintComponent就行的问题,照楼上的回答的思路,小弟想是否是因为
    repaint时派发线程还没有执行到这个事件,因而不能立刻绘出结果?但如果是这样,因该在等待一会之后就能够有结果呀,但事实为什么不是呢?
       3  如果repaint不能立刻得到所想的结果,为什么文档中推荐用户调用的是它而不是直接使用其他
    几个方法呢,还是我在使用时存在误区?
       还望赐教!!!
      

  2.   

    1、难道你的阻塞不是由Button触发的吗?Button按下的动作就是在事件派发线程里的。
    2、paintComponent时是直接绘制,是在Socket触发IDle之前,只要这个方法能被执行到,那么就能重新绘制Button
    3、repaint是产生一个重绘事件到事件派发线程里去了,所以才不行,paintComponent没有产生事件而是直接绘制。记住绘制和触发重绘是两个过程。
    4、是你使用时的错误,不应该在button的Action事件中处理会导致线程阻塞的动作。之所以推荐repaint,是因为系统会合并绘制,同时repaint还能避免组件相互覆盖时的绘制错误。
      

  3.   

    哦,我好象有点明白了,是不是重绘操作和Button按下的操作先后都排在了事件派发线程中,Button
    的阻塞导致了重绘操作的不能执行?
      

  4.   

    是的,就是这个道理,所以需要把Socket的操作放到独立线程里去。
      

  5.   

    哦,谢谢啦
        也就是说事件的处理应尽量能立刻返回,耗时和会引起阻塞的过程都应放到后台线程中去对吧?
        最后还有个相关的问题,为什么现在推荐覆盖paintComponent而不推荐覆盖paint呢?
      

  6.   

    因为你要为其他绘制操作保留调用过程,如果覆盖paint,那么就完全由你来完成paint了,update和paintChildren就无法进行。