最近总结了一下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. Examples_06_02(android)DDMS的data文件中没有显示文件。

    以前这里不显示music.cfg.通过Reset adb,就显示了. 查看虚拟机运行时里面的文件,进入adb.exe目录: E:\TDDOWNLOAD\adt-bundle-windows-x86-2 ...

  2. ASP.Net MVC 之FileResult

    FileResult是一个基于文件的ActionResult,利用FileResult我们可以很容易地将从某个物理文件的内容响应给客户端.ASP.NET MVC定义了三个具体的FileResult,分 ...

  3. 监听UITabBarItem来拦截是否要跳转

    情景是这样的: 我需要在用户点击"我的"的时候, 判断是否已经登录, 如果没有, 就不进入该界面, 而是跳转到用户登录界面, 所以这里我需要进行UITabBarItem点击事件的拦 ...

  4. javascript 比较对象(hashcode)

    javascript 对象的比较是比较坑爹的一件事,因为javascript对象比较的是引用地址!当两个内容完全一样的对象比较: var object1={ name:"1234 " ...

  5. 武汉科技大学ACM:1002: 华科版C语言程序设计教程(第二版)例题6.6

    Problem Description 明天就要英语考试了,小明明正在挑灯夜 战背单词.小明明发现单词很难背,背一个忘一个.经过仔细研究,小明明发现单词难背的原因是因为某个字符的出现,破坏了整个单词的 ...

  6. C++面试题:++i和i++哪个效率高?

    1.当变量i的数据类型是c++语言默认提供的类型的话,他们的效率是一样的. 从其汇编执行的条数是一样的,所以其执行效率是一样的(有兴趣可以用gdb查看汇编代码)  2.我们自定的数据类型,++i效率高 ...

  7. jquery中的html()、text()、val()的区别

      1.html(),text(),val()三种方法都是用来读取选定元素的内容: html()是用来读取元素的HTML内容(包括其Html标签),text()用来读取元素的纯文本内容,包括其后代元素 ...

  8. 提取所有mtk机型的线刷包

    首先手机root且安装busybox和超级终端软件,这里不提供自己百度一大堆 一.制作scatter 示范 PRELOADER 0x0 { } MBR 0x600000 { } EBR1 0x6800 ...

  9. 关于nginx架构探究(4)

    事件管理机制 Nginx是以事件驱动的,也就是说Nginx内部流程的向前推进基本都是靠各种事件的触发来驱动,否则Nginx将一直阻塞在函数epoll_wait()或suspend函数,Nginx事件一 ...

  10. Windows10关闭快速启动