前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
圈层
工具
发布
首页
学习
活动
专区
圈层
工具
MCP广场
社区首页 >专栏 >双缓冲原理在Awt和Swing中实现消除闪烁方法总结

双缓冲原理在Awt和Swing中实现消除闪烁方法总结

作者头像
sr
发布于 2018-08-20 02:16:30
发布于 2018-08-20 02:16:30
2.5K00
代码可运行
举报
文章被收录于专栏:swag codeswag code
运行总次数:0
代码可运行

最近在做Java版贪吃蛇的入门项目,过程中遇到窗口闪烁的问题总结。

一、AWT组件开发

1、AWT

AWT是抽象窗口工具箱的缩写,它为编写图形用户界面提供了用户接口,通过这个接口就可以继承很多方法,省去了很多工作。AWT还能使应用程序更好地同用户进行交互。

AWT中的容器是一种特殊的组件,他可以包含其他组件,即可以把组件方法容器中。Container类是用来存放其他组件的Component类的子类,Frame类又是Component的子类。Frame类用于创建具有标题栏和边界的窗口。这里通过继承Frame类来建立自己的界面。

二、Swing界面编程

       随着Java的发展,AWT已经渐渐被淘汰,它已经不能适应发展的需要,不能满足开发功能强大的用户界面的需要。这时Swing出现了,它是建立在AWT之上的组件集,在不同的平台上都能保持组件的界面样式,因此得到了非常广泛的应用。

1、Swing组件库

在Swing组件中有许多种组件,它们被封装在JFC中,下面我们会对每一种组件进行详细介绍。Swing包很多,但平常用到的只有javax.swing.*和javax.swing.event.*这两个包,其他的很少用到。

       1)、JFC结构

JFC是Java的基础类,是Java Foundation Classes的缩写形式,封装了一组用于构建图形用户界面的组件和特性。JFC包含了图形用户界面构建中需要用到的顶级容器(Applet、Dialog、Frame)、普通容器(面板、滚动面板、拆分窗格组件、选项卡插U能给个和工具条等)、特殊容器(InternalFrame、Layeredpane、root pane)、基本组件(button , combo box , list , menu , slider , spinner和textfild)等。

       2)、与AWT的区别

最大的区别在于Swing组件的实现与本地实现无关。Swing组件比AWT组件具有更多的功能。例如在Swing中添加了按钮组件和标签组件,通过继承来更改Swing组件的行为和外观,访问技术等。


在游戏中相应的实现即主要窗体用Frame和JFrame来构建。

1.Frame:重量级组件

2.JFrame:轻量级组件

出现问题:

①.窗体调用repaint()方法时闪烁严重

②.窗体设置双缓冲重绘后,DrawImage()进行缩放图片时会失真,Graphics2D设置抗锯齿属性也会失效

Ps:问题到目前为止还没有很好的处理,可能相应的用JPanel进行绘制会解决问题(暂未尝试!)


在Awt中对于窗体画布的重绘其条用顺序是repaint() —>update()—>paint();

默认的upadate()中自带clearRect()方法,即清屏功能,程序运行时我们调用repaint()方法刷新则会造成屏幕刚清空,又继续重新调用paint()方法往窗体上绘制,则就造成闪烁问题!

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
    public void update(Graphics g) {     
        if (isShowing()) {     
            if (! (peer instanceof LightweightPeer)) {     
                g.clearRect(0, 0, width, height);     
            }     
            paint(g);     
        }     
}    

所以闪烁问题我们需要重写update()方法来实现双缓冲

代码:(以本人贪吃蛇项目为例)

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
public void update(Graphics g) {


		// 截取窗体所在位置的图片  
                   if (image == null)
			image = this.createImage(this.getWidth(), this.getHeight());
		// 获得截取图片的画布
		Graphics gre = image.getGraphics();
                // 获取画布的底色并且使用这种颜色填充画布(默认的颜色为黑色) 
		gre.setColor(gre.getColor());
                // 有清除上一步图像的功能,相当于gImage.clearRect(0, 0, WIDTH, HEIGHT) 
		gre.fillRect(0, 0, this.getWidth(), this.getHeight());
		// 将截下的图片上的画布传给重绘函数,重绘函数只需要在截图的画布上绘制即可,不必在从底层绘制     
		paint(gre);
	        //将接下来的图片加载到窗体画布上去,才能考到每次画的效果  
		g.drawImage(image, 0, 0, null);
		

	}

而Swing中内置双缓冲,我们首先从继承体系来看,JFrame->Frame->Window->Container->Component,在Frame中的update()方法是从Container中继承而来的,而JFrame中却重写了update()方法如下:

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
public void update(Graphics g) {     
    paint(g);     
}   

