導航:首頁 > 編程語言 > java雙緩沖技術

java雙緩沖技術

發布時間:2022-08-16 19:01:33

java中repaint()方法到底應該怎麼用

java里repaint()是重繪component的方法;

repaint()方法用於重繪組件,該方法有下面四種形式:
1。public void repaint()
2。public void repaint(long tm)
//指定調用update方法之前等待的最大毫秒數tm
3。public void repaint(int x,int y,int width,int height)
//重繪組件的指定矩形區域
4。public void repaint(ling tm,int x,int y,int width,int height)
repaint方法不總是馬上執行,Java雖然會盡可能快的執行repaint,當Applet運行在較慢的平台上或計算機較忙時,應該考慮使用第2或4種repaint方法,指定在多長時間內必須執行repaint,否則就放棄。

repaint()這個方法是一個具有刷新頁面效果的方法,如果你要頁面進行重畫就可以調用.一般都是在AWT的圖形繪制當中調用的到.那麼該方法具體的工作原來是怎麼樣的呢?看下面的結構流程圖你就可以大概的了解了:
repaint()方法
|
|
V
AWT線程--->paint()方法-->圖形繪制
|
|
V
update()方法--->paint()方法--圖形繪制
從上面的流程圖可以看出,在繪制動畫圖形時候如果沒有調用repaint()方法的時候直接就是由線程調用paint()方法進行繪制,用repaint()進行刷新顯示.但是這樣的動畫會有個缺點(這樣的效果繪制出來會有閃爍).想想做出來的動畫總是隔一段時間就閃爍,有人會看嗎?那麼應該怎麼去除閃爍呢?我再下面的文章中會講到.這里主要的是說明repaint()這個方法.
在調用了repaint()的時候我門可以看出,它並不是直接就去繪制動畫(調用paint()),而是通過調用AWT線程在由線程去調用另一個方法update()再由update()調用畫筆paint()方法進行繪制.那麼這里為什麼要多做一步呢?這樣是不是為我門多增加代碼的書寫量呢?回答是當然不會,如果你不調用repaint()那麼就不能實現每一次的刷新顯示,就只會繪制重疊的圖形,不能一張一張的繪制出來.那麼其中調用的update()到底是起到什麼樣的作用呢?
update():清除當前顯示並調用paint()方法.當然這個update()方法是可以被修改的,我門在另一篇文章關於"雙緩沖技術"中會給大家講到這點.
綜合上面的介紹可以總結出repaint()的工作原理:repaint()通過調用線程再由線程去調用update()方法清除當前顯示並再調用paint()方法進行繪制下一個需要顯示的內容.這樣就起到了一種圖片的交替顯示從而在視角上形成了動畫.

⑵ 怎麼用雙緩沖解決java中關於Applet程序讓圖片動起來後如何解決屏閃

package yb_8_115;
import java.awt.Frame;
import java.awt.Graphics;
import java.awt.Image;
import java.awt.Toolkit;
import java.awt.event.KeyAdapter;
import java.awt.event.KeyEvent;
import java.awt.event.KeyListener;
import java.awt.event.WindowAdapter;
import java.awt.event.WindowEvent;

