swing学习笔记 - Swing Rendering Fundamentals

时间:2024-04-08 11:22:49

swing的渲染原理主要包括了Event,Painting,Rendering,Double Buffering,Threading,逐一介绍一下

Event:

     事件在程序中可以有本地系统引发,或者java程序自己引发,或者应用程序自己构建,所有的事件都有事件队列EventQueue进行统一维护和分发,他是一个单线程的,叫做EDT,后面的Threading中将介绍。他是一个非常重要的机制,是保障高效、灵活的基础。

swing学习笔记 - Swing Rendering Fundamentals

Painting

    在swing更新应用程序的界面时候执行代码,可以执行标准的组件代码,也可执行自定义代码。

     painting进程主要包含了发送EDT的paint请求数据和EDt执行paint和paintComponent的执行结果。

    二种数据来源:

    1)swing或者awt发送的repaint请求

    2)应用程序发送的请求

    例如:窗口大小变化,awt会接受本地的请求,进行repaint自己。在swing中一个按钮鼠标移动到上面,状态发生变化,repaint自己,也可以在执行代码中去执行repaint,执行控件的绘制。

  一般来说repaint是自动的,swing在发现了状态变化以后会自动执行repaint。

   repaint主要包含二种类型

    1)asyschronous:告诉swing需要更新,具体计划有swing自己安排,他分为按照控件重绘和按照区域重绘二种,这样可以提高效率。

    2)syschronous:马上绘制,需要注意保证在正确的线程中,比较容易引起死锁,尽量少用。调用方法paintImmediately

Rendering:

swing学习笔记 - Swing Rendering Fundamentals

    paint在jdk中比较重要的方法介绍

    paintComponent:如果定义的组件需要自定义render,覆盖此方法,进行组件的绘制

    paint:绘制,他其中调用了paintComponent,paintBorder等方法,如果覆盖了需要保证他们的执行。不建议覆盖此方法,但是对于如果需要绘制半透明的组件,其中的边框也是半透明的,可以覆盖此方法进行处理。一般情况下AWT组件是覆盖paint方法,swing的组件,覆盖paintComponent方法。

    setOpague:设置是否透明

Threading:

    应用程序启动以后需要启动三个进程,一个主进程,一个是tookit进程,一个是EDT。

    一个给textarea输入一个字符的事件需要进行如下处理:

    按下键盘,eDT接受到事件,然后转给组件进行处理,因为组件已经注册了事件监听,然后监听在转给EDT,EDT接收到事件后分发给compoent进行repaint。

   需要特别注意,EDT是单进程的,如果在进程中进行长时间的线程阻塞,会造成程序的假死,是一种非常不好的感知,这种方式有以下几种解决办法:(注意并不是只有swing是单线程的,其中的swt,qt,.net winForm都是单线程的)

   1)采用编写新的线程.

       new Thread(){

       }.run()

       这种方式可以将长时间的启动新的线程进行处理,不阻塞EDT,这样可以满足处理,但是啊违背了EDT的单线程原则,在长时间的处理完成以后,需要更新空间的属性,有一个新的线程去更新,可能会造成不法判断的问题。这个时候很有可能就会出现个人测试怎么都不会有问题,到客户哪里就经常出现问题的局面。

   2)采用SwingUtilities的三个方法进行处理

      A)invokeLater:这个方法是在处理的过程中给EDT发送新的处理,然后让EDt进行安排方法体内部的处理。

           这个正好可以上面的1中的更新空间内容部分的问题,可以如下编码

           new Thread(){

               public void run(){

                     StringUtilities.invokeLater(new Runable(){

                             //run

                       });

               }

           }.run()

 

       B)isEventDispatchThread:判断是否是EDT线程,

     public void setLable(){

        Runable test= new Runable(){

               //处理函数

               public void run(){}

        }

        if(SwingUtilities.isEventDispatchThread()){

            test.run();

        }else{

             SwingUtilities.invokeLater(test);

         }

}

     c)invokeWait:执行等待,知道EDT返回值

    jdk中二个Timer的区别:

     java.util.Timer:不能执行EDt线程,只能通过SwingUtilities的invokeLater执行EDt

     javax.swing.Timer,可以执行EDt线程

   SwingWorker:SwingUtilities的功能非常强大,但是使用它以后会出现大量的内部类,在jdk6中添加了一个javax.swing.SwingWorker他可以满足这个功能,不用出现大量的匿名类

    编写一个子类,继承自swingWorker,然后覆盖其中的doinBackground方法,

    doinBackground:是执行的方法,返回t

    在中间如果需要向EDT发送消息,可以采用pushlish(V)

    结束以后可以调用done方法,在方法中可以用get方法取出doInBackground方法的值

 swing学习笔记 - Swing Rendering Fundamentals