Java swing JFrame用repaint出现闪烁的问题解决

2023-11-21 05:10

本文主要是介绍Java swing JFrame用repaint出现闪烁的问题解决,希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!

这几天用swing写登录页面背景动图的时候发现一直会有闪烁(我的类是继承JFrame),就来搜原因后发现好像是因为repaint会调用update()方法中的清屏操作导致闪烁。

我当时看的是这个文章

穆梓先生-java 双缓冲技术解决屏幕闪烁问题

于是按照他的方法重写了update方法,却发现问题没解决

public void paint(Graphics g) {g.drawImage(skyImag.getImage(), skyX, skyY, null);g.drawImage(groundImag, groundX, groundY, null);g.drawImage(dinosaurImag.getImage(), dinoX, dinoY, null);}
public void update(Graphics g) {System.out.println("==1==");//这个是我拿来测试会不会调用的输出信息if (groundImag == null) {System.out.println("==2==");//这句话从没输出过,说明了JFrame不会执行清屏操作,即groundImag != null,而Frame跟JPanel好像会执行清屏操作groundImag = this.createImage(500, 500); // 新建一个图像缓存空间,这里图像大小为800*600,为了使这句话没问题,我把我的对象从ImagIcon对象改成Imag对象}Graphics gImage = groundImag.getGraphics(); // 把它的画笔拿过来,给gImage保存着paint(gImage); // 将要画的东西画到图像缓存空间去g.drawImage(groundImag, 0, 0, null); // 然后一次性显示出来}

于是我又继续查文章,我发现没什么人用JFrame出现闪烁现象(我上次写飞机大战都没闪烁的说!),所以我查文章的时候放大范围,只要是Java swing编程出现闪烁的文章我都看一遍过去,终于让我看到这个大佬的文章

ydcun-双缓冲原理在awt和swing中实现消除闪烁的方法

就是他做的测试,让我知道原来在JFrame中repaint()的时候update()方法就没被调用到,JFrame消除闪烁是在update()中“直接调用了paint()函数而没有clearRect(),也就是清屏的方法,这里他试图不通过清屏来阻止闪烁的发生。”

所以到底是哪一步出问题了。。paint()方法已经被我重写了是不会有清屏操作的,问题感觉只能出在repaint()上,看了repaint()的代码好像也没发现类似清屏的代码,我能力有限,还在学习中,有大佬知道咋回事就求赐教一下QWQ,为了方便大家找repaint()有没有问题我就把代码贴上来吧

public void repaint(long tm, int x, int y, int width, int height) {if (this.peer instanceof LightweightPeer) {// Needs to be translated to parent coordinates since// a parent native container provides the actual repaint// services.  Additionally, the request is restricted to// the bounds of the component.if (parent != null) {if (x < 0) {width += x;x = 0;}if (y < 0) {height += y;y = 0;}int pwidth = (width > this.width) ? this.width : width;int pheight = (height > this.height) ? this.height : height;if (pwidth <= 0 || pheight <= 0) {return;}int px = this.x + x;int py = this.y + y;parent.repaint(tm, px, py, pwidth, pheight);}} else {if (isVisible() && (this.peer != null) &&(width > 0) && (height > 0)) {PaintEvent e = new PaintEvent(this, PaintEvent.UPDATE,new Rectangle(x, y, width, height));SunToolkit.postEvent(SunToolkit.targetToAppContext(this), e);}}}

接下来我继续说说我是怎么解决这个问题的,在ydcun大佬那边是有讲他的解决方案的,我还没试过(因为凌晨3点了都!我写完立马睡觉!),我当时(凌晨2点)就想着既然不会去调用update(),那我手动调用不就好了?

于是

public void paint(Graphics g) {g.drawImage(skyImag.getImage(), skyX, skyY, null);g.drawImage(groundImag, groundX, groundY, null);g.drawImage(dinosaurImag.getImage(), dinoX, dinoY, null);update(getGraphics());//跟JPanel不同,JFrame的repaint方法不会自动调用update方法。所以我这边直接让它调用了。//而且参数不能用g得用getGraphics()}public void update(Graphics g) {
//		System.out.println("==1==");
//		if (groundImag == null) {
//			//System.out.println("==2==");//			groundImag = this.createImage(500, 500); }// 新建一个图像缓存空间,这里图像大小为800*600//Image对象在这边也会出问题//报getGraphics() not valid for images created with createImage(producer)//得改成BufferedImage,但是我懒得改,所以我直接全注释了//			Graphics gImage = groundImag.getGraphics(); // 把它的画笔拿过来,给gImage保存着
//			paint(gImage); // 将要画的东西画到图像缓存空间去
//			g.drawImage(groundImag, 0, 0, null); // 然后一次性显示出来}//为了实现动画效果我写了个计时器来repaint()public void startTimeTask() {Timer timer = new Timer();TimerTask task = new TimerTask() {@Overridepublic void run() {skyMove();groundMove();dinoMove();repaint();}};timer.schedule(task, 10, 20);}

对,我调用了一个什么东西都没有的update()方法,就解决了闪烁的问题。。。但是如果我调用系统的update()

public void update(Graphics g) {paint(g);}

就会更闪烁然后报错
Java HotSpot(TM) 64-Bit Server VM warning: Potentially dangerous stack overflow in ReservedStackAccess annotated method sun.java2d.d3d.D3DBlitLoops.IsoBlit(Lsun/java2d/SurfaceData;Lsun/java2d/SurfaceData;Ljava/awt/image/BufferedImage;Ljava/awt/image/BufferedImageOp;Ljava/awt/Composite;Lsun/java2d/pipe/Region;Ljava/awt/geom/AffineTransform;IIIIIDDDDZ)V [1] Exception in thread "AWT-EventQueue-0" java.lang.StackOverflowError at java.base/java.util.concurrent.locks.AbstractQueuedSynchronizer.acquire(AbstractQueuedSynchronizer.java:714) at java.base/java.util.concurrent.locks.AbstractQueuedSynchronizer.acquire(AbstractQueuedSynchronizer.java:937) at java.base/java.util.concurrent.locks.ReentrantLock$Sync.lock(ReentrantLock.java:153) at java.base/java.util.concurrent.locks.ReentrantLock.lock(ReentrantLock.java:322) at java.desktop/sun.awt.SunToolkit.awtLock(SunToolkit.java:195) at java.desktop/sun.java2d.pipe.RenderQueue.lock(RenderQueue.java:112) at java.desktop/sun.java2d.d3d.D3DBlitLoops.IsoBlit(D3DBlitLoops.java:313) at java.desktop/sun.java2d.d3d.D3DTextureToSurfaceScale.Scale(D3DBlitLoops.java:768) at java.desktop/sun.java2d.pipe.DrawImage.scaleSurfaceData(DrawImage.java:1001) at java.desktop/sun.java2d.pipe.DrawImage.renderImageScale(DrawImage.java:647) at java.desktop/sun.java2d.pipe.DrawImage.tryCopyOrScale(DrawImage.java:319) at java.desktop/sun.java2d.pipe.DrawImage.transformImage(DrawImage.java:258) at java.desktop/sun.java2d.pipe.DrawImage.copyImage(DrawImage.java:76) at java.desktop/sun.java2d.pipe.DrawImage.copyImage(DrawImage.java:1027) at java.desktop/sun.java2d.SunGraphics2D.drawImage(SunGraphics2D.java:3425) at java.desktop/sun.awt.image.ImageRepresentation.drawToBufImage(ImageRepresentation.java:813) at java.desktop/sun.java2d.pipe.DrawImage.copyImage(DrawImage.java:1034) at java.desktop/sun.java2d.pipe.ValidatePipe.copyImage(ValidatePipe.java:186) at java.desktop/sun.java2d.SunGraphics2D.drawImage(SunGraphics2D.java:3425) at java.desktop/sun.java2d.SunGraphics2D.drawImage(SunGraphics2D.java:3401) at cn.zhetech.BackImag.paint(UserLogin2.java:276) at java.desktop/javax.swing.JFrame.update(JFrame.java:469) at cn.zhetech.BackImag.paint(UserLogin2.java:283) at java.desktop/javax.swing.JFrame.update(JFrame.java:469) at cn.zhetech.BackImag.paint(UserLogin2.java:283) at java.desktop/javax.swing.JFrame.update(JFrame.java:469) at cn.zhetech.BackImag.paint(UserLogin2.java:283) at java.desktop/javax.swing.JFrame.update(JFrame.java:469) at cn.zhetech.BackImag.paint(UserLogin2.java:283) at java.desktop/javax.swing.JFrame.update(JFrame.java:469) at cn.zhetech.BackImag.paint(UserLogin2.java:283) at java.desktop/javax.swing.JFrame.update(JFrame.java:469) at cn.zhetech.BackImag.paint(UserLogin2.java:283) at java.desktop/javax.swing.JFrame.update(JFrame.java:469) at cn.zhetech.BackImag.paint(UserLogin2.java:283) at java.desktop/javax.swing.JFrame.update(JFrame.java:469) at cn.zhetech.BackImag.paint(UserLogin2.java:283) at java.desktop/javax.swing.JFrame.update(JFrame.java:469) at cn.zhetech.BackImag.paint(UserLogin2.java:283) at java.desktop/javax.swing.JFrame.update(JFrame.java:469) at cn.zhetech.BackImag.paint(UserLogin2.java:283) at java.desktop/javax.swing.JFrame.update(JFrame.java:469) at cn.zhetech.BackImag.paint(UserLogin2.java:283) at java.desktop/javax.swing.JFrame.update(JFrame.java:469) at cn.zhetech.BackImag.paint(UserLogin2.java:283) at java.desktop/javax.swing.JFrame.update(JFrame.java:469) at cn.zhetech.BackImag.paint(UserLogin2.java:283) at java.desktop/javax.swing.JFrame.update(JFrame.java:469) at cn.zhetech.BackImag.paint(UserLogin2.java:283) at java.desktop/javax.swing.JFrame.update(JFrame.java:469) at cn.zhetech.BackImag.paint(UserLogin2.java:283) at java.desktop/javax.swing.JFrame.update(JFrame.java:469) at cn.zhetech.BackImag.paint(UserLogin2.java:283) at java.desktop/javax.swing.JFrame.update(JFrame.java:469) at cn.zhetech.BackImag.paint(UserLogin2.java:283) at java.desktop/javax.swing.JFrame.update(JFrame.java:469) at cn.zhetech.BackImag.paint(UserLogin2.java:283) at java.desktop/javax.swing.JFrame.update(JFrame.java:469) at cn.zhetech.BackImag.paint(UserLogin2.java:283) at java.desktop/javax.swing.JFrame.update(JFrame.java:469) at cn.zhetech.BackImag.paint(UserLogin2.java:283) at java.desktop/javax.swing.JFrame.update(JFrame.java:469) at cn.zhetech.BackImag.paint(UserLogin2.java:283) at java.desktop/javax.swing.JFrame.update(JFrame.java:469) at cn.zhetech.BackImag.paint(UserLogin2.java:283) at java.desktop/javax.swing.JFrame.update(JFrame.java:469) at cn.zhetech.BackImag.paint(UserLogin2.java:283)

窗口也关不掉,只能从控制台强制停止运行。。。

等日后有大佬评论教我了或者我自己学习到了再补充一下这个原因,碎觉,溜了||ヽ( ̄▽ ̄)ノミ|Ю,狗命要紧

如果文章有帮到你或者给你提供了思路,那就送我个赞呗(◦˙▽˙◦),不然我就默认每个浏览的都是想点然后忘了(自欺欺人,bushi)
懂得都懂

这篇关于Java swing JFrame用repaint出现闪烁的问题解决的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!



http://www.chinasem.cn/article/400022

相关文章

Java方法重载与重写之同名方法的双面魔法(最新整理)

《Java方法重载与重写之同名方法的双面魔法(最新整理)》文章介绍了Java中的方法重载Overloading和方法重写Overriding的区别联系,方法重载是指在同一个类中,允许存在多个方法名相同... 目录Java方法重载与重写:同名方法的双面魔法方法重载(Overloading):同门师兄弟的不同绝

Spring配置扩展之JavaConfig的使用小结

《Spring配置扩展之JavaConfig的使用小结》JavaConfig是Spring框架中基于纯Java代码的配置方式,用于替代传统的XML配置,通过注解(如@Bean)定义Spring容器的组... 目录JavaConfig 的概念什么是JavaConfig?为什么使用 JavaConfig?Jav

Java数组动态扩容的实现示例

《Java数组动态扩容的实现示例》本文主要介绍了Java数组动态扩容的实现示例,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友们下面随着小编来一起学习学习吧... 目录1 问题2 方法3 结语1 问题实现动态的给数组添加元素效果,实现对数组扩容,原始数组使用静态分配

Java中ArrayList与顺序表示例详解

《Java中ArrayList与顺序表示例详解》顺序表是在计算机内存中以数组的形式保存的线性表,是指用一组地址连续的存储单元依次存储数据元素的线性结构,:本文主要介绍Java中ArrayList与... 目录前言一、Java集合框架核心接口与分类ArrayList二、顺序表数据结构中的顺序表三、常用代码手动

JAVA项目swing转javafx语法规则以及示例代码

《JAVA项目swing转javafx语法规则以及示例代码》:本文主要介绍JAVA项目swing转javafx语法规则以及示例代码的相关资料,文中详细讲解了主类继承、窗口创建、布局管理、控件替换、... 目录最常用的“一行换一行”速查表(直接全局替换)实际转换示例(JFramejs → JavaFX)迁移建

Spring Boot Interceptor的原理、配置、顺序控制及与Filter的关键区别对比分析

《SpringBootInterceptor的原理、配置、顺序控制及与Filter的关键区别对比分析》本文主要介绍了SpringBoot中的拦截器(Interceptor)及其与过滤器(Filt... 目录前言一、核心功能二、拦截器的实现2.1 定义自定义拦截器2.2 注册拦截器三、多拦截器的执行顺序四、过

JAVA线程的周期及调度机制详解

《JAVA线程的周期及调度机制详解》Java线程的生命周期包括NEW、RUNNABLE、BLOCKED、WAITING、TIMED_WAITING和TERMINATED,线程调度依赖操作系统,采用抢占... 目录Java线程的生命周期线程状态转换示例代码JAVA线程调度机制优先级设置示例注意事项JAVA线程

JavaWeb项目创建、部署、连接数据库保姆级教程(tomcat)

《JavaWeb项目创建、部署、连接数据库保姆级教程(tomcat)》:本文主要介绍如何在IntelliJIDEA2020.1中创建和部署一个JavaWeb项目,包括创建项目、配置Tomcat服务... 目录简介:一、创建项目二、tomcat部署1、将tomcat解压在一个自己找得到路径2、在idea中添加

Springboot3统一返回类设计全过程(从问题到实现)

《Springboot3统一返回类设计全过程(从问题到实现)》文章介绍了如何在SpringBoot3中设计一个统一返回类,以实现前后端接口返回格式的一致性,该类包含状态码、描述信息、业务数据和时间戳,... 目录Spring Boot 3 统一返回类设计:从问题到实现一、核心需求:统一返回类要解决什么问题?

Java使用Spire.Doc for Java实现Word自动化插入图片

《Java使用Spire.DocforJava实现Word自动化插入图片》在日常工作中,Word文档是不可或缺的工具,而图片作为信息传达的重要载体,其在文档中的插入与布局显得尤为关键,下面我们就来... 目录1. Spire.Doc for Java库介绍与安装2. 使用特定的环绕方式插入图片3. 在指定位