成人免费xxxxx在线视频软件_久久精品久久久_亚洲国产精品久久久_天天色天天色_亚洲人成一区_欧美一级欧美三级在线观看

淺談Swing繪畫的處理過程

開發 后端
本文介紹Swing繪畫的處理過程,以及介紹Swing開發人員在寫繪畫代碼時應該理解的準則。

AWT和Swing繪畫
在AWT中,對于重量級組件,在繪制時按照如下的調用進行:

1)因為系統觸發而重繪:(說白了,就是指這種重繪不是人為的,不是我們自己寫代碼調用repaint()等函數進行重繪,而是系統覺得有必要進行重繪而進行的。)
◆《AWT》確定是一部分還是整個部件需要繪畫。
◆《AWT》促使事件分派線程調用部件的paint()方法。

2)因為程序觸發而重繪:(人為在消息響應函數中或其他地方強制進行重繪的操作)
◆《程序》確定是一部分還是全部部件需要重畫以對應內部狀態的改變。
◆《程序》調用部件的repaint(),該方法向《AWT》登記了一個異步的請求 -- 當前部件需要重畫。
◆《AWT》促使事件分派線程去調用部件的update() 方法。
◆如果部件沒有覆蓋(override)update()方法,update()的默認實現會清除部件背景(如果部件不是“輕量級”),然后只是簡單地調用paint()方法。

說明:不論是那種觸發重繪的方式,均可以歸結到paint()函數上來,那為什么對于程序觸發方式還要有個中間步驟“update()”呢?這是為了讓我們能夠通過重寫update()方法后,在里面進行我們想要的控制,也就是我們可以在這里做點文章。當然我們也可以覆蓋paint()函數,但是有了 update()函數之后,我們就可以不干擾paint(),讓其“全身心”的負責繪制,而在update()這個地方進行我們需要的控制。比如提到的只能用到重量級組件的“增量繪制”,就是首先由系統觸發paint繪制,然后在這個基礎上(也就是背景下),在鼠標左鍵的消息響應函數中調用 repaint,然后重寫update函數,只是讓update函數畫新添加的內容,而不在update函數內部再調用paint函數了,這樣就避開了 paint函數,也就是實現了所謂的“增量繪制”。不過需要說明的是,增量繪制只在一些特殊的GUI部件上好用,比如我們下面給的這個例子(就是剛用來描述“增量繪制”的那個例子)中就是用的Canvas類,該類直接繼承于Component類,注意不是繼承自Container類,因為在 Container類中又實現了自己的paint方法,有了新的機制,這就和我們上述講的這一大套基于Component類的paint方法不一致了。

對于輕量級組件,都是繼承于Container類的,“輕量級”部件需要一個處在容器體系上的“重量級”部件提供進行繪畫的場所。當這個“重量級” 的“祖宗”被告知要繪制自身的窗體時,它必須把這個繪畫的請求轉化為對其所有子孫的繪畫請求。這是由java.awt.Container的 paint()方法處理的,該方法調用包容于其內的所有可見的、并且與繪畫區相交的輕量級部件的paint()方法。因此對于所有覆蓋了paint()方法的Container子類(“輕量級”或“重量級”,Container的子類不一定都是輕量級組件哦,呵呵)都需要在函數的最后調用父類的paint 方法,即super.paint(g)。

最后,對于AWT繪制,給出以下準則:
◆對于大多數程序,所有的客戶區繪畫代碼應該被放置在部件的paint()方法中。
◆通過調用repaint()方法,程序可以觸發一個將來執行的paint()調用,不能直接調用paint()方法。
◆對于界面復雜的部件,應該觸發帶參數的repaint()方法,使用參數定義實際需要更新的區域;而不帶參數調用會導致整個部件被重畫。
◆因為對repaint()的調用會首先導致update()的調用,默認地會促成paint()的調用,所以重量級部件應該覆蓋update()方法以實現增量繪制,如果需要的話(輕量級部件不支持增量繪制) 。
◆覆蓋了paint()方法的java.awt.Container子類應當在paint()方法中調用super.paint()以保證子部件能被繪制。
◆界面復雜的部件應該靈活地使用裁剪區來把繪畫范圍縮小到只包括與裁剪區相交的范圍。

