Picses' sky

          Picses' sky
          posts - 43, comments - 29, trackbacks - 0, articles - 24

          AWT, SWT, Swing: Java GUI Clean Up (3) [翻]

          Posted on 2007-11-29 08:21 Matthew Chen 閱讀(1049) 評論(0)  編輯  收藏 所屬分類: Java SE

          原文:http://blogs.sun.com/Swing/entry/awt_swt_swing_java_gui2

          作者:williamchen

          譯者:Matthew Chen

          備注:內(nèi)容有一些也是我以前不知道的,我也不得不說兩句,紅字為評論。

          Look And Feel觀感


          Native toolkits including SWT and AWT do not support Look And Feel mechanism. They bind their components to operating systems, which have both pros and cons. One of the cons is that they cannot support pluggable Look And Feel. Handling the drawing process to operating system deprives of their ability to customize component look and feel. This prevent them from providing Look And Feel mechanism. Look And Feel mechanism is becoming more and more indispensable in GUI toolkit.

          包括SWT和AWT在內(nèi)的本地工具集并不支持Look And Feel機制。它們將組件捆綁在操作系統(tǒng)上,有其優(yōu)勢和劣勢。其中的一個劣勢是它們不支持可插拔的Look And Feel。將繪制處理交由操作系統(tǒng)完成剝奪了它們實現(xiàn)自定義組件Look And Feel的能力,也就使得它們無法提供這種機制。Look And Feel機制越來越成為GUI工具集中不可缺少的一部分。

          Swing has wonderful Look And Feel support. You can even change Swing application's look and feel dynamically. This is an insurmountable task for AWT and SWT, since they handle their control entirely to operating system. I've heard many people complains about Sun on Swing design. They think why Swing can not be built on SWT like AWT. In fact, Look And Feel mechanism is one of reason why Swing should go in that direction. If Swing follows the way that wrapping existing components and emulating non-existing components, it cannot provide Look And Feel mechanism. Providing pluggable Look and Feel mechanism is an insurmountable task to native strategy.

          Swing擁有很好的Look And Feel支持。你甚至可以動態(tài)地改變Swing應用程序的Look And Feel,鑒于AWT和SWT將組件控制完全交給操作系統(tǒng)處理,這是它們所無法超越的任務。我曾經(jīng)聽很多人抱怨過Sun在Swing上的設計。他們覺得Swing為什么不像SWT那樣沿用AWT的思路呢?事實上,Look And Feel機制正是Swing走到這個方向上的原因之一。如果Swing遵循的是包裝已有的組件并模擬不存在的組件的路線,那它就無法提供Look And Feel機制。因為提供Look And Feel機制是本地策略所無法完成的任務。

          Graphics and Fonts圖形和字體

          Since Swing is an emulated system, its graphics tools is much more powerful than those of AWT and SWT. Swing bases its whole system on two fundamental components, one is Java 2D and the other is AWT. Java 2D is a powerful library in Java. It provides rich features of advanced image processing, color management, graphical drawing and filling, coordination system transmission and font manipulations. AWT and SWT only provides limited access to these features. Compared to Java 2D, they are comparably primitive and inferior.

          Swing作為一個仿生系統(tǒng),它的圖形工具集較之AWT和SWT強大許多。Swing基于其自身系統(tǒng)中的兩個基礎組件群:Java 2D和AWT。Java 2D在Java中是強大的類庫,它為高級圖像處理,顏色管理,圖形繪制和填充,坐標系變換和字體生成提供豐富的特性。相較之下,AWT和AWT僅對這些特性提供有限訪問,它們是相對原始和低級的。

          JavaBeans Specification Conformity JavaBeans規(guī)范一致性

          Swing and AWT was designed with JavaBeans specification in mind. So their component classes conform to JavaBeans specification. However SWT does not quite conforms to this specification. For example, there's no empty-argument constructor in every component classes. Every component in SWT must has at least a single parameter constructor. This parameter is the parent of the components. That means whenever a component is created, it must be immediately added to a component tree. A component cannot exist without registered native peer. By this way, SWT wants the components created by programmer can be automatically released when dispose methods of display is called.

          Swing和AWT在設計之初就秉承了JavaBeans規(guī)范,它們的組件類與JavaBeans規(guī)范一致。然而SWT并沒有很好的遵循這一規(guī)范。例如,在SWT的組件類中沒有無參的構造器。每個組件都必須至少擁有一個單參數(shù)的構造器。這個參數(shù)就是父組件的引用。這意味著無論何時組件被創(chuàng)建,它都直接被添加到一棵組件樹中。一個組件無法脫離于已注冊的本地對等體而存在。這樣,SWT就能讓由編程者創(chuàng)建的組件在display的dispose方法被調(diào)用的時候自動被釋放。

          More on Resource Management更多在資源管理方面的內(nèi)容

          SWT's strategy of component constructor can eliminate some possibility of memory leaks. AWT has the similar question about resource management. But it resolve the issues using a different way. When an AWT component is created, the counterpart peer will not immediately be added. When it is added to a component tree, but the tree is not visible yet, the peer will be still not created. Only when top container is set visible, will these peers be created. The method creating the peer generally is located in addNotify method. They generally call their parent's addNotify recursively until all of the peers on the component tree are created. When top container is dismissed by calling dispose method, a reverse method removeNotify will be called recursively to release these peers. By this way, AWT manage its resource without any interference from the developers.

          SWT的組件構造器策略可以排除某些內(nèi)存泄露的可能性。AWT在資源管理方面也有類似的問題。但它采用了不同的方式解決。當AWT組件被創(chuàng)建的時候,相應的對等體并不會立即被創(chuàng)建。即便它被添加到一棵組件樹,而如果這棵樹還不可見,那么對等體仍不會被創(chuàng)建。只有當頂層容器被設為可見,這些對等體才會被創(chuàng)建。創(chuàng)建對等體的方法通常在addNotify中,它們通常遞歸地調(diào)用父組件的addNotify直到整棵組件樹上的對等體都被創(chuàng)建了。當頂層容器由dispose方法銷毀的時候,一個對應的方法removeNotify將會被遞歸地調(diào)用以釋放這些對等體。這樣,AWT在不由開發(fā)者介入的情況下管理了它的資源。

          Event System事件系統(tǒng)

          An event is the message sent to a GUI system, either from the outside or from the system itself, which requires certain action to be taken. These events include I/O interrupts from computer devices such as mouse or keyboard or network ports, and logical events triggered by GUI system, such as ActionEvent posted by a button.

          一個事件要求特定的動作被執(zhí)行,它被作為消息由外界或系統(tǒng)自身發(fā)送給GUI系統(tǒng)。這些事件包括來自計算機設備如鼠標鍵盤和網(wǎng)絡端口的I/O中斷,以及GUI系統(tǒng)的邏輯事件觸發(fā),比如一個按鈕的ActionEvent事件。

          Single-Threaded vs Multiple-Threaded 單線程 vs 多線程

          Dispatching events can follow two different models. One is called single-threaded dispatching model and the other multiple-threaded dispatching model.

          事件分發(fā)遵循兩種不同的模型。單線程分發(fā)模型和多線程分發(fā)模型。



          In single-threaded dispatching model, an event is pumped from the queue and processed in the same thread immediately. After the event being processed, next pending event in the queue is pumped again and continues the next round of cycle. In multiple-threaded dispatching model, the thread fetching the events from the queue launches another thread called task thread, and hand the event over to it for processing. The thread responsible for fetching the event does not wait for the end of the processing thread. It simply goes on to fetch next pending event and dispatch it.

          在單線程分發(fā)模型中,一個事件從隊列中抽出并在同一個線程中被立即處理。事件處理后,隊緊跟著的下一個事件再被抽出并繼續(xù)下一輪的循環(huán)。在多線程分發(fā)模型中,從隊列中獲取事件的線程啟動另一個被稱作任務線程的線程,并把事件交給它處理。而獲取事件的線程并不等待處理線程的結束。它簡單的獲取下一個線程并分發(fā)它。

          Event processing usually involves changing application data. While these data are often the source data that components display. Multiple-threaded dispatching can easily raise synchronization issues. It generates multiple event processing threads, which might interfere with each other. In a stable GUI system, component should be able to keep the view synchronized with the model. Because of the synchronization issue, multiple-threaded model requires developers to be more experienced in concurrent programing. For ordinary programmers, it is very easy to make synchronization errors. Therefore many GUI system don't use this model.

          事件處理通常涉及應用程序的數(shù)據(jù)變化。而且這些數(shù)據(jù)經(jīng)常是組件需要顯示的。多線程分發(fā)很容易產(chǎn)生同步問題,它產(chǎn)生多個可能互相干擾的事件處理線程。在一個穩(wěn)定的GUI系統(tǒng)中,組件應該能夠保持視圖與模型間的同步。由于同步問題的出現(xiàn),多線程模型要求開發(fā)者擁有更多并發(fā)編程的經(jīng)驗。而對于普通編程人員,造成同步錯誤是很容易的。因此許多GUI系統(tǒng)并不使用這一模型。

          Single-threaded model provide natural synchronizations by enforcing sequential event processing. AWT, SWT and Swing all use this model to dispatch events. But single-threaded model also has its own issues. One of them is thread engrossment. Since all events are dispatched by a single thread, if one event processing last too long, it will hold back pending events from being processed. If there are PAINT event holding back, then the screen will appear to be unresponsive. This usually make user feel that the software is slow. There are many such slow applications that are programmed by inexperienced developers. What they did is most probably cramming a listener method with time-consuming tasks. Swing is especially prominent, since it is widely used. This has brought swing a bad reputation of slow and ugly. In fact, swing application can be very responsive if you knows to thread.

          單線程模型通過強制事件序列化地被處理提供了實際上的同步。AWT,SWT和Swing 都采用了這一模型來分發(fā)事件。但單線程模型也會有它自己的問題。其中之一就是線程專注。既然所有的事件都在一個線程中被分發(fā),如果其中的一個事件的處理費時過久,將會拖延下一個事件的抽取和執(zhí)行。如果有一個PAINT事件被延后,那么在屏幕上就會呈現(xiàn)為無法響應。這經(jīng)常使用戶感覺到軟件很慢。許多這樣的低效程序是由于開發(fā)者的經(jīng)驗不足造成的。他們的做法是將耗時任務填充到監(jiān)聽器方法中。由于這種錯誤的編程方式在Swing中大量被使用而尤為突出,這也是它慢而丑陋的壞名聲的由來之一。實際上,如果你懂得使用線程,Swing應用程序可以表現(xiàn)出很高的響應度。[沒錯,三者在gui上都是典型的單線程事件分發(fā)模式,如果你了解操作系統(tǒng)和編程語言的實現(xiàn)細節(jié),你就不會對此表現(xiàn)的詫異,因為單核中,多線程和多進程本質上也是單任務處理基礎上的抽象。]

          Thread Safety線程安全


          The solution to the above issue is launching a separate worker thread to handle long-time processing, thus releasing the event dispatching thread to continue. Just like what multiple-threaded model does. But that also invites the synchronization issues that happen in multiple-threaded model. Many GUI toolkits often setup some innate mechanism to avoid this, for example, by a complex lock on a component tree. Developers don't have to worry about how to program to be safe. This kind of toolkit is called thread-safe. AWT is one of them.

          上述問題的解決方案是啟動一個單獨的工作者線程來完成耗時處理,這樣就能把事件分發(fā)線程釋放處理以繼續(xù)運作。如果多線程模型中所做的那樣,然而這同樣會引入在多線程模型中出現(xiàn)的同步問題。許多GUI工具集都有自己先天性的機制來解決這一問題,例如,在組件樹上的組合鎖。開發(fā)者不需要為如何安全編程而操心。這樣的工具集被成為線程安全的。AWT就是其中之一。

          However, it is often too complex to build such GUI system and usually it creates a lot overhead because of unnecessary synchronization. Therefore, Swing and SWT were designed to be thread unsafe. That means developers have to program carefully when they want to do multi-threading task. There is a little difference between SWT and Swing about runtime behavior towards thread safety. SWT always checks if the action modifying component takes place in the event dispatching thread. By this way, developers can find out the probable synchronization issues. Swing does not have. This is a shortage of Swing, which I think should not be so hard to implement.

          然而,由于不必要的同步使得建立這樣的GUI系統(tǒng)過于負責并造成了額外的開銷。因此,Swing和SWT被設計為非線程安全的,這意味著開發(fā)者必須謹慎地實現(xiàn)他們的多線程任務。SWT和Swing在運行時線程安全行為上有一個小小的區(qū)別。SWT總是檢查改變組件的操作是否在事件分發(fā)線程上執(zhí)行。這樣,開發(fā)者就能夠發(fā)現(xiàn)同步問題。而Swing不這樣,這是Swing的一個不知之初,這其實并不難實現(xiàn)。[Swing似乎有相應的checkLock這樣的方法,檢查是否在事件分發(fā)線程上執(zhí)行應該已經(jīng)由Swing實現(xiàn)了,你不必顯示調(diào)用它,因為你調(diào)用的每一個組件操作方法都首先要執(zhí)行一遍它]

          Event Dispatching Thread事件分發(fā)線程

          AWT reads the primitive event from the operating systems and process them in java codes. AWT event dispatching thread is named as AWT-{OS}-Thread. This thread is launched implicitly by AWT system. When an AWT application launches, this thread starts in background, pumping and draining events from the operating systems. When logical events such button action is fired, it is passed over to action listeners registered on button. Developers can also listen to primitive events such as mouse, keyboard or paint event to write customized AWT components. This is generally done by extending AWT Canvas component. This component enables all of the available event happened on them, and by overriding the event processing method, you can implement a custom component.

          AWT讀取操作系統(tǒng)中的基本事件并在java代碼中處理它們。AWT事件分發(fā)線程被命名為 AWT-{OS}-Thread。這個線程由AWT系統(tǒng)隱式啟動。當AWT應用程序啟動時,這個線程在背后啟動,在操作系統(tǒng)上抽取和移除事件。當諸如按鈕動作這樣的邏輯事件被觸發(fā)時,它傳遞給注冊在按鈕上的操作監(jiān)聽器。開發(fā)者也能為AWT組件編寫鼠標,鍵盤和繪制事件的事件監(jiān)聽器。這通常通過擴展AWT Canvas組件來完成。這一組件支持了所有已提供的事件,而且你可以通過重寫事件處理方法,實現(xiàn)一個自定義的組件。

          However, in Swing, this is a different thread. Swing takes AWT events as the input of its event system. It gets AWT events and after some initial processing, generate a swing counterpart event and put it into its own event queue. Swing has own dispatching thread, usually named EventQueue-0. This thread pump swing events from the event queue, just as AWT does from the operating system. Then it dispatches this event to the target components. Usually an event is first post to the top container components. This event is then processed by the top container's dispatch methods. Then it may re-dispatching or re-targeting this event to a swing component, which in turn continues the processing by its listeners.

          然而,在Swing中,這是一個不同的線程。Swing把AWT事件作為自身事件系統(tǒng)的一個輸入。它獲取AWT事件并做一些初始化處理,產(chǎn)生一個對應的Swing事件并把它放到自己的事件隊列上。Swing也有自己的事件分發(fā)線程,通常命名為EventQueue-0。這個線程從事件隊列中抽取Swing事件,就如同AWT從操作系統(tǒng)中抽取那樣。然后它把事件分發(fā)給目標組件。通常事件首先被分發(fā)給組件的頂層容器,然后由頂層容器的dispatch方法處理,它可能被再分發(fā)或重定向到一個Swing組件,在那里繼續(xù)由自己的監(jiān)聽器進行處理。

          For example, when a mouse moves over a Jbutton on a Jframe, an AWT event targeting Jframe is fired to the AWT-thread. The AWT-thread checks to see if it needs further processing. Then it wraps the event into a Swing MouseEvent object and enqueue it into the EventQueue. Upon receiving the MouseEvent, EventQueue-0 pumps this event out and dispatch it to Jframe by calling its.dispatching method. This method then translate MouseEvent and figure out the target Swing component. Here, the component is Jbutton. After that, it created a new MouseEvent with the new coordinations and event source re-target to the Jbutton. After that, it calls the jbutton.dispatch to continue dispatching. Jbutton.dispatch filters these event to a specific method and finally hit the point where it is dispatched to specific mouse listener.

          例如,當一個鼠標移過一個JButton或JFrame時,一個指向JFrame的AWT事件在AWT線程上觸發(fā)。AWT線程檢查它是否需要作更多的處理,然后把它包裝成一個Swing的MouseEvent對象并把它添加到EventQueue隊列中。當獲得MouseEvent事件后,EventQueue-0抽取這個事件并判斷出目標Swing組件。這里,這個組件是JButton。然后它產(chǎn)生了一個包含相對坐標位置和事件源的新的MouseEvent重定向到這個JButton上,然后調(diào)用這個JButton的dispatch以繼續(xù)分發(fā)。JButton的dispatch過濾事件給特定的方法最終實現(xiàn)由鼠標監(jiān)聽器在該點上的分發(fā)的點擊。

          SWT is more akin to AWT. The only difference is that it requires the developers to explicitly write the event looping codes. However, the underneath implementation is different from that of AWT. Look at the code that SWT read and dispatching events, it reminds you MFC code style.

          SWT更類似于AWT。唯一的區(qū)別是它要求開發(fā)者顯式地書寫事件循環(huán)代碼。然而底層的實現(xiàn)細節(jié)是不同于AWT的。看看SWT的讀取和分發(fā)事件代碼,它會讓你想起MFC的代碼風格。

          Event Listener事件監(jiān)聽器

          AWT, SWT and Swing have similar event listener models. They all use observer pattern, in which, components and listeners are connected by adding listeners to components. This model forms a object-net model as shown in the following figure. When an event is fired and transmitted to the component by dispatching, the component call its listeners to process this event. A listener can also further dispatching this event after processing, or it can event generate a new event and broadcast it to other nodes of the net. Basically there are two different way of broadcasting events. One is synchronously calling other listeners. The other is asynchronously posting this event to the queue, where it can get dispatched during next round of event dispatching.

          AWT,SWT和Swing都有相似的事件監(jiān)聽器模型。它們都使用觀察者模式,組件和監(jiān)聽器的連接方式是把監(jiān)聽器添加到組件上,這組成了一個對象網(wǎng)絡的模型。當事件被觸發(fā)并分發(fā)給組件,組件調(diào)用它的監(jiān)聽器以處理事件。一個監(jiān)聽器也可以繼續(xù)分發(fā)事件給后續(xù)的處理,或產(chǎn)生一個新的事件并把它廣播到網(wǎng)絡中的其他節(jié)點上。基本上有兩種不同的廣播事件方式。一種是同步調(diào)用監(jiān)聽器。另一種是異步地將事件發(fā)送回隊列,它將在新一輪的事件分發(fā)中被分發(fā)出去。

          Besides post method, Swing has some other way of dispatching asynchronous event. One of them is invokeLater from SwingUtilities or EventQueue. This method can wrap a Runnable object into a event and post it into the event queue. This ensures the run method of Runnable can be executed on the event dispatching thread, enabling thread-safety operation. In fact, Swing Timer and SwingWorker is implemented based on this mechanism. SWT also has this counterpart utilities which can asynchronously post events. Its invokeLater counterpart is display.asyncExec which takes a Runnable object as parameter.

          除了直接發(fā)送給隊列的方式,Swing還有一些其他的分發(fā)異步事件的方法。其中之一是調(diào)用SwingUtilities 或EventQueue 的invokeLater,這一方法包裝一個Runnable對象到事件中并把它發(fā)送給事件隊列。這確保了Runnable的run方法能在事件分發(fā)線程上執(zhí)行,保證了線程安全。實際上,Swing的Timer好SwingWorker基于這一機制實現(xiàn)。SWT也有相應的發(fā)送異步事件的方式。它的invokeLater的對應方法是display.asyncExec,它以一個Runnable對象作為參數(shù)。

          (To be continued ...)

           

          主站蜘蛛池模板: 玉林市| 佳木斯市| 和顺县| 望谟县| 潮州市| 桂平市| 汤原县| 德阳市| 安远县| 旬阳县| 达孜县| 尚义县| 宕昌县| 龙口市| 淅川县| 汉中市| 调兵山市| 马尔康县| 专栏| 嘉义县| 应城市| 玉山县| 湘潭县| 乡城县| 金阳县| 武夷山市| 镇平县| 陆丰市| 兴安盟| 宜川县| 蕉岭县| 海伦市| 那曲县| 全州县| 法库县| 长乐市| 安龙县| 长阳| 江川县| 平顺县| 新邵县|