最近总结了一下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 之间的关系的更多相关文章

  1. Java Swing paint repaint update 方法的关系

    Java Swing paint repaint update 方法的关系: 参考:http://blog.csdn.net/xiaoliangmeiny/article/details/691665 ...

  2. Java Servlet与Web容器之间的关系

    自从计算机软件开发进入网络时代,就开始涉及到通讯问题.在客户/服务器(也叫C/S应用)时期,每个软件都有自己的客户端和服务器端软件.并且客户端和服务器端之间的通讯协议差别也很大.后来随着互联网的发展, ...

  3. Java中的集合类型的继承关系图

    Java中的集合类型的继承关系图

  4. Java 中基本类型和字符串之间的转换

    Java 中基本类型和字符串之间的转换 在程序开发中,我们经常需要在基本数据类型和字符串之间进行转换. 其中,基本类型转换为字符串有三种方法: 1. 使用包装类的 toString() 方法 2. 使 ...

  5. java中Integer 和String 之间的转换

    java中Integer 和String 之间的转换 将数组转换成字符串:char[] array = {'a','b','c','d','e'};String str = new String(ar ...

  6. Java学习--Java 中基本类型和字符串之间的转换

    Java 中基本类型和字符串之间的转换 在程序开发中,我们经常需要在基本数据类型和字符串之间进行转换. 其中,基本类型转换为字符串有三种方法: 1. 使用包装类的 toString() 方法 2. 使 ...

  7. Java开发学习--Java 中基本类型和包装类之间的转换

    Java 中基本类型和包装类之间的转换 基本类型和包装类之间经常需要互相转换,以 Integer 为例(其他几个包装类的操作雷同哦): 在 JDK1.5 引入自动装箱和拆箱的机制后,包装类和基本类型之 ...

  8. Java中InputStream和String之间的转化

    https://blog.csdn.net/lmy86263/article/details/60479350 在Java中InputStream和String之间的转化十分普遍,本文主要是总结一下转 ...

  9. Java中字节与对象之间的转换

    近期公司里面用到了消息队列,而正如我们知道的是消息队列之间的是通过二进制形式的.以下就分享一下java中字节与对象之间的转换. 主要是用到了ByteArrayOutputStream和ObjectOu ...

随机推荐

  1. Java设计模式---组合模式

    一.组合模式定义 组合模式定义: Compose objects into tree structures to represent part-whole hierarchies. Composite ...

  2. MM32/STM32中断和事件梳理

    Interrupt_event梳理 预备资料 MM32/stm32中文参考手册 Cortex-M3权威指南(深入了解中断和异常) MM32F103产品手册(配置GPIO的复用功能可能用到) 提出问题 ...

  3. 【iOS开发】emoji表情的输入思路

    1.自定义一个表情包类继承NSTextAttachment #import <UIKit/UIKit.h> /** 表情包的自定义类*/ @interface EmojiTextAttac ...

  4. asp.net设置元素css的属性

    controls.style.Add("css名称","css值") 添加class规则 control.cssclass="str_cssname& ...

  5. js接收复选框的值

    <td><input type="checkbox" class="title" name="title" value=& ...

  6. memcache缓存命中深入理解转载

    http://www.iteye.com/topic/225692 memcache的方法有 add,set,replace,get,delete,getstats,increment,decreme ...

  7. 使用PHP CURL的POST数据

    使用PHP CURL的POST数据 curl 是使用URL语法的传送文件工具,支持FTP.FTPS.HTTP HTPPS SCP SFTP TFTP TELNET DICT FILE和LDAP.cur ...

  8. 如何在CentOS 7上修改主机名

    如何在CentOS 7上修改主机名 在CentOS中,有三种定义的主机名:静态的(static),瞬态的(transient),和灵活的(pretty).“静态”主机名也称为内核主机名,是系统在启动时 ...

  9. 使用三层交换机的ACL实现不同vlan间的隔离

    使用三层交换机的ACL实现不同vlan间的隔离   建立三个vlan vlan10 vlan20 vlan30    www.2cto.com   PC1 PC3属于vlan10 PC2 PC4属于v ...

  10. CListBox控件基本功能

    创建CListBox对象 CListBox m_ListBox;关联控件 ,同时注意行数从  0  开始计算 1.向控件中添加内容 int AddString(LPCTSTR lpszItem ); ...