小男孩‘自慰网亚洲一区二区,亚洲一级在线播放毛片,亚洲中文字幕av每天更新,黄aⅴ永久免费无码,91成人午夜在线精品,色网站免费在线观看,亚洲欧洲wwwww在线观看

分享

JAVA Painting-Swing實現(xiàn)紀要一 - - JavaEye技術(shù)網(wǎng)站

 xuanda007 2010-12-15
VA Painting-Swing實現(xiàn)紀要一
首先推薦<Painting in AWT and Swing>by Amy Fowler。
Sun在JDK 1.0最初發(fā)布了圖形API包,代號AWT (abstract windowing toolkit),里面除對GUI基本支持(如結(jié)合各OS的事件分發(fā)機制等)外,自有一套重量級開發(fā)GUI的思路,并提供了一組常規(guī)使用的重量級組件。所謂重量級組件就是每個組件都引用一個本地對等體peer成員對象,這個對等體對象利用本地系統(tǒng)GUI API繪制組件。后來在JDK1.1,AWT包中引進了一套輕量級開發(fā)GUI的新思路,并提供了一組輕量級組件。所謂輕量級組件就是自身沒有本地對等體,而借助重量級組件作為容器來繪制組件。JDK 1.1之后,sun在開發(fā)GUI思路上,在效率,擴展性等方面給出了很多創(chuàng)新,并基于這種新思路推出一套豐富的新組件(輕量級組件),sun為此打出一個新的響亮的代號---Swing,并推薦以后的GUI開發(fā)都應(yīng)該基于SWING的GUI開發(fā)思路開展,應(yīng)該使用或擴展這套SWING的組件。
不論是AWT模式還是SWING模式,Sun的GUI開發(fā)思路都是純OO的。開發(fā)人員總是構(gòu)建多個組件對象實例來組合建立GUI,這些對象是因不同的輸入輸出表現(xiàn)被封裝為多種組件類的實例,而這些組件類是有合理的繼承關(guān)系因而容易擴展的“套件”。而且兩種模式最基本的統(tǒng)一的程序運行思路都是:
1.通過建立各種組件的實例來負責GUI的工作。
2. 約定出GUI變化時機—java應(yīng)用程序隨需發(fā)出請求調(diào)用或?qū)Σ僮飨到y(tǒng)級某種操作的監(jiān)聽(如暴露被遮擋的窗口內(nèi)容)。
3. 在時機到來時由“框架程序”來判斷并調(diào)用應(yīng)該調(diào)用的目標組件實例所提供的各種形式的paint方法(各組件在此方法里通過java 2d API包來實現(xiàn)自己的具體繪制邏輯)來完成各組件繪制。
4. 在GUI的整個生命周期里,通過以上的123模式來完成整個應(yīng)用界面的隨需而變。
下文將主要分析SWING模式。
Swing式 開發(fā)GUI的基本約定包括:SWING提供4個頂層容器JFrame,JDialog,JApplet,JWindow,如果是桌面應(yīng)用,則GUI必須要有一個JFrame,如果是瀏覽器應(yīng)用,則GUI必須要有一個JApplet。其他swing組件,或自定義開發(fā)的Swing組件都擴展自JComponent,并且其實例要存在于頂層容器的層次樹中。下面是一個符合約定的GUI的運行分析。
import javax.swing.JFrame;
import javax.swing.JLabel;
public class BasicSwing {
public static void main(String[] args) {
        javax.swing.SwingUtilities.invokeLater(new Runnable() {
            public void run() {
                createAndShowGUI();
            }
private void createAndShowGUI() {
JFrame frame = new JFrame("BasicSwing");
        frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
        JLabel label=new JLabel("hello world");
        frame.getContentPane().add(label);
        frame.setSize(100,200);
        frame.setVisible(true);
}
        });
    }
}
invokeLater方法在執(zhí)行時首先會延遲創(chuàng)建getToolkit---系統(tǒng)屬性awt.toolkit給出了要加載的類,在windows平臺下即為WToolkit。WToolkit在初始化時會啟動AWT-WINDOWS線程(setDaemon-true),該線程將一直負責從win32系統(tǒng)中獲取底層事件并簡接掛到EventQueue事件隊列中;同時激活A(yù)WT-Shutdown線程(setDaemon-false),該線程一直監(jiān)測是否滿足關(guān)閉GUI的條件(peerMap is null;AWT-WINDOWS is busy;EDT is busy),若是則主動要求關(guān)閉EDT也就是GUI最終退出(因為GUI環(huán)境下只有EDT是非daemon線程);WToolkit還有就是加載sun.java2d.Disposer類,其將在類加載初始化時啟動Java2D Disposer線程(setDaemon-true, MAX_PRIORITY),該線程將一直跟蹤監(jiān)測被廢棄的注冊記錄(WToolkit算一個,還有各種peer),監(jiān)測到后執(zhí)行對應(yīng)的Dispose類來完成相應(yīng)的資源回收。
invokeLater方法同時會創(chuàng)建EventQueue掛在AppContext里,并馬上向EventQueue提交InvocationEvent以執(zhí)行上面例子中的Runable,這將導(dǎo)致啟動第一個AWT-EventQueue-N線程(EDT-(setDaemon-false))。
EDT啟動后將一直從EventQueue獲取AWTEVENT進行dispatch分發(fā)處理,處理過程中若遇到某些意外或被強制中斷都有可能導(dǎo)致EDT熄火,此時AWT-Shutdown被notify檢測徹底終止AWT的時機是否到來,若不滿足條件新的EDT:AWT-EventQueue-N+1將被啟動。
以上將建立起界面GUI的基本運行框架。上述例子的main線程很快退出,而EDT線程將處理InvocationEvent,處理過程即是執(zhí)行Runable.run方法體。
在EDT中,JFrame被構(gòu)造,在其構(gòu)造過程中,會追加dispose記錄即
(addRecord(JFrame.anchorObject, WindowDisposerRecord(appContext,this));)進Java2D Disposer以在失去引用時釋放窗口資源。
隨后JFrame被setvisible,在setvisible過程中,將通過WToolkit createFramePeer,并注冊在AWT-Shutdown的peerMap中以支持AWT-AutoShutDown機制。
Setvisible中將促使調(diào)用peer.pShow-native代碼,即發(fā)送給win32請求顯示窗口,窗口被打開后awt_windows線程在eventloop中得到wm_paint消息進行處理,這是一個異步過程。
awt_windows處理中將有選擇地通過RepaintManager加入重畫記錄區(qū)幾何區(qū)域
RepaintManager. nativeAddDirtyRegio并調(diào)度重畫線程單位在EDT中進行繪制
postEvent-InvocationEvent(ProcessingRunnable),ProcessingRunnable隨后
在EDT中run時將根據(jù)重畫區(qū)記錄執(zhí)行可能的窗口內(nèi)容繪制--即各子組件回調(diào)paint過程。
上述是SWING頂層重量級容器組件的一個繪制場景,可以看到是經(jīng)由awt-windows eventloop到了底層事件后觸發(fā)paint繪制;然而對輕量級swing組件,其paint都是通過java代碼中對repaint調(diào)用而觸發(fā),其會向RepaintManager.addDirtyRegion,同時scheduleProcessingRunnable。這是整個GUI生命周期內(nèi)對繪制的兩種不同的觸發(fā)方式,但觸發(fā)后的處理都是交由RepaintManager。
回過頭去看,JFrame被構(gòu)造的時候就會創(chuàng)建root pane, layered pane,content pane, glass pane等,這些沒有對等體的輕量級Swing組件在構(gòu)造時都將repaint。雖然在創(chuàng)建windows對等窗口之前這些Swing組件就已經(jīng)在要求繪制,但是RepaintManager能夠協(xié)調(diào)好這個步調(diào)(具體即是當收到repaint請求時要判斷情況,像這時的請求因為頂層容器還沒有繪制則不會記錄到重畫區(qū))。所以最終效果就是在peer.pshow的時候只能看到一個空窗口,隨后底層消息到來后通過paint回調(diào)畫這些子組件,最后hello world才顯示出來。如果眼神好,能夠看出這有一個“閃爍”。
這是一個最簡單的swing應(yīng)用程序的基本運行機制分析,下面再具體分析。
Swing的GUI總是由頂層容器組件和輕量級swing組件組合建立,頂層容器和其他組件區(qū)別主要在于頂層容器沒有自身的paint邏輯。
所有頂層容器都是通過使用底層系統(tǒng)API來繪制對等體的方式進行paint,自身沒有java2d的paint邏輯實現(xiàn),對等體畫成什么樣頂層容器就是什么樣,它只是可以控制對等體的一些可配顯示屬性。所以效果就是比如在windows平臺上畫一個jframe,除在桌面上顯示一個窗口還會在任務(wù)欄上顯示一個條目。Swing的4個頂層容器都是在addNotify時才會getToolkit().createPeer(this)(Frame/Dialog/Window),而addNotify并不是在構(gòu)造時被調(diào)用,而是在pack/show或setvisible(這3個所謂的realized具現(xiàn)化方法)時被調(diào)用。創(chuàng)建了對等體peer后還要通過peer.pShow(show/setVisible(true)調(diào)用)調(diào)用才會要求底層系統(tǒng)進行顯示(所以只有pack是不會顯示窗口的)。在顯示窗口后底層消息隊列得到通知,此后隨著窗口被最小化后恢復(fù)或被遮蓋后恢復(fù)等系統(tǒng)操作后同樣能從底層消息得到通知,這時的監(jiān)聽處理將有選擇地通知給RepaintManager一個重畫請求進行窗口內(nèi)容-子組件重畫。
而輕量級swing組件將繪制有關(guān)的職責都委托給了ui成員對象,ui對象使用JAVA2D API 進行繪制,paint成什么樣那就是這個組件的樣子。具體就是在構(gòu)造的時候即要updateUI{setUI(UIManger.getUI(this))}。UIManger會根據(jù)當前L&F的選擇,根據(jù)this.uiClassID來得到ui成員類并建立實例,以后的paint回調(diào)等都推托給ui成員類paint,這也算是一種策略模式。Setui的過程中除了保存這個ui實例外,將repaint來通知RepaintManager進行paint回調(diào)完成組件繪制。輕量級swing組件在addNotify時也會去創(chuàng)建對等體getToolkit().createPeer(this)( LightWeightPeer),但這個peer的實現(xiàn)(NullComponentPeer)是個空殼子,只是作為一個輕量級組件的標記,以后的很多事件處理等都要判斷peer是否instance of LightWeightPeer從而能夠進行不同處理。同樣的Addnotify也不是在構(gòu)造時被調(diào)用,而是在被加入container時被調(diào)用。
注意:構(gòu)造方法本身就是狀態(tài)模式的第一狀態(tài),所以GUI組件的構(gòu)造方法里就應(yīng)該要努力完成自身的繪制來符合自己的地位。輕量級組件就是按這個意義在構(gòu)造方法里去通知repaintmanager進行自身繪制的,但是頂層容器卻將真正的繪制意圖createPeer延遲到了具現(xiàn)方法里。這是因為首先一個合乎思維的表達邏輯是先有容器,再將子組件向容器里添加, 所以最頂層容器總是先行構(gòu)造出來,然后再被一層層地追加輕量級子組件。如果最頂層容器在構(gòu)造時就去具現(xiàn),則就要求后續(xù)的構(gòu)造都應(yīng)該在EDT中進行,而且每次add子組件都要導(dǎo)致revalidate;但若將最頂層容器的繪制分離延遲到具現(xiàn)方法里,則可以表達是在容器里盛滿了要顯示的子組件后再一股腦具現(xiàn)繪制出來的概念,類似于在進行一次web頁面的完整加載,然后注意在具現(xiàn)方法執(zhí)行后如果要操作組件都在EDT中進行即可,而且頂層容器提供一個特有的pack方法,用來一次性對所有子組件驗證大小位置進行重布局,pack之后再show,這樣的一次性計算展現(xiàn)是最有效率的。
頂層容器和輕量級組件就是這樣誕生并繪制的,在此后的生命周期里,都將按事件監(jiān)聽機制完成GUI隨需而變,無論是系統(tǒng)事件,還是因為repaint調(diào)用主動post事件,事件到來后再在EDT中執(zhí)行監(jiān)聽器里的paint繪制。Swing已經(jīng)提供的頂層容器和輕量級組件因各自的定義已經(jīng)注冊了各自的paint監(jiān)聽,開發(fā)人員可以再行維護或按此模式開發(fā)新組件從而滿足應(yīng)用的需要。比如,jbutton默認有mousepress listener,在mousepress事件到來后,監(jiān)聽響應(yīng)中會設(shè)置鼠標顏色加深來表示按下,然后再調(diào)用repaint要求重畫,隨后在EDT中執(zhí)行jbutton的paint回調(diào),此時按深顏色繪制,于是一個被按下的效果就出來了。
下面在具體分析各類事件的處理。
對于頂層容器的受底層事件消息的觸發(fā),當?shù)玫降耐ㄖ且驗閑xpose暴露隱西藏(暴露被遮蔽的部分或恢復(fù)最小化或第一次繪制等)時,處理過程會涉及到雙緩存的處理,即如果可能,直接使用緩存中的舊圖像信息進行覆蓋而不再重新繪制。
所謂雙緩存機制是將一整片的顯示內(nèi)容暫時寫入一張內(nèi)存空間里,然后一次性內(nèi)存拷入顯示區(qū)來進行顯示,這樣處理是因為如果直接寫入顯示區(qū),隨著顯示區(qū)被該寫入線程逐漸寫入,可能經(jīng)歷多次屏幕刷新,導(dǎo)致每次刷新都形成過程圖像,給人眼造成閃爍感覺;同時一個副收益就是可以針對每個窗口都做緩存待用(而不僅僅是針對一個屏幕雙緩存),當窗口被遮擋的部分重現(xiàn)時直接拷貝緩存來覆蓋,不用再執(zhí)行繪畫邏輯,提高了效率。
現(xiàn)在的OS一般都提供雙緩存機制支持,如果底層系統(tǒng)自身支持以每個窗口為單位做雙緩存,則該expose消息將被本地處理,不需要通知進行子組件的繪制;如果底層不支持,則該消息會到達wcomponetpeer.handleexpose中進行回調(diào)處理,此時swing機制下有一個參數(shù)控制的雙緩存機制可以提供。這里的參數(shù)控制需要從RepaintManager的構(gòu)造過程說起。
首先RepaintManager可以通過static setCurrentManager(SomeCurrentManager)來進行全局指定。默認情況使用currentRepaintManager(){new RepaintManager(BUFFER_STRATEGY_TYPE)}得到一個延遲創(chuàng)建的單例。RepaintManager有一段靜態(tài)類初始化過程,涉及到雙緩存設(shè)置:
static {
nativeDoubleBuffering = "true".equals(AccessController.doPrivileged(
                    new GetPropertyAction("awt.nativeDoubleBuffering")));//JVM的啟動參數(shù)控制,默認false
        String bs = AccessController.doPrivileged(
                          new GetPropertyAction("swing.bufferPerWindow"));//是否每窗口緩存。
        if (headless) {
            BUFFER_STRATEGY_TYPE = BUFFER_STRATEGY_SPECIFIED_OFF;
        }
        else if (bs == null) {
            BUFFER_STRATEGY_TYPE = BUFFER_STRATEGY_NOT_SPECIFIED;
        }
        else if ("true".equals(bs)) {
            BUFFER_STRATEGY_TYPE = BUFFER_STRATEGY_SPECIFIED_ON;
        }
        else {
            BUFFER_STRATEGY_TYPE = BUFFER_STRATEGY_SPECIFIED_OFF;
        }
}
private RepaintManager(short bufferStrategyType) {
        // If native doublebuffering is being used, do NOT use
        // Swing doublebuffering.
        doubleBufferingEnabled = !nativeDoubleBuffering;

this.bufferStrategyType = bufferStrategyType;

}
public void setDoubleBufferingEnabled(boolean aFlag) {
        doubleBufferingEnabled = aFlag;

doubleBufferingEnabled(開啟雙緩存),nativeDoubleBuffering(利用本地雙緩存機制),bufferStrategyType(每窗口雙緩存策略)
這幾個參數(shù)將影響到RepaintManager的成員對象paintManager的選擇,也算是一個策略模式,該paintManager是負責繪制的核心類。
private synchronized PaintManager getPaintManager() {
        if (paintManager == null) {
            PaintManager paintManager = null;
            if (doubleBufferingEnabled && !nativeDoubleBuffering) {
                switch (bufferStrategyType) {
                case BUFFER_STRATEGY_NOT_SPECIFIED:
                    if (((SunToolkit)Toolkit.getDefaultToolkit()).
                                                useBufferPerWindow()) {//windows下是否禁用vista dwm,在沒有聲明bufferPerWindow的情況下由windows系統(tǒng)特性確定paintmanager。
                        paintManager = new BufferStrategyPaintManager();
                    }
                    break;
                case BUFFER_STRATEGY_SPECIFIED_ON:
                    paintManager = new BufferStrategyPaintManager();
                    break;
                default:
                    break;
                }
            }
            // null case handled in setPaintManager
            setPaintManager(paintManager);
        }
        return paintManager;
    }
void setPaintManager(PaintManager paintManager) {
        if (paintManager == null) {
            paintManager = new PaintManager();
        }

}
回到上文,當handleexpose時,通過getPaintEventDispatcher 來createPaintEvent,在UIManager.initialize根據(jù)RepaintManager.HANDLE_TOP_LEVEL_PAINT(屬性swing.handleTopLevelPaint)確定是SwingPaintEventDispatcher還是直接使用PaintEventDispatcher。
若為false,在PaintEventDispatcher中,將直接創(chuàng)建PaintEvent-PAINT提交,此后該事件經(jīng)合并后將由wcomponentpeer.handleEvent,該處理將通過一個自身維護的paintArea幾何臟區(qū)域進行重畫區(qū)域優(yōu)化,最終委托給Container進行子組件繪制,這是非SWING模式-即AWT模式,沒有雙緩存的概念。
補充:在Swing和它的RepainManager出現(xiàn)以前,GUI的模式-AWT模式總是要先形成一個PaintEvent(觸發(fā)可能來自底層消息-PAINT類型,也可能來自repaint-UPDATE類型),post給EventQueue,并組織一次合并:
public abstract class WComponentPeer{
void handlePaint(int x, int y, int w, int h) {
    System.out.println("handlePaint>>>"+x+":"+y+":"+w+":"+h);
        postPaintIfNecessary(x, y, w, h);
    }

    private void postPaintIfNecessary(int x, int y, int w, int h) {
        if ( !ComponentAccessor.getIgnoreRepaint( (Component) target) ) {
            PaintEvent event = PaintEventDispatcher.getPaintEventDispatcher().
                createPaintEvent((Component)target, x, y, w, h);
            if (event != null) {
                postEvent(event);
            }
        }
}
public class PaintEventDispatcher {
public PaintEvent createPaintEvent(Component target, int x, int y, int w,
                                       int h) {

        return new PaintEvent((Component)target, PaintEvent.PAINT,
                              new Rectangle(x, y, w, h));
    }

public abstract class Component{
public void repaint(long tm, int x, int y, int width, int height) {
        if (this.peer instanceof LightweightPeer) {
                ~~~
                parent.repaint(tm, px, py, pwidth, pheight);
            }
        } else {
            if (isVisible() && (this.peer != null) &&
                (width > 0) && (height > 0)) {
                PaintEvent e = new PaintEvent(this, PaintEvent.UPDATE,
                                              new Rectangle(x, y, width, height));
                Toolkit.getEventQueue().postEvent(e);
            }
        }
}

public class EventQueue{
private void postEvent(AWTEvent theEvent, int priority) {
        if (coalesceEvent(theEvent, priority)) {//post之前總是需要合并
            return;
        }


private boolean coalesceEvent(AWTEvent e, int priority) {

        if (e instanceof PaintEvent) {
            return coalescePaintEvent((PaintEvent)e);//對paintevent進行一輪合并處理,導(dǎo)致同一重量級組件的多次paintevent被合并為一個paintevent等待dispatch。以提高效率
        }

然后EDT中在Component.dispatchImpl中委托給wcomponentpeer處理。

public abstract class Component{

dispatchEventImpl{
/*
         * 9. Allow the peer to process the event.
         * Except KeyEvents,
         */
            if (tpeer != null) {
                tpeer.handleEvent(e);
            }
       

public abstract class WComponentPeer{

public void handleEvent(AWTEvent e) {

switch(id) {
            case PaintEvent.PAINT:
                // Got native painting
                paintPending = false;
                // Fallthrough to next statement
            case PaintEvent.UPDATE:
                // Skip all painting while layouting and all UPDATEs
                // while waiting for native paint
                if (!isLayouting && ! paintPending) {
                    paintArea.paint(target,shouldClearRectBeforePaint());
                }
                return;
            default:
            break;
        }

Peer處理過程中將利用自身維護的PaintArea進行重畫區(qū)域的優(yōu)化,并執(zhí)行子組件paint回調(diào)。
/**
     * Invokes paint and update on target Component with optimal
     * rectangular clip region.
     * If PAINT bounding rectangle is less than
     * MAX_BENEFIT_RATIO times the benefit, then the vertical and horizontal unions are
     * painted separately.  Otherwise the entire bounding rectangle is painted.
     *
     * @param   target Component to <code>paint</code> or <code>update</code>
     * @since   1.4
     */
    public void paint(Object target, boolean shouldClearRectBeforePaint) {
        Component comp = (Component)target;
~~~
        if (ra.paintRects[HORIZONTAL] != null && ra.paintRects[VERTICAL] != null) {
            Rectangle paintRect = ra.paintRects[HORIZONTAL].union(ra.paintRects[VERTICAL]);
            int square = paintRect.width * paintRect.height;
            int benefit = square - ra.paintRects[HORIZONTAL].width
                * ra.paintRects[HORIZONTAL].height - ra.paintRects[VERTICAL].width
                * ra.paintRects[VERTICAL].height;
            // if benefit is comparable with bounding box
            if (MAX_BENEFIT_RATIO * benefit < square) {
                ra.paintRects[HORIZONTAL] = paintRect;
                ra.paintRects[VERTICAL] = null;
            }
        }
        for (int i = 0; i < paintRects.length; i++) {
            if (ra.paintRects[i] != null
                && !ra.paintRects[i].isEmpty())
            {
                // Should use separate Graphics for each paint() call,
                // since paint() can change Graphics state for next call.
                Graphics g = comp.getGraphics();
                if (g != null) {
                    try {
                        g.setClip(ra.paintRects[i]);
                        if (i == UPDATE) {
                            updateComponent(comp, g);
                        } else {
                            if (shouldClearRectBeforePaint) {
                                g.clearRect( ra.paintRects[i].x,
                                             ra.paintRects[i].y,
                                             ra.paintRects[i].width,
                                             ra.paintRects[i].height);
                            }
                            paintComponent(comp, g);
                        }
                    } finally {
                        g.dispose();
                    }
                }
            }
        }
    }
若為true,在SwingPaintEventDispatcher.createPaintEvent,
if (component instanceof RootPaneContainer) {//如果是頂層容器
            AppContext appContext = SunToolkit.targetToAppContext(component);
            RepaintManager rm = RepaintManager.currentManager(appContext);
            if (!SHOW_FROM_DOUBLE_BUFFER ||//參數(shù)swing.showFromDoubleBuffer控制,默認true確定swing//是否會考慮雙緩存支持
                  !rm.show((Container)component, x, y, w, h)) {
                rm.nativeAddDirtyRegion(appContext, (Container)component,
                                        x, y, w, h);
            }
return new IgnorePaintEvent(component, PaintEvent.PAINT,
                                        new Rectangle(x, y, w, h));//返回一個將被忽略的假事件提交

如果SHOW_FROM_DOUBLE_BUFFER 考慮雙緩存支持,將進行rm.show,其交給getPaintManager().show,這時的paintmanager是經(jīng)過了前面所說的幾個參數(shù)選擇的,也就是說,考慮當前是否當前正使能雙緩存doubleBufferingEnabled,是否不使用本地雙緩存nativeDoubleBuffering, BUFFER_STRATEGY_TYPE是否指定了每窗口緩存的雙緩存支持策略,如果沒有指定策略是否或本地windows系統(tǒng)環(huán)境沒有開啟vista dwm效果,如果都滿足將使用BufferStrategyPaintManager,借由swing提供每窗口雙緩存機制,檢查swing記錄中是否具有有效緩存,若存在則會要求該區(qū)直接拷貝flip即可,如果沒有成功執(zhí)行雙緩存拷貝,則將加入Repaintmanager重畫區(qū)域進行swing模式的重畫。
頂層容器除了在對等體發(fā)過消息后處理paint,也具有自己的repaint方法去主動創(chuàng)造繪畫時機。
public void repaint(long time, int x, int y, int width, int height) {
       if (RepaintManager.HANDLE_TOP_LEVEL_PAINT) {//屬性swing.handleTopLevelPaint確定,默認true
            RepaintManager.currentManager(this).addDirtyRegion(
                              this, x, y, width, height);
        }
        else {
            super.repaint(time, x, y, width, height);
        }
    }
這里的repaint將首先確定RepaintManager.HANDLE_TOP_LEVEL_PAINT-如果不支持將委托給Component.repaint,形成PaintEvent并進行提交走AWT模式。支持的話將促使RepaintManager加入重畫區(qū)后通過調(diào)度走SWING模式。SWING模式就是走RepaintManager的方式。自身的repaint不會去考慮每窗口雙緩存直接拷貝區(qū)域,因為這時的需求就是要求重新繪畫。
輕量級swing組件在自己的repaint方法去主動創(chuàng)造繪畫時機。
JComponent.Repaint{RepaintManager.currentManager(this).addDirtyRegion}走SWING模式處理。
SWING模式都是借由RepaintManager來安排繪畫,它維護了一個幾何區(qū)域并負責重畫的框架。外界總是要求先加入RepaintManager重繪區(qū),在加入的同時激發(fā)起一個調(diào)度重畫的
SunToolkit.getSystemEventQueueImplPP(context).
                postEvent(new InvocationEvent(Toolkit.getDefaultToolkit(),
                                              processingRunnable))

InvocationEvent。
注意,通過上文分析,對于頂層容器處理底層消息的觸發(fā)時,走swing處理模式而通過swingpaintEventdispatcher去創(chuàng)建painitevent時除向repaintmanager登記臟區(qū)(如果不使用每窗口雙緩存策略)外,還要額外post一個IgnorePaintEvent。該paintevent在隨后的EDT里按awt模式走peer處理時并沒有加入awt的重畫臟區(qū),實際上忽略掉了繪制意義,這樣做避免了在swing和awt兩種模式的重復(fù)繪制,但同時形成依然將paint事件通知到組件的效果。
public void coalescePaintEvent(PaintEvent e) {
        Rectangle r = e.getUpdateRect();
        if (!(e instanceof IgnorePaintEvent)) {
            paintArea.add(r, e.getID());
        }

    本站是提供個人知識管理的網(wǎng)絡(luò)存儲空間,所有內(nèi)容均由用戶發(fā)布,不代表本站觀點。請注意甄別內(nèi)容中的聯(lián)系方式、誘導(dǎo)購買等信息,謹防詐騙。如發(fā)現(xiàn)有害或侵權(quán)內(nèi)容,請點擊一鍵舉報。
    轉(zhuǎn)藏 分享 獻花(0

    0條評論

    發(fā)表

    請遵守用戶 評論公約

    類似文章 更多