swing的渲染原理主要包括了Event,Painting,Rendering,Double Buffering,Threading,逐一介绍一下
Event:
事件在程序中可以有本地系统引发,或者java程序自己引发,或者应用程序自己构建,所有的事件都有事件队列EventQueue进行统一维护和分发,他是一个单线程的,叫做EDT,后面的Threading中将介绍。他是一个非常重要的机制,是保障高效、灵活的基础。
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:
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方法的值