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 ...
随机推荐
- 27个Jupyter Notebook使用技巧及快捷键(翻译版)
Jupyter Notebook Jupyter Notebook 以前被称为IPython notebook.Jupyter Notebook是一款能集各种分析包括代码.图片.注释.公式及自己画的图 ...
- Android应用程序安装与Launcher启动机制
以下资料摘录整理自老罗的Android之旅博客,是对老罗的博客关于Android底层原理的一个抽象的知识概括总结(如有错误欢迎指出)(侵删):http://blog.csdn.net/luoshe ...
- linux-swappiness参数的作用及设置
linux 会使用硬盘的一部分做为SWAP分区,用来进行进程调度--进程是正在运行的程序--把当前不用的进程调成‘等待(standby)‘,甚至‘睡眠(sleep)’,一旦要用,再调成‘活动(acti ...
- Linux下python升级
Centos即使用Yum更新也是Python2.6.6所以需要升级到Python2.7.8 1.先下载源码包 1 wget https://www.python.org/ftp/python/2.7. ...
- Shell中的${},##和%%的使用
假设我们定义了一个变量为: file=/dir1/dir2/dir3/my.file.txt 可以用${ }分别替换得到不同的值: ${file#*/}:删掉第一个/ 及其左边的字符串:dir1/di ...
- win7下如何执行批处理文件
经过了一段时间的适应之后,某C也基本摸透了Win7的习性,然后突然发现无聊,就上了VeryCD去下载几个游戏玩.R大是电驴游戏版块的大神,某C怀着崇敬的心情,每每都追寻着他的足迹下载游戏.这次正好下载 ...
- CSS布局注意(纯属个人总结)
和CSS样式有关多用class,和后台数据有关多用id. 1.使用绝对定位时(偏移量如:top,left...),如果父类没有相对定位,使用绝对定位的元素是相对根元素(即<html>标签) ...
- MyEclipse导入Maven项目报错 Plugin execution not covered by lifecycle configuration:
web项目使用到mybatis,需要使用mybatis的自动生成代码插件,配置build部分如下: <build> <pluginManagement></pluginM ...
- PHPCMS 标签与解析小记_Jason
Content模块下的标签解析:phpcms\modules\content\classes\content_tag.class.php 推荐位:public function position
- centos 安装RAR
根据系统的情况下载rarlinuxx64版本wget http://www.rarlab.com/rar/rarlinux-x64-4.2.0.tar.gzx86版本wget http://www.r ...