这几天用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); // 然后一次性显示出来 }
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17

于是我又继续查文章,我发现没什么人用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);
}
}
}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32
  • 33
  • 34
  • 35
  • 36

接下来我继续说说我是怎么解决这个问题的,在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() {
@Override
public void run() {
skyMove();
groundMove();
dinoMove();
repaint();
}
};
timer.schedule(task, 10, 20);
}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32
  • 33
  • 34
  • 35
  • 36
  • 37
  • 38

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

public void update(Graphics g) {
paint(g);
}
  • 1
  • 2
  • 3

就会更闪烁然后报错
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)

原文章:https://blog.csdn.net/qq_38677092/article/details/112092928

Java swing JFrame用repaint出现闪烁的问题解决的更多相关文章

  1. Java Swing JFrame实现全屏--无标题,无边框

    实现方式一: import java.awt.Dimension; import java.awt.Toolkit; import javax.swing.JFrame; public class T ...

  2. Java Swing 托盘闪烁Demo实例

    桌面程序当中,托盘显示是一个常用的功能. C#的WinForm程序要实现托盘是挺轻松的,而Java Swing要实现这个功能虽然也不难, 但是由于Java Swing开发者或许没有C#多,所以看到很多 ...

  3. Java Swing paint repaint update 方法的关系

    Java Swing paint repaint update 方法的关系: 参考:http://blog.csdn.net/xiaoliangmeiny/article/details/691665 ...

  4. Java Swing类 例子代码:将子类继承JFrame 并且接口按键监听ActionLisetener (将内容直接添加到JFrame不创建Contaniner)

    package rom; import java.awt.BorderLayout; import java.awt.Color; import java.awt.Container; import ...

  5. Java Swing学习笔记——创建JFrame

    创建显示一个空JFrame import javax.swing.JFrame; public class JFrameDemo extends JFrame{ public JFrameDemo() ...

  6. java swing 双人五子棋源代码

    import java.awt.Color; import java.awt.Font; import java.awt.Graphics; import java.awt.Toolkit; impo ...

  7. java swing模仿随机频谱

    import java.awt.BorderLayout; import java.awt.Color; import java.awt.Dimension; import java.awt.Grap ...

  8. Java Swing jpanel paint方法执行两次的问题

    Java Swing jpanel paint方法执行两次的问题: 在其他环境下执行了两次,自己测试怎么都是执行了一次,记录一下这个问题:需要后继工作: 可能是进行各种参数设置的时候导致了paint方 ...

  9. java Swing 图片缓冲机制

    java Swing 图片缓冲机制: 参考:http://jorneyr.iteye.com/blog/868858#comments package util; import java.awt.ge ...

随机推荐

  1. web php wrong nginx config

    web php wrong nginx config 目录 web php wrong nginx config 题目描述 解题过程 信息收集 robots.txt hint.php Hack.php ...

  2. Day007 数组的声明与创建

    数组 数组的定义 数组是相同类型数据的有序集合. 数组描述的是相同类型的若干个数据,按照一定的先后次序排列组合而成. 其中,每一个数据称作一个数组元素,每个数组元素可以通过一个下标来访问它们. 数组声 ...

  3. No input file specified.问题的解决

    问题描述:apache配置网站出现问题"No input file specified." 解决1: 打开.htaccess 在RewriteRule 后面的index.php教程 ...

  4. Java筑基 - JNI到底是个啥

    在前面介绍Unsafe的文章中,简单的提到了java中的本地方法(Native Method),它可以通过JNI(Java Native Interface)调用其他语言中的函数来实现一些相对底层的功 ...

  5. 如何利用CRM系统打通营销全渠道?

    企业经常通过不同渠道组织各种形式的营销推广,可惜,这些营销推广的效果往往差强人意. 相关研究表明,很多营销推广不理想的主要原因是不同营销渠道之间没有打通数据,不清楚每个营销渠道或营销策划的投入产出.推 ...

  6. Zoho:SaaS行业的“紫色奶牛”

    以下文章来源于:中国软件网,作者王锦宝 蓝天白云的映衬下,一群黑白相间的奶牛在绿草场自由玩耍,这种田园牧歌场景看久了,总会引起审美疲劳.假如突然出现一头紫色奶牛,你肯定会眼前一亮,把所有注意力集中到紫 ...

  7. [DB] CDH集群规划

    配置 三台机器:node01.node02.node03 node01:6G+60G node02:2G+40G node03:2G+40G 组件 Cloudera Managerment Servi ...

  8. QT windows 应用程序 exe ,设置详细信息并解决中文乱码问题

    原博主:https://blog.csdn.net/xiezhongyuan07/article/details/87691490 1.新创建一个.rc文件,随意命名,例如叫app.rc 并编辑 1 ...

  9. Linux ll查看文件属性详解-软硬链接详解

    Linux文件属性及类型 [root@localhost ~]# ll anaconda-ks.cfg 文件类型 权限 硬连接数 文件的大小 文件的创建,修改时间 - rw-------. 1 roo ...

  10. python基础之psutil模块和发邮件(smtplib和yagmail)

    除了内建的模块外,Python还有大量的第三方模块. 基本上,所有的第三方模块都会在PyPI - the Python Package Index上注册,只要找到对应的模块名字,即可用pip安装. 此 ...