public class JSG extends Frame {
// 定義游戲關數0代表開始1代表第一關。。。
int state = 0;
// 定義全局變數用於拿到圖片系統路徑
// 得到默認工具包
Toolkit tk = Toolkit.getDefaultToolkit();
// 通過工具包拿到圖片
Image start = tk.getImage(
// 拿路徑
JSG.class.getResource("/image/start.png"));
Image bj2 = tk.getImage(JSG.class.getResource("/image/bj_2.png"));
Image dyg = tk.getImage(JSG.class.getResource("/image/lesson_1.png"));
Image heart = tk.getImage(JSG.class.getResource("/image/heart.png"));
Image songshu = tk.getImage(JSG.class.getResource("/image/songshu.png"));

public void init() {
new MusicFor("/music/tsg.mp3").musicplay();
new myThread().start();// 啟動線程

this.setSize(800, 600);
// 窗口大小
this.setVisible(true);
// 可見性
this.setLocationRelativeTo(null);
// 居中
this.setResizable(false);
// 禁用最大化
this.setTitle("松鼠快跑");
// 標題設置
this.addWindowListener(new WindowAdapter() {

@Override public void windowClosing(WindowEvent e) {
System.exit(0);
// 退出系統
}

});

this.addKeyListener(new KeyAdapter() {

@Override
public void keyPressed(KeyEvent e) {
// e.getKeyCode獲得鍵盤的按鍵 KeyEvent.VK_ENTER java定義的回車標識符
if (state == 0 && e.getKeyCode() == KeyEvent.VK_ENTER) {
state = 1;

}
}
});
}
@Override public void paint(Graphics g) {
if (state == 0) {
System.out.println("開始");// 列印開始界面
g.drawImage(start, 0, 0, getWidth(), getHeight(), this);

} else if (state == 1) {
System.out.println("第一關");// 列印第一關背景
g.drawImage(bj2, 0, 0, getWidth(), getHeight(), this);
g.drawImage(dyg, 328, 20, 145,51 , this);
g.drawImage(heart, 50, 520, 40,40 , this);
g.drawImage(heart, 90, 520, 40,40 , this);
g.drawImage(heart, 130, 520, 40,40 , this);
g.drawImage(songshu, 400, 450, 98,119 , this);
this.addKeyListener(new KeyAdapter() {
public void keyPressed(KeyEvent e) {
if(e.getKeyCode()==KeyEvent.VK_S);{
g.

}
}
});
}
}

/**
* @param args
*/
public static void main(String[] args) {
// 實例化一個對象mainframe對象
JSG jsg = new JSG();
jsg.init();

}
class myThread extends Thread {
public void run() {
while (true) {
repaint();// 重繪方法 ,這個方法會自動調用paint方法

}
}
}
// 雙緩沖技術
@Override
public void update(Graphics g) {
//創建和窗體一樣大小的圖片
Image temp=createImage(getWidth(),getHeight());
//拿到緩沖圖片的畫筆
Graphics gh=temp.getGraphics();
//將圖片加入窗體
print(gh);
//吧緩沖區的圖片畫到窗體上
g.drawImage(temp, 0, 0, this);
}
}

//其實很簡單就是把緩沖區的圖片畫到窗體的最上面

⑶ 關於java中利用BufferedImage的雙緩沖技術

雙緩沖就是先在內存中的另一張「畫布」上進行多次繪圖,然後把畫好的圖在一次性畫到屏幕上,也就是最後一步的g.drawimage。簡單的說,一個graphics對應著自己的繪圖區域圖形上下文

⑷ java中使用了雙緩沖技術後,黑色字體變成白色,怎麼樣才能改回黑色!

我也遇到了相同的問題,根據你給出的代碼,可以在第2、3行中間加上一句代碼:
g1.setColor(Color.BLACK);
也就是先把字體主動設置為黑色。
就應該OK了,我就是這么弄的。

⑸ java 雙緩沖,消除閃爍 的問題

[轉]雙緩沖在畫板程序中的應用

1.用雙緩沖解決畫板程序中的刷新問題

我們用Java編制畫板程序的時候,總是存在一個刷新的問題:當Canvas所在的窗口最小化或者被其他應用程序遮擋後,再次恢復,Canvas上的圖形

數據將被部分或者完全擦除掉.

通常解決這個問題的方法是在Canvas的paint()函數中重繪圖形,但是由於在繪圖的過程中產生了大量的數據,重新在Canvas上繪制這些數據將導

致大量的系統開銷,還會產生閃爍,故該方法可行但並不可取.

利用雙緩沖技術可以很好的解決這個問題,其主要原理是開辟兩個圖形緩沖區,一個是前台的顯示緩沖(也就是Canvas),一個是後台的圖形緩沖(

通常是Image).用戶在繪制圖形時,我們對這兩個緩沖區進行同步更新,相當於為前台的數據作了一個後台備份.當前台的圖形被遮蓋需要恢復的

時候,我們就可以用這個後台備份來恢復,具體方法是重寫paint()函數,將備份好的圖像一次性的畫到屏幕上去.

為什麼是paint()?這里需要先了解一下有關Java處理AWT繪圖的基礎知識:Java的顯示更新是由一個AWT線程來控制完成的.該線程主要負責兩種

與顯示更新相關的情況.第一種情況稱為曝光,表示部分顯示區域毀壞或需要清除.這種情況發生時,系統直接調用paint()方法;第二種情況是程

