原文:http://blogs.sun.com/Swing/entry/awt_swt_swing_java_gui1
作者:williamchen
译者:Matthew Chen
备注:本文是四篇文章中的第二。
Implementations
The above comparison is mainly conducted in API level. Let's continue the comparison with focus on implementation details. In all the difference between Swing and SWT/AWT is that Swing is purely implemented in Java, while SWT and AWT is a mixture of Java and JNI. Of course, their target is same, to provide a cross-platform APIs. However to achieve this, SWT and AWT has to sacrifice some components and some features so that they can provide a universal APIs.
上一篇的比较主要是在API级别上的。让我们将比较的焦点转移到实现细节上。Swing和SWT/AWT的区别是Swing是纯Java实现,而SWT和AWT是Java和JNI的混合。当然,它们的目标都是相同的,提供一个跨平台的APIs。然而为了达到这一点,SWT和AWT不得不牺牲一些组件和特性以提供一个通用的APIs。
AWT
An AWT component is usually a component class which holds a reference with a peer interface type. This reference points to a native peer implementation. Take java.awt.Label for example, its peer interface is LabelPeer. LabelPeer is platform independent. On every platform, AWT provides different peer class which implements LabelPeer. On Windows, the peer class is WlabelPeer, which implement label functionalities by JNI calls. These JNI methods are coded in C or C++. They do the actual work, interacting with a native label. Let's look at the figure. You can see that AWT components provide a universal public API to the application by AWT component class and AWT peers. A component class and its peer interface are identical across platform. Those underlying peer classes and JNI codes are different.
一个AWT组件通常是一个包含了对等体接口类型引用的组件类。这个引用指向本地对等体实现。举java.awt.Label为例,它的对等体接口是LabelPeer。LabelPeer是平台无关的。在不同平台上,AWT提供不同的对等体类来实现LabelPeer。在Windows上,对等体类是WlabelPeer,它调用JNI来实现label的功能。这些JNI方法用C或C++编写。它们关联一个本地的label,真正的行为都在这里发生。作为整体,AWT组件由AWT组件类和AWT对等体提供了一个全局公用的API给应用程序使用。一个组件类和它的对等体接口是平台无关的。底层的对等体类和JNI代码是平台相关的。
SWT
SWT implementation also utilize JNI methodology. But the detail is different from that of AWT. SWT evangelists often became furious when they heard people describing SWT as another AWT. Steve Northover, the father of SWT, once complained about this.
SWT也使用JNI的方法论来实现。但细节不同于AWT。SWT的拥护者听到人们拿SWT和AWT相提并论可是会很生气的,Steve Northover,SWT之父,就曾为此抱怨过。
Yes, they are different. Let's delve into SWT code. In SWT, the only identical part on every platform is the component interface. That is class and method definition signature. All the underlying codes are different from platform to platform. SWT provides an OS class for every platform. This class encapsulates many native APIs by JNI methods. And then SWT component class glues these JNI method together to provide a meaning functionality.
没错,它们是不同的。让我们深究SWT的代码。在SWT中,各个平台上唯一相同的部分是组件的接口,是类和方法的定义签名。所有的底层代码都是平台差异的。SWT为每个平台提供了OS类。这个类用JNI封装了许多本地APIs。SWT组件类通过把这些JNI方法黏合在一起提供一个有意义的功能。
For example, on Windows, text field selection can be conducted by only one system call. This system call is implemented in the Windows OS class as an native method. So there is only one JNI call in the setSelection method of Text on Windows.
例如,在Windows上,文本域的选择是由一个系统调用处理的。这个系统调用在Windows的OS类中作为一个本地方法实现。所以在Windows平台的Text的setSelection方法中只用到了一个JNI调用。
However, on motif platform, text selection involves two native calls. Again SWT implements these two calls in the motif OS class. So the component class on motif needs to call these two calls to achieve text selection.
然而,在motif上,文本域的选择包含两个本地调用。SWT就在motif的OS类中实现了两个调用。所以在motif上组件类需要作两次调用来实现文本的选择。
By now, you can see the major difference between SWT and AWT is that they use different peer code to wipe out the differences. SWT uses java code, or java peer to glue system calls implemented by JNI. However, AWT put these code in native peers, which complicates the situation. I think SWT's method is more clever.
现在你应该能看出SWT和AWT的最大不同了,它们使用了不同的对等体编程方式来消除平台差异。SWT用java代码或有JNI实现的java对等体来黏合系统调用。而AWT把代码包含在对等体中,使情况复杂化了,我个人觉得SWT的方法更加明智。[是否我翻译有问题,因为我并不觉得是这样更明智,SWT的无则模拟是不必要的,这是使用者才去做的事,SWT作为提供者应该无则C++实现,当然实现的是最核心的高度复用的又或者需要极大性能支持的,毕竟带了动态链接库,索性多放点东西。]
Swing
When it comes to Swing, everything becomes clear and straight forward. Except the top containers, Swing implementation depends on nothing of individual platform. It has all the controls and resources. What Swing needs is event inputs to drive the system, and graphics, fonts and colors which are inherited from the top AWT containers. Ordinary Swing components can be seen as a logical area on AWT containers. They do not have a peer registered. All swing components added to a same top container share its AWT peer to acquire system resources, such as font, graphics etc. Swing has its own component data structure stored in JVM space. It manages drawing process, event dispatching and component layout totally by itself.
到了Swing这里,一切就变得清晰和直接了。除了顶层容器,Swing的实现不依赖于具体平台。它掌管了所有的控制和资源。Swing所需要的是事件输入来驱动系统,以及承接自顶层AWT容器的图形处理,字体和颜色。普通的Swing组件可以看作是AWT容器的一块逻辑区域。它们并没有注册对等体。所有添加到同一顶层容器的Swing组件共享它的AWT对等体以获取系统资源,如字体,图形处理等。Swing将组件自己的数据结构存储在JVM的空间中。它完全由自己管理画图处理,事件分发和组件布局。
Resource Management
Because both AWT and SWT holds reference to native components, they must release them in a correct manner to avoid memory leaks and JVM crashes. AWT takes most of the resource management task to the system, relieving developers from tedious resource management. However this complicates the AWT implementation. Once it is implemented, developers has less opportunities to make errors and crash their applications.
由于AWT和SWT都持有对本地组件的引用,它们必须以正确的方式释放这些引用以避免内存泄露和JVM崩溃。AWT将绝大多数资源管理任务交给系统,将开发者从单调乏味的资源管理中解救出来。然而这使得AWT的实现复杂化了。一旦它实现了,开发者很少有机会犯错误并使他们的程序崩溃。
SWT follows another way. In essence, SWT let the developers to manage those resources by themselves. There's a famous rule there. That is those who create the component should release it as well. Thus developers have to explicitly and carefully call the dispose method on every component or resource he has created. This greatly simplifies the SWT implementation model. But it puts the developers at the risk that they might easily crash their applications due to incorrect coding.
SWT用的是另一种方法。大体上,SWT让开发者自己来管理资源。它的一条著名的规则是:谁创建,谁释放。因此开发者必须谨慎地显式调用dispose方法释放每一个由他创建的组件和资源。这简化了SWT的实现模型,但把开发者摆在了因错误编码而易于造成程序崩溃这一风险之上。
Emulation difference模拟方式的区别
Both Swing and SWT uses emulation in their implementation. SWT emulate those components which are missing from one platform. The difference is that SWT's emulation is much more like those of AWT Canvas. SWT has a Composite class which has a counterpart peer in the operating system. It gets all the resources it needs such as graphics object, font or color from its own peer. It gets all the events directly from the operating systems process it. However, swing component does not have a counterpart peer. It is only logical area of the top container. The resources it acquires from itself are in fact borrowed from those top containers' peer. As to event, swing event is not the event generated from the underlying system. It is in fact a pseudo event which is generated when the top container processes AWT event. We'll detail it later in the event parts.
Swing和SWT在它们的实现上都使用了模拟。SWT只模拟平台上缺失的组件。区别是SWT的模拟更像是AWT的Canvas实现的模拟。SWT的Composite类有它自己在操作系统中相应的对等体。它从自己的对等体中获得所有它所需要的资源如图形处理的对象,字体和颜色等。它直接从操作系统获取所有的事件并进行处理。然而,Swing组件在操作系统中没有相应的对等体。它只是一块顶层容器中的逻辑区域,实际上它从顶层容器的对等体中借用资源。Swing的事件并不是底层系统产生的事件。它们实际是由顶层容器处理AWT事件所产生的伪事件。我们会在稍后的事件部分中详细介绍它。
Graphical Layer Architecture图形层结构
The other difference is that swing components have its own separate z-order system from AWT components. As I mentioned above, swing components share a same peer with the top AWT container. Therefore, swing components have same z-order with the top container. SWT and AWT components each have a different z-order from the top container. So if AWT components and Swing components are mixed together, Swing components will probably be hidden by AWT components, because z-order values of AWT components are higher than the top container, while Swing components have the same z-order value with the top container. When operating system begin to update the UI, top container and swing components are always painted earlier than those of AWT. When they finished painting, AWT components will wipe out what swing has painted. So it is not encouraged to mix swing and AWT components together. If there are floating swing components such as menu, AWT component probably can hide menus.
另一个不同之处是Swing组件的z-order系统是来自于AWT组件的。如上所述,Swing组件与顶层AWT容器共享一个对等体。因此,Swing组件也和顶层容器有相同的z-order。SWT和AWT组件都有不同于顶层容器的z-order,通常是高于顶层容器。故而如果AWT组件和Swing组件混合在一起的话,Swing组件将可能被AWT组件遮住。当操作系统开始更新UI的时候,顶层容器和Swing组件总是先于AWT组件绘制。当它们完成绘制,AWT组件会覆盖Swing可能绘制过的地方。因此不提倡Swing和AWT组件的混用。如果有一个浮动的Swing组件如菜单,AWT组件很可能遮盖菜单。
Layout Manager布局管理器
Not all of the elements of the three are different. Layout manager is an exception. What is layout manager? When developing a gui application, developers need to re-position or resize components when the container is resized. In traditional language, this is usually achieved by listening to resizing events. The code snippets usually scattered around and mess up the code. Java introduces the idea of wrapping layout codes together and name it Layout Manager. When a layout manager object is set to the container, it is automatically connected to resizing events. When resizing happens, layout method of the manger is called to re-position or reshape its children components.
并不是三者中的所有部分都是不同的。布局管理器是一个例外。开发GUI应用程序,当容器改变大小的时候,组件需要重定位或改变大小。在传统的编程语言中,这依靠监听大小改变的事件来实现。相应的片段散落在源代码的各个角落降低了程序的可读性。Java引入了将布局代码封装的思路,称之为布局管理器。当布局管理器对象被设置到一个容器中,它自动处理大小改变的事件。当大小改变时,管理器的布局方法被调用以重定位子组件或调整它们的形状。
AWT, SWT and Swing agree on this infrastructure. However every one has its own specific layout managers. Because AWT and Swing share a common parent class java.awt.Component, therefore AWT and Swing layout manger can work interchangeably.
AWT,SWT和Swing都以这样的方式来组织,而都有它们各种独特的布局管理器。由于AWT和Swing拥有一个共同的超类java.awt.Component,它们的布局管理器可以交替地使用。
(To be continued ...)