对比之后会发现直接调用了paint()函数而没有clearRect(),试图不通过清屏来阻止闪烁的发生。这也就是JFrame本身的一种处理方法。

但是我们用JFrame编程并且重新update()实现双缓冲后,窗体一样狂闪不停!原因为何?

下面引用一张图来说明:

repaint()方法在重量级组件的时候会调用update方法,在轻量级组件的时候会调用paint方法

即JFrame根本不会去调用update()方法!

解决方法:在Paint()中直接进行双缓冲操作

代码:

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
if (image == null)
			 
	// 截取窗体所在位置的图片  
                   if (image == null)
			image = this.createImage(this.getWidth(), this.getHeight());
		// 获得截取图片的画布
		Graphics gre = image.getGraphics();
                // 获取画布的底色并且使用这种颜色填充画布(默认的颜色为黑色) 
		gre.setColor(gre.getColor());
                // 有清除上一步图像的功能,相当于gImage.clearRect(0, 0, WIDTH, HEIGHT) 
		gre.fillRect(0, 0, this.getWidth(), this.getHeight());
		//调用父类的重绘方法,传入的是截取图片上的画布,防止再从最底层来重绘      
		 super.paint(imageG );
		 
		//蛇身
		if (snake != null) {
			snake.drawSnake(imageG );
			snake.scoreView(imageG );
		}
                //墙体
		if (wall != null)
			wall.drawWall(imageG );
                //食物(金币)
		if (food != null)
			food.drawFood(imageG );
		
		
		
               //将接下来的图片加载到窗体画布上去,才能考到每次画的效果  
		 g.drawImage(image, 0, 0, null);
	}

其中最重要的是 super.paint(imageG );

这里必须先调用父类Frame的方法刷新屏幕清理上一次repaint画出的图像。

然后可以创建一个线程让程序每隔一段时间后自动调用repaint()方法;