序決定重畫顯示區域,添加一些新的內容,此時需要程序調用成員的repaint()方法,repaint()方法調用成員的update(),update()再調用paint()

方法.顯然我們所說的就是第一種.只要Canvas組件所在的窗口最小化或者被其他應用程序遮擋住,系統就會調用paint()對畫布進行重繪.如果我

們在paint()方法中什麼都不做,就只能眼睜睜的看著辛辛苦苦畫的線條一旦被覆蓋就再也看不見了.

作為起點,請先看一個最簡單的畫板程序,請注意,以下程序使用的是j2sdk1.4.1版本,在Win98的IE下(不是Tencent Explorer)全部測試通過:

//:WBApplet.java

import java.applet.*;

public class WBApplet extends Applet{

final static int DEFAULT_BOARDWIDTH=700;
final static int DEFAULT_BOARDHEIGHT=400;

public void init(){
super.init();
setLayout(null);
whiteBoard = new WhiteBoard(this);
whiteBoard.reshape(0,0,DEFAULT_BOARDWIDTH,DEFAULT_BOARDHEIGHT);
add(whiteBoard);
}

WhiteBoard whiteBoard;

}

///:~

//:WhiteBoard.java

java.awt.*;
import java.awt.event.*;

public class WhiteBoard extends Canvas implements MouseMotionListener,MouseListener{

final static int DEFAULT_BOARDWIDTH=700;
final static int DEFAULT_BOARDHEIGHT=400;
int x0,y0,x1,y1;

WhiteBoard(WBApplet WBApplet1){
parent = WBApplet1;
addMouseMotionListener(this);
addMouseListener(this);
}

synchronized public void update_buffer(Graphics g,DrawItem data) {
g.drawLine(data.x0,data.y0,data.x1,data.y1);
}

public void mouseReleased(MouseEvent e){}
public void mouseEntered(MouseEvent e){}
public void mouseExited(MouseEvent e){}
public void mouseClicked(MouseEvent e){}
public void mouseMoved(MouseEvent e){}

public void mouseDragged(MouseEvent e){
x1=e.getX();
y1=e.getY();
Graphics g = getGraphics();
update_buffer(g,new DrawItem(x0,y0,x1,y1));
g.dispose();
x0=x1;
y0=y1;
}

public void mousePressed(MouseEvent e){
x0 =e.getX();
y0 =e.getY();
}

WBApplet parent;

}

class DrawItem{
DrawItem(int x0,int y0,int x1,int y1){
this.x0=x0;
this.y0=y0;
this.x1=x1;
this.y1=y1;
}
int x0;
int y0;
int x1;
int y1;
}

///:~

我們將白板需完成的所有邏輯操作封裝在了一個WhiteBoard類中,以方便主程序的Applet調用.同時,定義了一個繪圖的數據類DrawItem,用來封

裝圖形數據.繪圖的操作都寫在update_buffer中.顯然,這個程序無法實現刷新後的恢復,我們需要使用雙緩沖技術.

為了實現雙緩沖,首先定義圖形緩沖區如下

private Image off_screen_buf;
private Graphics off_screen_gc;

並在WhiteBoard類的構造函數中對其進行初始化

off_screen_buf =parent.createImage(DEFAULT_BOARDWIDTH,DEFAULT_BOARDHEIGHT);
off_screen_gc = off_screen_buf.getGraphics();

在處理用戶繪制圖形的函數中,我們使用update_buffer對顯示緩沖和圖形緩沖同時進行更新

Graphics g = getGraphics();
update_buffer(g,new DrawItem(x0,y0,x1,y1));//前台更新畫布
update_buffer(off_screen_gc,new DrawItem(x0,y0,x1,y1));//後台更新緩沖
g.dispose();

顯然,後台的更新操作是不可視的,所以是off-screen.

最後,重寫paint()方法,調用_from_offscreen_buf(g)將圖形緩沖區的圖像畫到屏幕上去.

public void paint(Graphics g){
_from_offscreen_buf(g);
}

void _from_offscreen_buf(Graphics g){
if(g != null)
g.drawImage(off_screen_buf, 0, 0, null);
}

就是這么簡單的幾行代碼,就可以讓我們完全的避免圖形不能恢復的問題.下面是WhiteBoard經改進後的完整代碼.

//:WhiteBoard.java

