论文部分内容阅读
摘要:本文详细分析了Java中两大类型的组件的各自特性,以及由此特性引起的相关组件行为。同时分析了两大类型组件的视图绘制实现机制,对Java组件的绘制机制做了详细的描述,并阐述为什么需要这样实现。
关键词:Java;组件;视图绘制;重量组件;轻量组件
中图分类号:TP3 文献标识码:A 文章编号:1007-9599 (2011) 18-0000-02
View Rendering Mechanism of Java Components
Xu Wenping
(Wuxi Yozo Software Co.,Ltd.,Wuxi 214135,China)
Abstract:This paper analyzes two types of Java components in the respective characteristics,and the resulting properties caused by the behavior of related components.Also analyzed two types of components to achieve the view rendering mechanism,the mechanism of Java components draw a detailed description,and describes the need for such implementation.
Keywords:Java;Components;View drawing;Weight components;Lightweight components
Java开始于20世纪90年代初,伴随作Internet的迅速发展而逐渐成为当今最为流行的开发语言之一。其一开始就定位在一次编写程序,到处都可以运行的目标。然而由于当今的硬件環境,操作系统的多种多样,导致其实现的复杂性。而为了能减少这种差异带来的实现复杂,Java的组件实现采用了两种方式,一种是直接与平台有关的重量组件,一种是与平台无关的,而且可以轻易替换外观的轻量组件。下面就着重分析这两种组件的视图实现机制。
一、Java中的两种类型组件
(一)重量组件
该种类型的组件与程序运行时刻的具体平台有关,也就是说同一个程序中,如果某个组件使用的是重量组件,则该组件在Windows,Linux,OS/2,Solaris,Mac等各个平台上的视图外观表现是不一样的,在每个平台上,该组件的表现同该平台上的同样组件一样。
(二)轻量组件
该种类型的组件与重量组件的表现正好相反,其视图外观表现在程序运行时刻与具体的平台无关;也就是说同一个程序中,如果某个组件使用的是轻量组件,则该组件在Windows,Linux,OS/2,Solaris,Mac等各个平台上的视图外观表现是完全一致的;当然轻量组件也有可替换的皮肤,以根据需要进行替换,进而可以在某个平台上使用另外一种平台上到界面风格。
二、Java中两种类型组件的特点
(一)重量组件的特点
在Java中所有的AWT的组件都是重量组件。
对于重量组件,所有的重量组件都有本地同位体(对等体),该同位体即是与各种运行平台相关的,正是由于该本地同位体的存在,导致前面提到的,所有重量组件的视图外观表现随运行平台的变化而变化,而不是一个固定的表现。基于同位体这点,导致重量组件有后续一系列的特点。
所有的重量组件都是不透明的组件,其组件的颜色不能设置为透明或半透明的效果,由于该原因所以重量组件间一旦有重叠,则在上方的组件势必盖住下方的组件。
所有的重量组件其形态外观都是规则的矩形形状,不存在圆形,倒角矩形等形状的重量组件,当然一旦后续的平台支持这种非矩形的组件,则重量组件的外观形状中也会有这种非矩形的了。
在Java中所有的重量组件本身(除几个容器组件外)都不能作为其他组件的容器使用,这里的其他组件包括重量组件和轻量组件。重量组件中可作为容器的组件有Panel,Applet,ScrollPane,Window,及从Window派生的Fram,Dialog。
(二)轻量组件的特点
在Java中,Swing体系下的组件除了几个组件是重量组件以外,其他都是轻量组件。这几个组件都是Swing组件的底层容器组件,其包括:继承AWT的Window组件的JWindow组件,继承于AWT的Frame组件的JFrame组件,继承于AWT的Applet组件的Japplet,继承于AWT的Dialog组件的JDialog。
对于轻量组件,不存在本地同位体,但是为了同整个Java的组件体系相容,每一个轻量组件在具体实例化的时候,会统一赋予一个LightweightPeer类型的NullComponentPeer虚拟的同位体。
由于轻量组件的体系结构采用的是Swing体系结构,该结构体系是独立于重量组件的体系结构,所以轻量组件的一系列特性是不受具体的运行平台限制的,其具有一系列重量组件无法完成的特性。
所有的轻量组件的背景可以在透明和不透明之间任意调整其透明度,如果一个轻量组件是透明的,则其在位置上虽然覆盖了另外的组件的位置,但此时另外被覆盖的组件仍然可见,当然其可见程度就视覆盖它的轻量组件的透明程度而定了。
基于轻量组件的背景可以透明,所以该类型组件的外观形状就可以是任何形状的外观,圆形,椭圆形,曲线行等等任何用户需求的外观形状。既然外观形状可以是任意的,所以其响应鼠标事件的区域也可以是任意的。当然实际上响应鼠标事件的任意定制并不是由于组件的背景可以是透明的原因,是由于其事件的处理机制是独立的Swing体系结构的一部分。
万事万物不可能凭空而存在,轻量组件也不例外。对于所有的轻量组件其最终容器必须是某个重量组件性质的容器,这里指的最终容器是指在运行时刻,所有组件集合中的根容器。任何一个轻量组件都可以作为其他轻量组件的父容器,包括同类型的轻量组件,一个组件实例也可以作为另一个组件实例的父容器,所以在任何时刻一个轻量组件可以是另外一个组件中的子组件,而与此同时其又可能是另一些轻量组件的容器。
三、Java组件的视图绘制机制
(一)重量组件的视图绘制机制
前面重量组件的特点中提到,所有重量组件都有相对应的本地同位体存在,正是基于这点一般重量组件的视图绘制完全是由其同位体来负则在其本地窗体中绘制。一个重量组件,其平台中同样的组件表现的是什么外观,则其就表现的是什么外观,即使在定制重量组件的时候,重载其原有的方法paint(Graphics g)方法,在该方法中,增加一些定制的外观,仍然逃不掉其本地同位体的影响。如定制java.awt.Button组件,虽然在其paint(Graphics g)中,重新对组件的视图外观进行了新的绘制处理,但是如果你遗漏了在一开始就使用某种背景把原本地同位体产生的视图效果擦出,则产生的视图绘制效果并不是你所想要的。
在定制重量组件的绘制时,一般只需要重载其顶层父类java.awt.Component的paint(Graphics g)方法即可,同时为了消除频繁绘制造成的闪烁,要重载其update()方法,自己定制缓存来消除闪烁。如果需要重载重量容器的paint()方法,一般必须在一定位置调用其父类的paint()方法,以保证能够在重绘时,该容器上的所有子组件能够得到重新绘制,如果不这样处理则该容器上的子组件则不能正确显示。
由于重量组件的本地同位体的特性,导致当某个重量组件同其他轻量组件在同一个容器中的时候,此时无论重量组件是先于轻量组件加入容器还是后加入容器的,重量组件总是在轻量组件的上方,并且遮盖住同一位置处的所有轻量组件。
(二)轻量组件的视图绘制机制
轻量组件采用的是轻量级的Swing体系,每个轻量组件一般都有一个UI代表来负责具体的组件外观的视图绘制显示,而且该UI代表是可以随时动态替换的,正是由于该UI代表的可替换特性,所以采用轻量组件来实现的程序界面,可以实现目前可视程序中流行的换肤效果。
轻量组件绘制总的特点是,用其容器传递的Graphics,在容器中绘制。利用该特性就可以使得轻量组件可以在任何给定的Grpahics中进行具体外观效果的绘制。如在BufferImange里绘制,这样就可以把该组件在某一时刻的某次视图效果制作为一个相应的图片,再存储该图片为各种格式的图片文件。如此制作该组件在多个时间段的不同图片,再由这些图片制作为动画的各种效果,这样就可以随时跟踪组件的外观形状变化,并回放。
由于轻量组件的绘制只依赖于给定的Graphics,所以轻量组件之间的绘制关系可以做所需用的调整。对于Java默认的实现,在同一个容器中的所有轻量组件,其绘制的先后顺序,以及组件间的重叠关系,是由在该轻量组件加入该容器时候的先后顺序和给定的层次决定的,也就是说该顺序是可以自己控制的。在默认不给层次关系的时候,如果两个轻量组件在容器中的位置有交叉,则一般是后加入的轻量组件被先加入的轻量组件覆蓋。当然如果程序员自己重载容器的相应方法,也可以改变Java的默认实现效果。
在Java中轻量组件视图外观绘制的几个主要方法是:paintBuffer()方法,该方法负责绘制该组件的缓存;paintComponent()方法,该方法负责绘制轻量组件本身的视图外观;paintBorder()方法,该方法负责绘制组件的边框;paintChildren()方法,该方法负责绘制组件作为容器时候,在该组件中的所有子组件。
对于轻量组件的视图绘制定制,一般可以仅仅重载组件的paintComponent()方法或由其UI的paint()方法就可以实现了。轻量组件的paintComponent()方法缺省会调用其UI的update()方法,然后由update()方法调用paint()方法。所有的轻量组件一般有UI代表,而轻量组件的具体绘制就由其UI代表来负责完成,对于组件的换肤,通常就是替换该UI代表即可。
一般轻量组件的定制绘制就是在UI的paint(Graphics g)方法中进行,UI的update()方法在没有特殊需求一般不需要重写;如果需要自己清出组件的背景或定制组件的背景,可以通过改写该update()方法来实现;paintBorder()方法是负责绘制组件的边框,组件的边框可以通过设置不同的边框类来实现不同的效果,这样在通常情况下就不需要重载该方法来实现特殊的边框效果;当然如果要固定一种特殊的边框效果也可以重载该方法来实现自己的特殊边框要求;paitChildren()方法是负责绘制该组件作为容器的时候,其包括的所有子组件,每个子组件的具体绘制又同前面所述的视图绘制机制一样。
四、Java组件的视图重绘制机制
在一般的Java组件应用中,如果没有特别的需要,组件的repaint()方法不用去重载。如果需要重载该方法,最好是在一定时候要调用super的repaint()方法。对repaint()的其他几个带参数的方法同样在没有特别的需求的时候也最好是不要去重载。对于开发者,在有时候为了调试绘制的情况,往往可以通过重载repaint(long t,int x,int y,int w,int h)方法来跟踪组件的具体重绘情况,当然该代码应该在最终发布的版本中去掉。
(一)重量组件的视图重绘制机制
对于重量组件的repaint()方法,该方法基本上是立即通过事件队列调用其同位体来立即进行该组件的重新绘制。重量组件的repaint()方法只影响其组件本身,只有该组件本身才进行重新绘制,其他相临的兄弟组件不会重新绘制,而不管该相临的兄弟组件组件是重量组件还是轻量组件;如果该重量组件是容器,当然会影响其内的子组件。
(二)轻量组件的视图重绘制机制
对于轻量组件的repaint()方法则有很大的不同,在组件的repaint()方法里最终会把所需要绘制的范围计算出来,然后把该组件和该区域记入RepaintManager类里,在RepaintManager类里,会处理所记录的需要绘制的组件,如果在一定的时间内重复的调用同一组件的多次repaint()方法,则通过RepaintManager类的处理,会把多次的调用合并为一次有效的重新绘制事件,在该次事件中,其绘制范围会合并多次调用时候的绘制区域,多所有的区域采取取并集的方式,在RepaintManager类里处理完成后会以一个绘制事件让组件绘制所需要绘制的区域,该绘制事件是由另外的绘制线程控制的,在该绘制线程里会调用组件的paintImmediately()方法,组件的paintImmediately()方法会使该次绘制从该组件的最终容器开始绘制。
由于组件的重新绘制往往是从该组件的最终容器开始绘制,所以某个组件的repaint()方法导致的组件重新绘制,可能会导致其容器绘制,进而导致容器中的其他组件绘制((如果在repaint的范围内);也就是说,轻量组件的重新绘制可能导致其兄弟组件(轻量的组件,重量的不会)的重新绘制。
参考文献:
[1]朱志,王怀,赵伟等.Java2核心技术(卷I:基础知识)[M].北京:机械工业出版社,2000
[2]朱志,王怀,赵伟等.Java2核心技术(卷II:高级特性)[M].北京:机械工业出版社,2000
[作者简介]徐文平,系统分析师,主研领域:Java桌面应用,Java网络应用,分布式系统。
关键词:Java;组件;视图绘制;重量组件;轻量组件
中图分类号:TP3 文献标识码:A 文章编号:1007-9599 (2011) 18-0000-02
View Rendering Mechanism of Java Components
Xu Wenping
(Wuxi Yozo Software Co.,Ltd.,Wuxi 214135,China)
Abstract:This paper analyzes two types of Java components in the respective characteristics,and the resulting properties caused by the behavior of related components.Also analyzed two types of components to achieve the view rendering mechanism,the mechanism of Java components draw a detailed description,and describes the need for such implementation.
Keywords:Java;Components;View drawing;Weight components;Lightweight components
Java开始于20世纪90年代初,伴随作Internet的迅速发展而逐渐成为当今最为流行的开发语言之一。其一开始就定位在一次编写程序,到处都可以运行的目标。然而由于当今的硬件環境,操作系统的多种多样,导致其实现的复杂性。而为了能减少这种差异带来的实现复杂,Java的组件实现采用了两种方式,一种是直接与平台有关的重量组件,一种是与平台无关的,而且可以轻易替换外观的轻量组件。下面就着重分析这两种组件的视图实现机制。
一、Java中的两种类型组件
(一)重量组件
该种类型的组件与程序运行时刻的具体平台有关,也就是说同一个程序中,如果某个组件使用的是重量组件,则该组件在Windows,Linux,OS/2,Solaris,Mac等各个平台上的视图外观表现是不一样的,在每个平台上,该组件的表现同该平台上的同样组件一样。
(二)轻量组件
该种类型的组件与重量组件的表现正好相反,其视图外观表现在程序运行时刻与具体的平台无关;也就是说同一个程序中,如果某个组件使用的是轻量组件,则该组件在Windows,Linux,OS/2,Solaris,Mac等各个平台上的视图外观表现是完全一致的;当然轻量组件也有可替换的皮肤,以根据需要进行替换,进而可以在某个平台上使用另外一种平台上到界面风格。
二、Java中两种类型组件的特点
(一)重量组件的特点
在Java中所有的AWT的组件都是重量组件。
对于重量组件,所有的重量组件都有本地同位体(对等体),该同位体即是与各种运行平台相关的,正是由于该本地同位体的存在,导致前面提到的,所有重量组件的视图外观表现随运行平台的变化而变化,而不是一个固定的表现。基于同位体这点,导致重量组件有后续一系列的特点。
所有的重量组件都是不透明的组件,其组件的颜色不能设置为透明或半透明的效果,由于该原因所以重量组件间一旦有重叠,则在上方的组件势必盖住下方的组件。
所有的重量组件其形态外观都是规则的矩形形状,不存在圆形,倒角矩形等形状的重量组件,当然一旦后续的平台支持这种非矩形的组件,则重量组件的外观形状中也会有这种非矩形的了。
在Java中所有的重量组件本身(除几个容器组件外)都不能作为其他组件的容器使用,这里的其他组件包括重量组件和轻量组件。重量组件中可作为容器的组件有Panel,Applet,ScrollPane,Window,及从Window派生的Fram,Dialog。
(二)轻量组件的特点
在Java中,Swing体系下的组件除了几个组件是重量组件以外,其他都是轻量组件。这几个组件都是Swing组件的底层容器组件,其包括:继承AWT的Window组件的JWindow组件,继承于AWT的Frame组件的JFrame组件,继承于AWT的Applet组件的Japplet,继承于AWT的Dialog组件的JDialog。
对于轻量组件,不存在本地同位体,但是为了同整个Java的组件体系相容,每一个轻量组件在具体实例化的时候,会统一赋予一个LightweightPeer类型的NullComponentPeer虚拟的同位体。
由于轻量组件的体系结构采用的是Swing体系结构,该结构体系是独立于重量组件的体系结构,所以轻量组件的一系列特性是不受具体的运行平台限制的,其具有一系列重量组件无法完成的特性。
所有的轻量组件的背景可以在透明和不透明之间任意调整其透明度,如果一个轻量组件是透明的,则其在位置上虽然覆盖了另外的组件的位置,但此时另外被覆盖的组件仍然可见,当然其可见程度就视覆盖它的轻量组件的透明程度而定了。
基于轻量组件的背景可以透明,所以该类型组件的外观形状就可以是任何形状的外观,圆形,椭圆形,曲线行等等任何用户需求的外观形状。既然外观形状可以是任意的,所以其响应鼠标事件的区域也可以是任意的。当然实际上响应鼠标事件的任意定制并不是由于组件的背景可以是透明的原因,是由于其事件的处理机制是独立的Swing体系结构的一部分。
万事万物不可能凭空而存在,轻量组件也不例外。对于所有的轻量组件其最终容器必须是某个重量组件性质的容器,这里指的最终容器是指在运行时刻,所有组件集合中的根容器。任何一个轻量组件都可以作为其他轻量组件的父容器,包括同类型的轻量组件,一个组件实例也可以作为另一个组件实例的父容器,所以在任何时刻一个轻量组件可以是另外一个组件中的子组件,而与此同时其又可能是另一些轻量组件的容器。
三、Java组件的视图绘制机制
(一)重量组件的视图绘制机制
前面重量组件的特点中提到,所有重量组件都有相对应的本地同位体存在,正是基于这点一般重量组件的视图绘制完全是由其同位体来负则在其本地窗体中绘制。一个重量组件,其平台中同样的组件表现的是什么外观,则其就表现的是什么外观,即使在定制重量组件的时候,重载其原有的方法paint(Graphics g)方法,在该方法中,增加一些定制的外观,仍然逃不掉其本地同位体的影响。如定制java.awt.Button组件,虽然在其paint(Graphics g)中,重新对组件的视图外观进行了新的绘制处理,但是如果你遗漏了在一开始就使用某种背景把原本地同位体产生的视图效果擦出,则产生的视图绘制效果并不是你所想要的。
在定制重量组件的绘制时,一般只需要重载其顶层父类java.awt.Component的paint(Graphics g)方法即可,同时为了消除频繁绘制造成的闪烁,要重载其update()方法,自己定制缓存来消除闪烁。如果需要重载重量容器的paint()方法,一般必须在一定位置调用其父类的paint()方法,以保证能够在重绘时,该容器上的所有子组件能够得到重新绘制,如果不这样处理则该容器上的子组件则不能正确显示。
由于重量组件的本地同位体的特性,导致当某个重量组件同其他轻量组件在同一个容器中的时候,此时无论重量组件是先于轻量组件加入容器还是后加入容器的,重量组件总是在轻量组件的上方,并且遮盖住同一位置处的所有轻量组件。
(二)轻量组件的视图绘制机制
轻量组件采用的是轻量级的Swing体系,每个轻量组件一般都有一个UI代表来负责具体的组件外观的视图绘制显示,而且该UI代表是可以随时动态替换的,正是由于该UI代表的可替换特性,所以采用轻量组件来实现的程序界面,可以实现目前可视程序中流行的换肤效果。
轻量组件绘制总的特点是,用其容器传递的Graphics,在容器中绘制。利用该特性就可以使得轻量组件可以在任何给定的Grpahics中进行具体外观效果的绘制。如在BufferImange里绘制,这样就可以把该组件在某一时刻的某次视图效果制作为一个相应的图片,再存储该图片为各种格式的图片文件。如此制作该组件在多个时间段的不同图片,再由这些图片制作为动画的各种效果,这样就可以随时跟踪组件的外观形状变化,并回放。
由于轻量组件的绘制只依赖于给定的Graphics,所以轻量组件之间的绘制关系可以做所需用的调整。对于Java默认的实现,在同一个容器中的所有轻量组件,其绘制的先后顺序,以及组件间的重叠关系,是由在该轻量组件加入该容器时候的先后顺序和给定的层次决定的,也就是说该顺序是可以自己控制的。在默认不给层次关系的时候,如果两个轻量组件在容器中的位置有交叉,则一般是后加入的轻量组件被先加入的轻量组件覆蓋。当然如果程序员自己重载容器的相应方法,也可以改变Java的默认实现效果。
在Java中轻量组件视图外观绘制的几个主要方法是:paintBuffer()方法,该方法负责绘制该组件的缓存;paintComponent()方法,该方法负责绘制轻量组件本身的视图外观;paintBorder()方法,该方法负责绘制组件的边框;paintChildren()方法,该方法负责绘制组件作为容器时候,在该组件中的所有子组件。
对于轻量组件的视图绘制定制,一般可以仅仅重载组件的paintComponent()方法或由其UI的paint()方法就可以实现了。轻量组件的paintComponent()方法缺省会调用其UI的update()方法,然后由update()方法调用paint()方法。所有的轻量组件一般有UI代表,而轻量组件的具体绘制就由其UI代表来负责完成,对于组件的换肤,通常就是替换该UI代表即可。
一般轻量组件的定制绘制就是在UI的paint(Graphics g)方法中进行,UI的update()方法在没有特殊需求一般不需要重写;如果需要自己清出组件的背景或定制组件的背景,可以通过改写该update()方法来实现;paintBorder()方法是负责绘制组件的边框,组件的边框可以通过设置不同的边框类来实现不同的效果,这样在通常情况下就不需要重载该方法来实现特殊的边框效果;当然如果要固定一种特殊的边框效果也可以重载该方法来实现自己的特殊边框要求;paitChildren()方法是负责绘制该组件作为容器的时候,其包括的所有子组件,每个子组件的具体绘制又同前面所述的视图绘制机制一样。
四、Java组件的视图重绘制机制
在一般的Java组件应用中,如果没有特别的需要,组件的repaint()方法不用去重载。如果需要重载该方法,最好是在一定时候要调用super的repaint()方法。对repaint()的其他几个带参数的方法同样在没有特别的需求的时候也最好是不要去重载。对于开发者,在有时候为了调试绘制的情况,往往可以通过重载repaint(long t,int x,int y,int w,int h)方法来跟踪组件的具体重绘情况,当然该代码应该在最终发布的版本中去掉。
(一)重量组件的视图重绘制机制
对于重量组件的repaint()方法,该方法基本上是立即通过事件队列调用其同位体来立即进行该组件的重新绘制。重量组件的repaint()方法只影响其组件本身,只有该组件本身才进行重新绘制,其他相临的兄弟组件不会重新绘制,而不管该相临的兄弟组件组件是重量组件还是轻量组件;如果该重量组件是容器,当然会影响其内的子组件。
(二)轻量组件的视图重绘制机制
对于轻量组件的repaint()方法则有很大的不同,在组件的repaint()方法里最终会把所需要绘制的范围计算出来,然后把该组件和该区域记入RepaintManager类里,在RepaintManager类里,会处理所记录的需要绘制的组件,如果在一定的时间内重复的调用同一组件的多次repaint()方法,则通过RepaintManager类的处理,会把多次的调用合并为一次有效的重新绘制事件,在该次事件中,其绘制范围会合并多次调用时候的绘制区域,多所有的区域采取取并集的方式,在RepaintManager类里处理完成后会以一个绘制事件让组件绘制所需要绘制的区域,该绘制事件是由另外的绘制线程控制的,在该绘制线程里会调用组件的paintImmediately()方法,组件的paintImmediately()方法会使该次绘制从该组件的最终容器开始绘制。
由于组件的重新绘制往往是从该组件的最终容器开始绘制,所以某个组件的repaint()方法导致的组件重新绘制,可能会导致其容器绘制,进而导致容器中的其他组件绘制((如果在repaint的范围内);也就是说,轻量组件的重新绘制可能导致其兄弟组件(轻量的组件,重量的不会)的重新绘制。
参考文献:
[1]朱志,王怀,赵伟等.Java2核心技术(卷I:基础知识)[M].北京:机械工业出版社,2000
[2]朱志,王怀,赵伟等.Java2核心技术(卷II:高级特性)[M].北京:机械工业出版社,2000
[作者简介]徐文平,系统分析师,主研领域:Java桌面应用,Java网络应用,分布式系统。