本文参与 腾讯云自媒体同步曝光计划,分享自作者个人站点/博客。
原始发表:2018-07-05,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 作者个人站点/博客 前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体同步曝光计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
暂无评论
推荐阅读
编辑精选文章
换一批
【Java AWT 图形界面编程】Canvas 组件中使用 Graphics 绘图 ④ ( AWT 绘图窗口闪烁问题 )
画图的过程是有时间消耗的 , 先清屏 , 再画图 , 清屏到画图完毕之前 界面是空白的 , 这是闪烁产生的原因 ;
韩曙亮
2023/03/30
9360
【Java AWT 图形界面编程】Canvas 组件中使用 Graphics 绘图 ④ ( AWT 绘图窗口闪烁问题 )
java的双缓冲技术
Java的强大特性让其在游戏编程和多媒体动画处理方面也毫不逊色。在Java游戏编程和动画编程中最常见的就是对于屏幕闪烁的处理。本文从J2SE的一个再现了屏幕闪烁的Java Appilication简单动画实例展开,对屏幕闪烁的原因进行了分析,找出了闪烁成因的关键:update(Graphics g)函数对于前端屏幕的清屏。由此引出消除闪烁的方法——双缓冲。双缓冲是计算机动画处理中的传统技术,在用其他语言编程时也可以实现。本文从实例出发,着重介绍了用双缓冲消除闪烁的原理以及双缓冲在Java中的两种常用实现
xiangzhihong
2018/02/01
2.4K0
老Java程序员花一天时间写了个飞机大战,很舒服![通俗易懂]
前两天我发现CSDN上有两篇飞机大战的文章异常火爆,各种指标都很高(阅读、点赞、评论、收藏等),但都是python写的,竟然不是我大Java,说实话作为老java选手,我心里是有那么一些失落的,难道我大java打飞机不行?就算大java打飞机不行,那我用单身30年的打飞机手速,我肯定行(反正我的代码我做主,就是玩!),于是我决定一展伸手,用java写了一个飞机大战。我就问你们我打飞机行不行,我媳妇都说行,你们呢?欢迎我亲爱的大Java选手们 点赞+评论+收藏!给我冲、冲、冲。。。
全栈程序员站长
2022/07/23
4930
老Java程序员花一天时间写了个飞机大战,很舒服![通俗易懂]
Java游戏编程不完全详解-2(1万6千字吐血推荐)
虽然这些代码是10几年前的写的,但是仍然能够在现代操作系统和Java最新开源版本中正常运行。
老九君
2021/08/26
1.7K0
Java---实力弹弹球,弹弹弹
直接上代码了。 微调按钮加画布画几个圆,再实现监听。。。 package cn.hncu.threadDemo.thread2; import java.awt.Canvas; import java.awt.Color; import java.awt.Graphics; import java.awt.event.ActionEvent; import java.awt.event.ActionListener; import java.awt.event.FocusEvent; import j
谙忆
2021/01/20
3750
Java---实力弹弹球,弹弹弹
java JAVA生成随机椭圆二一个以上widget的frame
 JAVA生成随机椭圆二一个以上widget的frame,内部类 package liezi; import javax.swing.*; import java.awt.*; import java.awt.event.*; public class TwoButtons { JFrame frame; JLabel label1; JLabel label2; public static void main(String[] args){ TwoButtons TwoButtons=new Two
葫芦
2019/05/09
4870
Java游戏编程不完全详解-3(爆肝一万七千字)
虽然这些代码是10几年前的写的,但是仍然能够在现代操作系统和Java最新开源版本中正常运行。
老九君
2021/08/26
2.2K0
基于Java swing开发的雷霆战机
游戏截图 飞机项目的所有类的截图 主窗体类 package com.tarena.shout; import java.awt.Graphics; import java.awt.Image; imp
时间静止不是简史
2020/07/24
1K0
基于Java swing开发的雷霆战机
【Java AWT 图形界面编程】使用小键盘按键缩放 Canvas 画布中绘制的背景图像 ( 键盘按键监听 + 绘制超大图像 + 鼠标拖动 + 鼠标滚轮缩放 + 以当前鼠标指针位置为缩放中心 示例 )
如果要为 Java AWT 界面编程的应用设置键盘按键监听 , 必须为 Frame / JFrame 窗口设置键盘监听 , 为组件设置是无效的 ;
韩曙亮
2023/05/09
2K0
【Java AWT 图形界面编程】使用小键盘按键缩放 Canvas 画布中绘制的背景图像 ( 键盘按键监听 + 绘制超大图像 + 鼠标拖动 + 鼠标滚轮缩放 + 以当前鼠标指针位置为缩放中心 示例 )
java贪吃蛇小游戏(详解)[通俗易懂]
首先给出代码下载地址(含素材):https://share.weiyun.com/8hkvy1Ja
全栈程序员站长
2022/09/07
1.8K0
java贪吃蛇小游戏(详解)[通俗易懂]
字符画视频 动态字符画java源代码
思路很简单,javacv抽帧,逐帧生成对应字符画后保存,生成完通过swing播放。
相思不扫积久弥厚
2023/10/26
2880
4、Swing在JPanel中添加背景图片方法
该文介绍了在Java Swing GUI应用程序中,如何利用Swing组件在JPanel中添加背景图片,以使页面更加美观。主要包括背景图片的加载方式、设置背景图片以及JPanel的绘制方式。同时,提供了一个调用示例程序。"
YGingko
2017/12/28
4.1K0
【Java AWT 图形界面编程】使用鼠标滚轮缩放 Canvas 画布中绘制的背景图像 ( 绘制超大图像 + 鼠标拖动 + 鼠标滚轮缩放 + 以当前鼠标指针位置为缩放中心 示例 )
鼠标指针指向界面中的 Canvas 画布某个位置 , Canvas 画布中绘制着一张超大图片 , 以该位置为中心 , 滑动鼠标滚轮时进行缩放 ;
韩曙亮
2023/05/07
3.1K0
【Java AWT 图形界面编程】使用鼠标滚轮缩放 Canvas 画布中绘制的背景图像 ( 绘制超大图像 + 鼠标拖动 + 鼠标滚轮缩放 + 以当前鼠标指针位置为缩放中心 示例 )
【Java AWT 图形界面编程】Canvas 中绘制超大图片 ( 使用鼠标拖动查看全图 | 设置 JFrame 窗口自动关闭 | 获取并绘制图片 | 鼠标拖动计算位移 | 画布偏移 )
创建 JFrame 窗口后 , 通过调用 JFrame#setDefaultCloseOperation 可以设置窗口自动关闭 ;
韩曙亮
2023/03/25
1.5K0
【Java AWT 图形界面编程】Canvas 中绘制超大图片 ( 使用鼠标拖动查看全图 | 设置 JFrame 窗口自动关闭 | 获取并绘制图片 | 鼠标拖动计算位移 | 画布偏移 )
【Java AWT 图形界面编程】使用鼠标滚轮放大缩小 Canvas 画布 ( 鼠标滚轮事件监听器 MouseWheelListener )
设置鼠标滚轮监听 , 在 Canvas 组件中 , 调用 addMouseWheelListener 函数 , 添加 鼠标滚轮监听器 MouseWheelListener ,
韩曙亮
2023/03/30
2.5K0
【Java AWT 图形界面编程】使用鼠标滚轮放大缩小 Canvas 画布 ( 鼠标滚轮事件监听器 MouseWheelListener )
YourBatman用趣味代码雨祝你:端午安康
端午节(也叫粽子节)与春节、清明节、中秋节并称为中国民间四大传统节日,一直延续至今。
YourBatman
2022/06/06
8810
YourBatman用趣味代码雨祝你:端午安康
浅谈双缓冲技术在游戏里面的应用【java】
窗体类有两种Frame、JFrame两种格式。 需要注意的是,他们都需要导入相关的包。如果是Frame格式,需要添加如下代码(导入相关的包):
时间静止不是简史
2020/07/24
6300
浅谈双缓冲技术在游戏里面的应用【java】
教你用JAVA写个小游戏[通俗易懂]
上周上课的时候老师让用Java写个小程序,我本想写一个经典的飞机大战游戏来着,可以后来突发奇想就写成了这个
全栈程序员站长
2022/09/14
2.4K0
教你用JAVA写个小游戏[通俗易懂]
【Java AWT 图形界面编程】Canvas 组件中使用 Graphics 绘图 ① ( AWT 绘图线程 | Component 绘图函数 )
在 AWT 绘图程序中 , 有一个专门的线程用于绘制界面的线程 , AWT 绘制线程 ;
韩曙亮
2023/03/30
8600
【Java AWT 图形界面编程】Canvas 组件中使用 Graphics 绘图 ① ( AWT 绘图线程 | Component 绘图函数 )
《Java 2 图形设计卷Ⅱ- SWING》第2章 Swing的基本知识
本章介绍开发Swing小应用程序和应用程序时要用到的Swing的基本知识。  虽然Swing是AWT的扩展,但是两者的基本概念还是有许多不同之处。首先,Swing小应用程序和应用程序的实现方式与AWT小应用程序和应用程序的实现方式有所不同。而且,如果开发人员想要开发同时使用AWT组件和Swing组件的小应用程序或应用程序,则还必须注意混合使用轻量组件和重量组件所带来的许多问题。  Swing是线程不安全的,这就是说,在大多数情况下,只能从事件派发线程中访问Swing组件。本章将介绍采用这种方法的原因及使用这种方法所带来的结果,另外,本章还介绍了Swing提供的一些机制,这些机制使其他线程能从事件派发线程中执行代码。
用户7886150
2020/12/10
2.7K0
推荐阅读
【Java AWT 图形界面编程】Canvas 组件中使用 Graphics 绘图 ④ ( AWT 绘图窗口闪烁问题 )
9360
java的双缓冲技术
2.4K0
老Java程序员花一天时间写了个飞机大战,很舒服![通俗易懂]
4930
Java游戏编程不完全详解-2(1万6千字吐血推荐)
1.7K0
Java---实力弹弹球,弹弹弹
3750
java JAVA生成随机椭圆二一个以上widget的frame
4870
Java游戏编程不完全详解-3(爆肝一万七千字)
2.2K0
基于Java swing开发的雷霆战机
1K0
【Java AWT 图形界面编程】使用小键盘按键缩放 Canvas 画布中绘制的背景图像 ( 键盘按键监听 + 绘制超大图像 + 鼠标拖动 + 鼠标滚轮缩放 + 以当前鼠标指针位置为缩放中心 示例 )
2K0
java贪吃蛇小游戏(详解)[通俗易懂]
1.8K0
字符画视频 动态字符画java源代码
2880
4、Swing在JPanel中添加背景图片方法
4.1K0
【Java AWT 图形界面编程】使用鼠标滚轮缩放 Canvas 画布中绘制的背景图像 ( 绘制超大图像 + 鼠标拖动 + 鼠标滚轮缩放 + 以当前鼠标指针位置为缩放中心 示例 )
3.1K0
【Java AWT 图形界面编程】Canvas 中绘制超大图片 ( 使用鼠标拖动查看全图 | 设置 JFrame 窗口自动关闭 | 获取并绘制图片 | 鼠标拖动计算位移 | 画布偏移 )
1.5K0
【Java AWT 图形界面编程】使用鼠标滚轮放大缩小 Canvas 画布 ( 鼠标滚轮事件监听器 MouseWheelListener )
2.5K0
YourBatman用趣味代码雨祝你:端午安康
8810
浅谈双缓冲技术在游戏里面的应用【java】
6300
教你用JAVA写个小游戏[通俗易懂]
2.4K0
【Java AWT 图形界面编程】Canvas 组件中使用 Graphics 绘图 ① ( AWT 绘图线程 | Component 绘图函数 )
8600
《Java 2 图形设计卷Ⅱ- SWING》第2章 Swing的基本知识
2.7K0
相关推荐
【Java AWT 图形界面编程】Canvas 组件中使用 Graphics 绘图 ④ ( AWT 绘图窗口闪烁问题 )
更多 >
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档
本文部分代码块支持一键运行,欢迎体验
本文部分代码块支持一键运行,欢迎体验