Swing繪畫的處理過程
Swing處理"repaint"請求的方式與AWT有稍微地不同,雖然對于應用開發人員來講其本質是相同的 -- 同樣是觸發paint()。Swing這么做是為了支持它的RepaintManager API (后面介紹),就象改善繪畫性能一樣。在Swing里的繪畫可以走兩條路,如下所述:

(A) 繪畫需求首先產生于一個重量級祖先(通常是JFrame、JDialog、JWindow或者JApplet):
1。事件分派線程調用其祖先的paint()
2。Container.paint()的默認實現會遞歸地調用任何輕量級子孫的paint()方法。
3。當到達第一個Swing部件時,JComponent.paint()的默認執行做下面的步驟:
◆如果部件的雙緩沖屬性為true并且部件的RepaintManager上的雙緩沖已經激活,將把Graphics對象轉換為一個合適的屏外Graphics。
◆調用paintComponent()(如果使用雙緩沖就把屏外Graphics傳遞進去)。
◆調用paintBorder()(如果使用雙緩沖就把屏外Graphics傳遞進去)。
◆調用paintChildren()(如果使用雙緩沖就把屏外Graphics傳遞進去),該方法使用裁剪并且遮光和optimizedDrawingEnabled等屬性來嚴密地判定要遞歸地調用哪些子孫的paint()。
◆如果部件的雙緩沖屬性為true并且在部件的RepaintManager上的雙緩沖已經激活,使用最初的屏幕Graphics對象把屏外映像拷貝到部件上。

注意:JComponent.paint()步驟#1和#5在對paint()的遞歸調用中被忽略了(這里的JComponent指的是在paintChildren()函數中判斷出的需要遞歸調用的組件,在步驟#4中介紹了),因為所有在swing窗體層次中的輕量級部件將共享同一個用于雙緩沖的屏外映像。

(B) 繪畫需求從一個javax.swing.JCponent擴展類的repaint()調用上產生:
1。JComponent.repaint()注冊一個針對部件的RepaintManager的異步的重畫需求,該操作使用invokeLater()把一個Runnable加入事件隊列以便稍后執行在事件分派線程上的需求。
 
2。該Runnable在事件分派線程上執行并且導致部件的RepaintManager調用該部件上paintImmediately(),該方法執行下列步驟:

◆使用裁剪框以及遮光和optimizedDrawingEnabled屬性確定“根”部件,繪畫一定從這個部件開始(處理透明以及潛在的重迭部件)。
◆如果根部件的雙緩沖屬性為true,并且根部件的RepaintManager上的雙緩沖已激活,將轉換Graphics對象到適當的屏外Graphics。
◆調用根部件(該部件執行上述(A)中的JComponent.paint()步驟#2-4)上的paint(),導致根部件之下的、與裁剪框相交的所有部件被繪制。
◆如果根部件的doubleBuffered屬性為true并且根部件的RepaintManager上的雙緩沖已經激活,使用原始的Graphics把屏外映像拷貝到部件。

注意:如果在重畫沒有完成之前,又有發生多起對部件或者任何一個其祖先的repaint()調用,所有這些調用會被折迭到一個單一的調用,即回到最上層(這里的層指的是那種Hierarchy,而不是展現給我們的最上面的那個圖或者按鈕)的SWing部件的paintImmediately(),調用它的repaint()。例如,如果一個JTabbedPane包含了一個JTable并且在其包容層次中的現有的重畫需求完成之前兩次發布對repaint()的調用,其結果將變成對該JTabbedPane部件的paintImmediately()方法的單一調用,會觸發兩個部件的paint()的執行。
 
這意味著對于Swing部件來說,update()不再被調用。

雖然repaint()方法導致了對paintImmediately()的調用,它不考慮"回調"繪圖,并且客戶端的繪畫代碼也不會放置到 paintImmediately()方法里面。實際上,除非有特殊的原因,根本不需要超載paintImmediately()方法。

Swing繪畫準則
Swing開發人員在寫繪畫代碼時應該理解下面的準則:
1。對于Swing部件,不管是系統-觸發還是程序-觸發的請求,總會調用paint()方法;而update()不再被Swing部件調用。
2。程序可以通過repaint()觸發一個異步的paint()調用,但是不能直接調用paint()。
3。對于復雜的界面,應該調用帶參數的repaint(),這樣可以僅僅更新由該參數定義的區域;而不要調用無參數的repaint(),導致整個部件重畫。
4。Swing中實現paint()的3個要素是調用3個分離的回調方法:
◆paintComponent()
◆paintBorder()
◆paintChildren()
Swing部件的子類,如果想執行自己的繪畫代碼,應該把自己的繪畫代碼放在paintComponent()方法的范圍之內。(不要放在paint()里面)。
5。Swing引進了兩個屬性來最大化的改善繪畫的性能:
◆opaque: 部件是否要重畫它所占據范圍中的所有像素位?
◆optimizedDrawingEnabled: 是否有這個部件的子孫與之交迭?
6。如果Swing部件的(遮光)opaque屬性設置為true,那就表示它要負責繪制它所占據的范圍內的所有像素位(包括在paintComponent()中清除它自己的背景),否則會造成屏幕垃圾。
7。如果一個部件的遮光性(opaque)和optimizedDrawingEnabled屬性有一個被設置為false,將導致在每個繪畫操作中要執行更多的處理,因此我們推薦的明智的方法是同時使用透明并且交迭部件。
8。使用UI代理(包括JPanel)的Swing部件的擴展類的典型作法是在它們自己的paintComponent()的實現中調用super.paintComponent()。因為UI代理可以負責清除一個遮光部件的背景,不過這一操作需要根據規則#5中的設定來決定。
9。Swing通過JComponent的doubleBuffered屬性支持內置的雙緩沖,所有的Swing部件該屬性默認值是true,然而把Swing容器的遮光設置為true有一個整體的構思,把該容器上的所有輕量級子孫的屬性打開,不管它們各自的設定。
10。強烈建議為所有的Swing部件使用雙緩沖。
11。界面復雜的部件應該靈活地運用剪切框來,只對那些與剪切框相交的區域進行繪畫操作,從而減少工作量。

【編輯推薦】

  1. 淺析Swing線程包括內容
  2. AWT或Swing混合環境中的事務處理
  3. Swing性能和Swing程序的學習
  4. 比較Swing和SWT的速度
  5. 淺談Swing構造JList
責任編輯:佚名 來源: 機械工業出版社
相關推薦

2009-09-24 17:11:53

Hibernate處理

2011-04-11 16:42:05

Oracle無法啟動

2011-02-21 13:26:47

Postfix郵件處理

2009-07-20 17:49:07

JSF請求處理

2010-06-09 18:17:20

Postfix郵件

2010-06-02 18:00:05

Postfix郵件

2009-07-16 16:01:55

EventQueue

2013-06-20 10:17:34

Android應用

2009-07-14 18:28:58

Swing入門

2009-07-15 13:06:38

Swing組件

2009-07-15 14:29:24

構造JListSwing

2009-07-15 09:59:11

Metal觀感Swing

2009-07-17 12:44:01

NetBeans開發S

2009-07-16 12:58:50

Swing控件

2019-08-19 11:07:41

SQL數據庫優化

2018-05-30 09:47:02

2011-04-13 15:50:49

.htmHTTP請求處理

2009-07-10 17:20:38

Swing構件AWT構件

2011-09-02 14:09:47

OracleDML命令

2021-02-01 09:00:34

Ceph octopu集群運維
點贊
收藏

51CTO技術棧公眾號

主站蜘蛛池模板: 激情欧美一区二区三区中文字幕 | 狠狠的干| 天堂色区 | 成年人视频在线免费观看 | 美女一区| 在线欧美亚洲 | 国产精品久久久久久久久图文区 | 国产日韩欧美在线播放 | 成人在线视频一区二区三区 | 久久国产精品-国产精品 | 日韩手机视频 | 97超碰免费 | 羞羞视频网站免费看 | 91亚洲免费| 大学生a级毛片免费视频 | 牛牛热在线视频 | 二区三区在线观看 | 久久精品免费 | 欧美二区三区 | 午夜av在线 | 国产一区二区在线视频 | 女人毛片a毛片久久人人 | 欧美一区二区视频 | 欧美九九 | 国产三级大片 | 国产高清在线观看 | 国产视频1区 | 国产精品一区二区视频 | 日日综合| 国产视频一区二区三区四区五区 | 久久久久久免费毛片精品 | 国产精品久久久久久久久久免费看 | 中文字幕视频在线观看免费 | 久久久亚洲一区 | 日韩av成人 | 91视频导航 | 亚洲人人| 午夜视频网站 | 亚洲一区二区三区高清 | 亚洲精品av在线 | 毛片一区二区三区 |