java中paint repaint update 之间的关系
最近总结了一下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 之间的关系的更多相关文章
- Java Swing paint repaint update 方法的关系
Java Swing paint repaint update 方法的关系: 参考:http://blog.csdn.net/xiaoliangmeiny/article/details/691665 ...
- Java Servlet与Web容器之间的关系
自从计算机软件开发进入网络时代,就开始涉及到通讯问题.在客户/服务器(也叫C/S应用)时期,每个软件都有自己的客户端和服务器端软件.并且客户端和服务器端之间的通讯协议差别也很大.后来随着互联网的发展, ...
- Java中的集合类型的继承关系图
Java中的集合类型的继承关系图
- Java 中基本类型和字符串之间的转换
Java 中基本类型和字符串之间的转换 在程序开发中,我们经常需要在基本数据类型和字符串之间进行转换. 其中,基本类型转换为字符串有三种方法: 1. 使用包装类的 toString() 方法 2. 使 ...
- java中Integer 和String 之间的转换
java中Integer 和String 之间的转换 将数组转换成字符串:char[] array = {'a','b','c','d','e'};String str = new String(ar ...
- Java学习--Java 中基本类型和字符串之间的转换
Java 中基本类型和字符串之间的转换 在程序开发中,我们经常需要在基本数据类型和字符串之间进行转换. 其中,基本类型转换为字符串有三种方法: 1. 使用包装类的 toString() 方法 2. 使 ...
- Java开发学习--Java 中基本类型和包装类之间的转换
Java 中基本类型和包装类之间的转换 基本类型和包装类之间经常需要互相转换,以 Integer 为例(其他几个包装类的操作雷同哦): 在 JDK1.5 引入自动装箱和拆箱的机制后,包装类和基本类型之 ...
- Java中InputStream和String之间的转化
https://blog.csdn.net/lmy86263/article/details/60479350 在Java中InputStream和String之间的转化十分普遍,本文主要是总结一下转 ...
- Java中字节与对象之间的转换
近期公司里面用到了消息队列,而正如我们知道的是消息队列之间的是通过二进制形式的.以下就分享一下java中字节与对象之间的转换. 主要是用到了ByteArrayOutputStream和ObjectOu ...
随机推荐
- Java设计模式---组合模式
一.组合模式定义 组合模式定义: Compose objects into tree structures to represent part-whole hierarchies. Composite ...
- MM32/STM32中断和事件梳理
Interrupt_event梳理 预备资料 MM32/stm32中文参考手册 Cortex-M3权威指南(深入了解中断和异常) MM32F103产品手册(配置GPIO的复用功能可能用到) 提出问题 ...
- 【iOS开发】emoji表情的输入思路
1.自定义一个表情包类继承NSTextAttachment #import <UIKit/UIKit.h> /** 表情包的自定义类*/ @interface EmojiTextAttac ...
- asp.net设置元素css的属性
controls.style.Add("css名称","css值") 添加class规则 control.cssclass="str_cssname& ...
- js接收复选框的值
<td><input type="checkbox" class="title" name="title" value=& ...
- memcache缓存命中深入理解转载
http://www.iteye.com/topic/225692 memcache的方法有 add,set,replace,get,delete,getstats,increment,decreme ...
- 使用PHP CURL的POST数据
使用PHP CURL的POST数据 curl 是使用URL语法的传送文件工具,支持FTP.FTPS.HTTP HTPPS SCP SFTP TFTP TELNET DICT FILE和LDAP.cur ...
- 如何在CentOS 7上修改主机名
如何在CentOS 7上修改主机名 在CentOS中,有三种定义的主机名:静态的(static),瞬态的(transient),和灵活的(pretty).“静态”主机名也称为内核主机名,是系统在启动时 ...
- 使用三层交换机的ACL实现不同vlan间的隔离
使用三层交换机的ACL实现不同vlan间的隔离 建立三个vlan vlan10 vlan20 vlan30 www.2cto.com PC1 PC3属于vlan10 PC2 PC4属于v ...
- CListBox控件基本功能
创建CListBox对象 CListBox m_ListBox;关联控件 ,同时注意行数从 0 开始计算 1.向控件中添加内容 int AddString(LPCTSTR lpszItem ); ...