import java.awt.*;
import java.awt.event.*;

public class WhiteBoard extends Canvas implements MouseMotionListener,MouseListener{

final static int DEFAULT_BOARDWIDTH=700;
final static int DEFAULT_BOARDHEIGHT=400;
int x0,y0,x1,y1;

WhiteBoard(WBApplet WBApplet1){
parent = WBApplet1;
off_screen_buf =parent.createImage(DEFAULT_BOARDWIDTH,DEFAULT_BOARDHEIGHT);
off_screen_gc = off_screen_buf.getGraphics();
addMouseMotionListener(this);
addMouseListener(this);
}

synchronized public void update_buffer(Graphics g,DrawItem data) {
g.drawLine(data.x0,data.y0,data.x1,data.y1);
}

public void mouseMoved(MouseEvent e){}
public void mouseReleased(MouseEvent e){}
public void mouseEntered(MouseEvent e){}
public void mouseExited(MouseEvent e){}
public void mouseClicked(MouseEvent e){}

public void mouseDragged(MouseEvent e){
x1=e.getX();
y1=e.getY();
Graphics g = getGraphics();
update_buffer(g,new DrawItem(x0,y0,x1,y1));
update_buffer(off_screen_gc,new DrawItem(x0,y0,x1,y1));
g.dispose();
x0=x1;
y0=y1;
}

public void mousePressed(MouseEvent e){
x0 =e.getX();
y0 =e.getY();
}

public void paint(Graphics g){
_from_offscreen_buf(g);//把這句話屏蔽掉,就不能恢復用戶繪制的圖形了
}

void _from_offscreen_buf(Graphics g){
if(g != null)
g.drawImage(off_screen_buf, 0, 0, null);
}

private Image off_screen_buf;
private Graphics off_screen_gc;
WBApplet parent;

}

class DrawItem{
DrawItem(int x0,int y0,int x1,int y1){
this.x0=x0;
this.y0=y0;
this.x1=x1;
this.y1=y1;
}
int x0;
int y0;
int x1;
int y1;
}

///:~

運行一下,看是不是不一樣了.這一次你想讓你畫的東西消失都不可能了.為了將這個原理說清楚,以上的代碼我都沒有編寫的太復雜,下一次我們

會創建更加復雜,更加完善的畫板程序.

2.用雙緩沖實現各種圖形的繪制

在一個畫板程序中,用戶應該能夠用畫筆繪制各種圖形,除了上一節實現的自由畫法(Freehand)外,還應該可以畫直線,長方體,橢圓等等.以繪制

直線為例,我們都知道,只有在松開滑鼠鍵之後,直線才實實在在的顯示在了畫布上,而在拖拽滑鼠的過程中,直線在畫布中的顯示是隨著滑鼠的箭

頭方位的變化而不斷更新的.體現在程序中,這是一個不斷擦除,顯示,再擦除,再顯示的過程.擦除的是箭頭上一個點和起點間的直線,顯示的是箭

頭當前點和起點間的的直線.這個顯示的過程由update_buffer負責,而這個擦除的工作則和上一節出理刷新一樣,由_from_offscreen_buf來

完成.實際上,所謂擦除,也就是將畫板恢復到某一個原來的時刻.

這一個過程在下面一個修改後的拖拽操作的處理程序中完成:

public void mouseDragged(MouseEvent e){
Graphics g = getGraphics();
_from_offscreen_buf(g);
x1=e.getX();
y1=e.getY();
update_buffer(g,new DrawItem(x0,y0,x1,y1));
g.dispose();
}

注意,在該方法中,我們沒有對後台緩沖進行更新,這是因為滑鼠在拖拽的時候,雖然畫板上會顯示線條,但是這條直線並沒有真正的畫下去.那麼

在什麼時候應該對後台緩沖更新呢?顯然,是在滑鼠松開的時候.我們需要在mouseReleased方法中做這個工作.

public void mouseReleased(MouseEvent e){
Graphics g = getGraphics();
_from_offscreen_buf(g);
x1=e.getX();
y1=e.getY();
update_buffer(g,new DrawItem(x0,y0,x1,y1));
update_buffer(off_screen_gc,new DrawItem(x0,y0,x1,y1));
g.dispose();
}

可以看到,只有在滑鼠松開的時候,畫到畫板上的直線才最後確定了,我們才能夠將這一條線備份到緩沖區裡面去.

