中日韩va无码中文字幕_亚洲va中文字幕无码久_又粗又大又黄又刺激的免费视频_成年人国产免费网站

當(dāng)前位置:

java認(rèn)證考試專(zhuān)業(yè)語(yǔ)言串講雙緩沖原理在實(shí)現(xiàn)消除閃爍

發(fā)表時(shí)間:2015/4/9 13:47:24 來(lái)源:互聯(lián)網(wǎng) 點(diǎn)擊關(guān)注微信:關(guān)注中大網(wǎng)校微信
關(guān)注公眾號(hào)

雙緩沖原理在實(shí)現(xiàn)如何消除閃爍

對(duì)于雙緩沖的分析是在坦克大戰(zhàn)游戲的設(shè)計(jì)時(shí)開(kāi)始的,由于當(dāng)時(shí)忙于游戲的整體設(shè)計(jì),所以對(duì)這一個(gè)問(wèn)題沒(méi)有進(jìn)行詳細(xì)的研究,現(xiàn)在就這個(gè)問(wèn)題來(lái)談?wù)勛约旱囊恍┛捶ā?/p>

分析前提出幾個(gè)問(wèn)題:

1、為什么當(dāng)想屏幕上添加圖片之后會(huì)有明顯的閃爍現(xiàn)象?

2、在awt中如何實(shí)現(xiàn)雙緩沖?

3、如何理解swing內(nèi)置雙緩沖以及比較他與awt中消除閃爍的方法區(qū)別在哪里?

首先我們來(lái)解答第一個(gè)問(wèn)題:

我們?cè)谄聊簧献岳L圖形或者是添加圖片都是要通過(guò)所在畫(huà)布的重繪來(lái)實(shí)現(xiàn)的,因此閃爍的出現(xiàn)必然與重繪機(jī)制有著一些關(guān)聯(lián)。在awt中對(duì)于窗體畫(huà)布的重繪其條用順序是repaint() —>update()—>paint();我們來(lái)看看update()的源碼:

Java代碼

/**

* Updates the container. This forwards the update to any lightweight

* components that are children of this container. If this method is

* reimplemented, super.update(g) should be called so that lightweight

* components are properly rendered. If a child component is entirely

* clipped by the current clipping setting in g, update() will not be

* forwarded to that child.

*

* @param g the specified Graphics window

* @see

Component#update(Graphics)

*/

public void update(Graphics g) {

if (isShowing()) {

if (! (peer instanceof LightweightPeer)) {

g.clearRect(0, 0, width, height);

}

paint(g);

}

}

從這里我們可以清晰的看到,update中有一個(gè)清屏的作用,即g.clearRect(0, 0, width, height);然后再在下面調(diào)用paint(g),函數(shù)進(jìn)行重繪。因此到這里的話我們可以在一定程度上對(duì)底層的重繪機(jī)制有一個(gè)了解了。

現(xiàn)在我們明白了,屏幕上之所以出現(xiàn)閃爍是因?yàn)樵趗pdate()方法內(nèi)先要嘩嘩的清空屏幕上原有的東西,然后又嘩嘩的往上畫(huà),所以在我們需要不斷重繪的屏幕上出現(xiàn)閃爍是必然的了,哪怕CPU的速度快之又快。

通過(guò)上述的分析,在awt中我們解決閃爍問(wèn)題的思路也因該隨之產(chǎn)生,即重寫(xiě)update()函數(shù)的代碼,改變它的工作原理。于是我們引進(jìn)一段在坦克大戰(zhàn)中已經(jīng)重寫(xiě)了的update()方法。其中通過(guò)改變重繪函數(shù)paint(g)重繪的畫(huà)布對(duì)象,由窗體的畫(huà)布變?yōu)榻厝〉膱D片上的畫(huà)布gImage,這樣的話就很大程度上改善這個(gè)問(wèn)題了。具體如下

Java代碼

// 重寫(xiě)update方法,先將窗體上的圖形畫(huà)在圖片對(duì)象上,再一次性顯示

public void update(Graphics g) {

if (offScreenImage == null) {

// 截取窗體所在位置的圖片

offScreenImage = this.createImage(WIDTH, HEIGHT);

}

// 獲得截取圖片的畫(huà)布

Graphics gImage = offScreenImage.getGraphics();

// 獲取畫(huà)布的底色并且使用這種顏色填充畫(huà)布(默認(rèn)的顏色為黑色)

Color c = Color.BLACK;

gImage.setColor(c);

gImage.fillRect(0, 0, WIDTH, HEIGHT); // 有清除上一步圖像的功能,相當(dāng)于gImage.clearRect(0, 0, WIDTH, HEIGHT)

// 將截下的圖片上的畫(huà)布傳給重繪函數(shù),重繪函數(shù)只需要在截圖的畫(huà)布上繪制即可,不必在從底層繪制

paint(gImage);

//將接下來(lái)的圖片加載到窗體畫(huà)布上去,才能考到每次畫(huà)的效果

g.drawImage(offScreenImage, 0, 0, null);

}

其實(shí)一言以蔽之就是通過(guò)重寫(xiě)update()方法改變重繪函數(shù)paint(g)重繪的畫(huà)布對(duì)象g。

以上的討論我們都是在awt中進(jìn)行,然后大家就想將繼承Frame改為JFrame試試,結(jié)果一試就傻眼了,屏幕上居然又是嘩嘩的閃了,真是辛辛苦苦去改變,一下回到解放前,我們不是在update()中實(shí)現(xiàn)雙緩沖機(jī)制了嗎?請(qǐng)看下面的一個(gè)對(duì)比測(cè)試:

(1)在awt中測(cè)試update():

Java代碼

// 重寫(xiě)update方法,先將窗體上的圖形畫(huà)在圖片對(duì)象上,再一次性顯示

public void update(Graphics g) {

System.out.println("awt的update()在此...");

if (offScreenImage == null) {

// 截取窗體所在位置的圖片

看看結(jié)果:

要是沒(méi)覺(jué)得意外的話就繼續(xù)往下看

在swing中測(cè)試update():

Java代碼

// 重寫(xiě)update方法,先將窗體上的圖形畫(huà)在圖片對(duì)象上,再一次性顯示

public void update(Graphics g) {

System.out.println("Swing的update()在此...");

if (offScreenImage == null) {

// 截取窗體所在位置的圖片

結(jié)果是:

是不是有點(diǎn)吃驚了,在我沒(méi)有故意編出這個(gè)東西忽悠大伙的前提下我們可以得知,在swing中update()方法并沒(méi)有像awt的update()那樣隨時(shí)被調(diào)用,所以就很好解釋為什么該為繼承JFrame之后屏幕重繪閃爍了。就是你認(rèn)為自己改寫(xiě)了update()方法就會(huì)解決這個(gè)問(wèn)題是一廂情愿的,系統(tǒng)并不買(mǎi)你的帳,調(diào)都沒(méi)去調(diào)用吶!

那么怎么通過(guò)其他的方法消除swing中的閃爍問(wèn)題呢,我們此時(shí)再回到出發(fā)點(diǎn),雙緩沖的核心就是改變paint(g)中的畫(huà)布,那么好了,我直接在paint(g)函數(shù)里實(shí)現(xiàn)不就得了,下面再來(lái)看這一段代碼:

Java代碼

public void paint(Graphics g)

{

// 在重繪函數(shù)中實(shí)現(xiàn)雙緩沖機(jī)制

offScreenImage = this.createImage(WIDTH, HEIGHT);

// 獲得截取圖片的畫(huà)布

gImage = offScreenImage.getGraphics();

// 獲取畫(huà)布的底色并且使用這種顏色填充畫(huà)布,如果沒(méi)有填充效果的畫(huà),則會(huì)出現(xiàn)拖動(dòng)的效果

gImage.setColor(gImage.getColor());

gImage.fillRect(0, 0, WIDTH, HEIGHT); // 有清楚上一步圖像的功能,相當(dāng)于gImage.clearRect(0, 0, WIDTH, HEIGHT)

// 調(diào)用父類(lèi)的重繪方法,傳入的是截取圖片上的畫(huà)布,防止再?gòu)淖畹讓觼?lái)重繪

super.paint(gImage);

// 當(dāng)游戲沒(méi)有結(jié)束的時(shí)候繪出對(duì)戰(zhàn)雙方

if (!getGameOver()) {

// 畫(huà)出自己的坦克

paintMyTank(gImage);

// 畫(huà)出自己坦克發(fā)射的子彈

paintMyBullet(gImage);

// 畫(huà)出敵方坦克

paintEnemyTank(gImage);

// 畫(huà)出敵方坦克發(fā)射的子彈

paintEnemyBullet(gImage);

}

// 畫(huà)出草地

paintGrass(gImage);

// 畫(huà)出小河

paintRiver(gImage);

// 畫(huà)出石頭

paintStone(gImage);

// 畫(huà)出各種道具

paintTool(gImage);

// 將接下來(lái)的圖片加載到窗體畫(huà)布上去,才能考到每次畫(huà)的效果

g.drawImage(offScreenImage, 0, 0, null);

}

有一些相似的部分吧,其中最重要的是super.paint(gImage)這句,改變畫(huà)布在這里,消除閃爍也是在這里!!!

下面我們?cè)偬接懽詈笠粋€(gè)問(wèn)題,即如何理解swing中內(nèi)置雙緩沖,我們首先從繼承體系來(lái)看,JFrame->Frame->Window->Container->Component,在Frame中的update()方法是從Container中繼承而來(lái)的,而JFrame中卻重寫(xiě)了update()方法如下

Java代碼

/**

* Just calls paint(g). This method was overridden to

* prevent an unnecessary call to clear the background.

*

* @param g the Graphics context in which to paint

*/

public void update(Graphics g) {

paint(g);

}

與之前的同名方法相比,這里直接調(diào)用了paint()函數(shù)而沒(méi)有clearRect(),也就是清屏的方法,這里他試圖不通過(guò)清屏來(lái)阻止閃爍的發(fā)生。這也就是JFrame本身的一種處理方法。

以上是通過(guò)自己對(duì)雙緩沖的一些理解,其中還有很多問(wèn)題,希望牛人們能夠積極指出來(lái),并且一起討論這個(gè)問(wèn)題。

編輯推薦

java認(rèn)證考試專(zhuān)業(yè)語(yǔ)言串講struts2文件上傳的三種方式

java認(rèn)證考試專(zhuān)業(yè)語(yǔ)言串講cookie技術(shù)在J2ME平臺(tái)應(yīng)用

(責(zé)任編輯:xy)

2頁(yè),當(dāng)前第1頁(yè)  第一頁(yè)  前一頁(yè)  下一頁(yè)
最近更新 考試動(dòng)態(tài) 更多>