java中paint repaint update 之間的關係

來源:互聯網
上載者:User

標籤:except   thread   http   rgs   輕量   strong   gre   自動產生   blog   

最近總結了一下java中的paint,repaint和updata三者之間的關係,首先咱們都知道用paint方法來繪圖,用repaint重繪,用update來寫雙緩衝。但是他們之間是怎麼來調用的呢,咱們來分析一下(想直接看結果,請跳過分析過程):

-----------------------------------------------------------------------------------------------------------------------------

1.首先咱們畫在JFrame上面

import java.awt.Color;
import java.awt.Graphics;
import java.awt.Image;
import javax.swing.JFrame;

 

public class Jframe extends JFrame{
int x = 40,y=50;
Jframe(){
this.setSize(800,700);
this.setLocationRelativeTo(null);
this.getContentPane().setBackground(Color.GREEN);
this.setVisible(true);
this.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
}
public static void main(String[] args) {
new Jframe();
}
public void paint(Graphics g){
super.paint(g);//調用super.paint(g)去清除運動的痕迹
g.setColor(Color.RED);
g.fillOval(x, y, 20, 20);
y++;
repaint();//重畫
try {
Thread.sleep(10);//在此處睡眠一會,要不運動太快
} catch (InterruptedException e) {
// TODO 自動產生的 catch 塊
e.printStackTrace();
}
}
}

運行之後的介面

但是你仔細觀察一下,會發現有閃爍現象,怎麼辦呢?我第一時間想到的就是加個雙緩衝。那麼咱們來試一下!

import java.awt.Color;
import java.awt.Graphics;
import java.awt.Image;
import javax.swing.JFrame;


public class Jframe extends JFrame{
int x = 40,y=50;
Jframe(){
this.setSize(800,700);
this.setLocationRelativeTo(null);
this.getContentPane().setBackground(Color.GREEN);
this.setVisible(true);
this.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
}
public static void main(String[] args) {
new Jframe();
}
Image offScreenImage = null;
public void update(Graphics g) { //雙緩衝
if(offScreenImage == null) {
offScreenImage = this.createImage(800, 600);
}
Graphics gOffScreen = offScreenImage.getGraphics();
Color c = gOffScreen.getColor();
gOffScreen.setColor(Color.GREEN);
gOffScreen.fillRect(0, 0, 800, 600);
gOffScreen.setColor(c);
paint(gOffScreen);
g.drawImage(offScreenImage, 0, 0, null);
}
public void paint(Graphics g){
super.paint(g);
g.setColor(Color.RED);
g.fillOval(x, y, 20, 20);
y++;
repaint();
try {
Thread.sleep(10);
} catch (InterruptedException e) {
// TODO 自動產生的 catch 塊
e.printStackTrace();
}
}
}

運行:仔細看一下,發現還是閃爍,這是什麼鬼,難道雙緩衝加錯了嗎?咱們再用Frame試一下

import java.awt.Color;
import java.awt.Frame;
import java.awt.Graphics;
import java.awt.Image;
import javax.swing.JFrame;


public class Jframe extends Frame{
int x = 40,y=50;
Jframe(){
this.setSize(800,700);
this.setLocationRelativeTo(null);
this.setBackground(Color.GREEN);
this.setVisible(true);
//this.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
}
public static void main(String[] args) {
new Jframe();
}
Image offScreenImage = null;
public void update(Graphics g) { //雙緩衝
if(offScreenImage == null) {
offScreenImage = this.createImage(800, 600);
}
Graphics gOffScreen = offScreenImage.getGraphics();
Color c = gOffScreen.getColor();
gOffScreen.setColor(Color.GREEN);
gOffScreen.fillRect(0, 0, 800, 600);
gOffScreen.setColor(c);
paint(gOffScreen);
g.drawImage(offScreenImage, 0, 0, null);
}
public void paint(Graphics g){
super.paint(g);
g.setColor(Color.RED);
g.fillOval(x, y, 20, 20);
y++;
repaint();
try {
Thread.sleep(10);
} catch (InterruptedException e) {
// TODO 自動產生的 catch 塊
e.printStackTrace();
}
}
}

運行:發現不閃爍了,說明剛才加的雙緩衝是沒有問題的,然後我在JFrame的update方法裡和Frame的update方法裡都加個輸出語句

結果發現,JFrame運行後並沒有輸出0,而Frame在不斷輸出0;

看來JFrame壓根沒有調用update方法!!!

然後咱們用JPanel再試一下,把小球畫在JPanel上面

import java.awt.Color;
import java.awt.Graphics;
import javax.swing.JFrame;
import javax.swing.JPanel;


public class Jpanel extends JPanel{
int x=40,y=40;
Jpanel(){
JFrame frame = new JFrame();
frame.setSize( 800, 600);
frame.setLayout(null);
this.setBounds(0, 0, 800, 700);
frame.setLocationRelativeTo(null);
frame.setVisible(true);
this.setBackground(Color.GREEN);
frame.add(this);
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
}
public static void main(String[] args) {
new Jpanel();
}
public void paint(Graphics g){
super.paint(g);
g.setColor(Color.red);
g.fillOval(x, y, 20, 20);
y++;
repaint();
try {
Thread.sleep(10);
} catch (InterruptedException e) {
// TODO 自動產生的 catch 塊
e.printStackTrace();
}
}
}

運行後,竟然神奇的發現小球不閃爍了!!!並且沒有加雙緩衝!

為什麼呢?

-----------------------------------------------------------------------------------------------------------------------------

我查了API和其他資得出如下結果:

 

首先repaint()方法在重量級組件的時候會調用update方法,在輕量級組件的時候會調用paint方法,(重量級和輕量級的概念自查)

恰恰Frame是重量級組件,JFrame是輕量級組件,這樣就能解釋JFrame不運行update方法的原因了!

那JPanel為什麼就不會閃爍呢?

其實是因為JPanel中的paint方法和JFrame中的paint方法不太一樣

 

 JFrame的paint方法是繼承Container類中的,而JPanel的paint方法是繼承JComponent類中的,看看他倆之間方法的差異:

 

 這樣就明白了吧,JFrame的paint方法與JPanel中的paint方法並不一樣!JPanel的paint是按順序畫的,因為Frame已經過時了,以後咱們就可以把用paint方法把東西畫在JPanel(或者JLabel)上面,這樣不用加雙緩衝就不閃爍!

 

java中paint repaint update 之間的關係

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.