下面是升級後的完整的WhiteBoard.java程序.

//:WhiteBoard.java

import java.awt.*;
import java.awt.event.*;

public class WhiteBoard extends Canvas implements MouseMotionListener,MouseListener{

final static int DEFAULT_BOARDWIDTH=700;
final static int DEFAULT_BOARDHEIGHT=400;
int x0,y0,x1,y1;

WhiteBoard(WBApplet WBApplet1){
parent = WBApplet1;
off_screen_buf =parent.createImage(DEFAULT_BOARDWIDTH,DEFAULT_BOARDHEIGHT);
off_screen_gc = off_screen_buf.getGraphics();
addMouseMotionListener(this);
addMouseListener(this);
draw_mode=2;
}

synchronized public void update_buffer(Graphics g,DrawItem data) {
g.drawLine(data.x0,data.y0,data.x1,data.y1);
}

public void mouseMoved(MouseEvent e){}
public void mouseReleased(MouseEvent e){
switch(draw_mode){
case 2:
Graphics g = getGraphics();
_from_offscreen_buf(g);
x1=e.getX();
y1=e.getY();
update_buffer(g,new DrawItem(x0,y0,x1,y1));
update_buffer(off_screen_gc,new DrawItem(x0,y0,x1,y1));
g.dispose();
}

}
public void mouseEntered(MouseEvent e){}
public void mouseExited(MouseEvent e){}
public void mouseClicked(MouseEvent e){}

public void mouseDragged(MouseEvent e){
switch(draw_mode){
case 1:
x1=e.getX();
y1=e.getY();
Graphics g = getGraphics();
update_buffer(g,new DrawItem(x0,y0,x1,y1));
update_buffer(off_screen_gc,new DrawItem(x0,y0,x1,y1));
g.dispose();
x0=x1;
y0=y1;
break;
case 2:
Graphics g1 = getGraphics();
_from_offscreen_buf(g1);
x1=e.getX();
y1=e.getY();
update_buffer(g1,new DrawItem(x0,y0,x1,y1));
g1.dispose();
}
}

public void mousePressed(MouseEvent e){
x0 =e.getX();
y0 =e.getY();
}

public void paint(Graphics g){
_from_offscreen_buf(g);
}

void _from_offscreen_buf(Graphics g){
if(g != null)
g.drawImage(off_screen_buf, 0, 0, null);
}

private int draw_mode;
private Image off_screen_buf;
private Graphics off_screen_gc;
WBApplet parent;

}

class DrawItem{
DrawItem(int x0,int y0,int x1,int y1){
this.x0=x0;
this.y0=y0;
this.x1=x1;
this.y1=y1;
}
int x0;
int y0;
int x1;
int y1;
}

///:~

注意到,在這個程序裡面我們創建了一個新的私有變數draw_mode,用來存儲繪圖模式的代號.在這里,我們使用1來代表自由繪畫,2來代表畫直線.

在構造函數中為draw_mode定義初值可以使我們對不同種類圖形繪制的調試很方便,在上面的程序中,我們定義的是2,如果賦值為1,則又回到自由

繪畫的模式.事實上,我們應該在這樣的一個框架上把程序不斷的擴充和完善.

⑹ 什麼是雙緩沖雙緩沖技術的出現是基於怎樣的編程思想

雙緩沖是先將顯示圖形放在緩沖區,再一起顯示到屏幕上,以防止屏幕上的東西一個個出現或是發生閃爍。
雙緩沖是基於「空間換時間」和「功能分塊」的思想。
下面的文章詳細介紹了雙緩沖,雖然他講的是C++,但原理和java的是完全一樣的。

⑺ g如何用雙緩沖解決java swing圖像移動閃爍

雙緩存:緩存區是繪圖繪圖時使用的屏外內存區。使用雙緩存不是直接繪制屏幕,而是繪制到後緩存區,然後將整個緩存區復制到屏幕上,這樣就可以同時更新整個屏幕,游戲者只看到要看到的東西了。後緩存區可能只是普通java圖像。可以用Component類的createImage(int w,int h)方法生成後緩存區,如果是不使用活動繪制的小程序使用雙緩存,則可以覆蓋update()方法,改用雙緩存,並用雙緩存的圖形描述表調用paint()方法,實現代碼如下:

