標籤: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 之間的關係