private Image doubleBuffer;
public void update(Graphics g){
Dimension size=getSize();
if(doubleBuffer.getWidth(this)!=size.width||doubleBuffer.getHeight(this)!=size.height)
{ doubleBuffer=createImage(size.width,size.height);
}
if(doubleBuffer!=null){
//繪制到雙緩存區
Graphics g2=doubleBuffer.getGraphics();
paint(g2);
g2.dispose();
//將雙緩存復制到屏幕
g.drawImage(doubleBuffer,0,0,null);
}
else
{//不要雙緩存,只繪制屏幕
paint(g);
}
}
public void paint(Graphics g){
//在此繪圖
}

⑻ java中的雙緩沖

paint (offScreen);
分好改成英文的
畫面重畫 offScreenImage 是保存在內存中原來的畫 畫中有個圓
圓的移動是通過 畫面重畫實現的 所以先把原來offScreenImage畫出來 再在這個之上畫一個圓
paint (offScreen); 這句畫就是把offScreenImage重新畫上去
注釋掉後 剛打開 你在一個窗口畫圓 然後保存在內存 再重新出現一個窗口 但不畫offScreen 窗口當然就是空白的了
能明白不

⑼ 關於java Applet 雙緩沖技術顯示圖片的疑問

1, Graphics2D 相比Graphics功能更強大,以後用這個功能強大。所以是向後兼容;
BufferImage 就是緩沖圖片,作用就是緩沖。先把圖形繪制到BufferImage,然後把整張圖片BufferImage直接顯示出來。好比在食堂吃飯的時候,BufferImage相當於一個大托盤,這個大托盤裡面裝了幾十碗(碟)小菜, 小二上菜的時候直接把這個大托盤一次端到客人桌子上就好了,只跑一次,效率高,速度快啊。BufferImage就起一個緩沖作用。

2、BufferGraphics 只是把圖形繪制到 BufferImage 這張圖片里,但這張圖片只是在內存里,並沒有顯示出來。
g.drawImage(BufferImage,0,0,this) 這一句才把整張圖片顯示出來(店小二才把掌托盤菜端上桌),不調用就不顯示圖片(沒有端出來,裝滿菜的托盤還在廚房呢,客人當然沒菜吃!)。

BufferImage 最開始確實為空,但是applet在顯示之前會先做初始化,也就是會執行init()方法。很顯然init()方法里調用了createImage(***)這個方法來初始化BufferImage。後面顯示出來的時候BufferImage當然就不為空了。

明白了吧!!!

⑽ java 雙緩沖問題

應該把雙緩沖放在update方法裡面的
調用情況是repaint() -> update(Graphics g) -> paint(Graphics g)
具體方法如下
public void update(Graphics g){
Graphics bufferg;
if(bufferPage==null){
buffer=createImage(350,350);
}
bufferg=bufferPage.getGraphics();
Color c = bufferg.getColor();
bufferg.setColor(getBackground());
bufferg.fillRect(0,0, this.getSize().width, this.getSize().height);
bufferg.drawImage(img, x,y,this);
paint(bufferg);
g.drawImage(bufferPage,0,0,this);
bufferg.setColor(c);

}
public void paint(Graphics g){
g.drawImage(img,0,0,this);
}

閱讀全文

與java雙緩沖技術相關的資料

熱點內容
解壓新奇特視頻 瀏覽:702
圖書信息管理系統java 瀏覽:548
各種直線命令詳解 瀏覽:859
程序員淚奔 瀏覽:143
素材怎麼上傳到伺服器 瀏覽:513
android百度離線地圖開發 瀏覽:187
web可視化編程軟體 瀏覽:288
java筆試編程題 瀏覽:742
win11什麼時候可以裝安卓 瀏覽:560
java不寫this 瀏覽:999
雲點播電影網php源碼 瀏覽:95
pythonclass使用方法 瀏覽:226
移動加密軟體去哪下載 瀏覽:294
php彈出alert 瀏覽:209
吉林文檔課件加密費用 瀏覽:136
感測器pdf下載 瀏覽:289
隨車拍app綁定什麼設備 瀏覽:898
方維團購系統源碼 瀏覽:993
linux反彈shell 瀏覽:159
列印機介面加密狗還能用嗎 瀏覽:301