如何解决由于加载图像而导致屏幕闪烁的问题?

Posted

技术标签:

【中文标题】如何解决由于加载图像而导致屏幕闪烁的问题?【英文标题】:How to fix the blinking of the screen due to loading of the Image? 【发布时间】:2019-12-23 21:30:20 【问题描述】:

我正在尝试在其上加载和图像绘制,然后将其显示在框架上。 我也可以在框架上加载图像并在框架上绘图,但这会在我的屏幕上产生更多的闪烁。

在下面的代码中,当用户按下任意键时屏幕会闪烁,因为图像被再次加载并且球的新位置被绘制。

if up_key y--
if down_key y++
if left_key x--
if right_key x++

根据按下的键重新显示图像并更新球的位置。

如何减少闪烁效果以使其平滑?

必须替换我在文件构造函数中给出的路径。

import java.awt.*;
import java.io.*;
import java.awt.image.*;
import javax.imageio.ImageIO;
import java.awt.event.*;

class MyFrame extends Frame implements KeyListener 

    BufferedImage img;
    int x=100,y=100;
    public MyFrame()
    
        super("Box");
        this.setSize(1382,784);
        this.setVisible(true);
        this.addKeyListener(this);
        this.requestFocus();
        this.setResizable(false);
    
    public void make()
    
        try
        img=ImageIO.read(new File("c:/users/udesh_2/desktop/Boundary.jpg"));
        Graphics gfx=img.getGraphics();
        gfx.setColor(Color.black);
        gfx.fillOval(x,y,40,40);
        
        catch(IOException io)
    
    @Override
    public void paint(Graphics g)
    
        make();
        g.drawImage(img,0,0,getWidth(),getHeight(),null);
    
    public static void main(String $[])
    
        MyFrame f=new MyFrame();
        f.make();
        f.repaint();
    

    public void keyPressed(KeyEvent key)
    
        boolean found=false;

        if(key.getKeyCode()==KeyEvent.VK_UP)
        
            found=true;
            y--;
        
        if(key.getKeyCode()==KeyEvent.VK_DOWN)
        
            found=true;
            y++;
        
        if(key.getKeyCode()==KeyEvent.VK_LEFT)
        
            found=true;
            x--;
        
        if(key.getKeyCode()==KeyEvent.VK_RIGHT)
        
            found=true;
            x++;
        
                    if(found)
        repaint();
    
    public void keyTyped(KeyEvent key)
    public void keyReleased(KeyEvent key)

【问题讨论】:

为避免预加载 img 时闪烁,请将 make() 调用移至构造函数,并避免在 paint 方法中调用 make()。在paint里面你应该只有绘图的东西,而不是加载资源和其他繁重的工作。 @mmmatey 那我应该如何有效地加载加载图像并在框架上显示图像。 我为您准备了如何避免它的示例,现在无法运行,但它应该是这样的:pastebin.com/XpzDx33e 在这里查看代码。 “我想在图像上而不是在框架上绘画” 有趣的是(或者我猜不是),我实际上更喜欢在图像上完成所有绘画,但是它'd 只需使用标签显示(上述第二种方法)。这是an example of doing that,尽管它比您现在看起来需要的要复杂。 我注意到您的代码的一件事。大部分时间都花在了调整图像大小上!如果 GUI 不会改变大小,我只会缩放一次。 (拍前额)并且每次绘制都会调用make()方法,这会导致图像再次加载! 【参考方案1】:

每次调用repaint() 时,您都在设置变量img 的值,这会导致闪烁。而是在您的构造函数中初始化一次。那么在这种情况下也不需要额外的 make 方法。这应该有效:

import java.awt.*;
import java.io.*;
import java.awt.image.*;
import javax.imageio.ImageIO;
import java.awt.event.*;

class MyFrame extends Frame implements KeyListener 

    BufferedImage img;
    int x = 100, y = 100;

    public MyFrame() 
        super("Box");
        this.setSize(480, 480);
        this.setVisible(true);
        this.addKeyListener(this);
        this.requestFocus();
        this.setResizable(false);
        try 
            img = ImageIO.read(new File("c:/users/udesh_2/desktop/Boundary.jpg"));   
         catch (IOException io) 
            io.printStackTrace();
        
    

    @Override
    public void paint(Graphics g) 
        super.paint(g);
        g.drawImage(img, 0, 0, getWidth(), getHeight(), this);
        g.setColor(Color.black);
        g.fillOval(x, y, 40, 40);
    

    public static void main(String $[]) 
        MyFrame f = new MyFrame();
        f.repaint();
    

    public void keyPressed(KeyEvent key) 
        boolean found = false;

        if (key.getKeyCode() == KeyEvent.VK_UP) 
            found = true;
            y--;
        
        if (key.getKeyCode() == KeyEvent.VK_DOWN) 
            found = true;
            y++;
        
        if (key.getKeyCode() == KeyEvent.VK_LEFT) 
            found = true;
            x--;
        
        if (key.getKeyCode() == KeyEvent.VK_RIGHT) 
            found = true;
            x++;
        
        if (found) 
            repaint();
        
    

    public void keyTyped(KeyEvent key) 
    

    public void keyReleased(KeyEvent key) 
    

【讨论】:

g.drawImage(img, 0, 0, getWidth(), getHeight(), null); 1) 首先致电super.paint(g);。 2) FrameImageObserver 所以 null 最好是 this @AndrewThompson 很好的观察和很好的建议,我已经编辑了我的答案。【参考方案2】:
import java.awt.*;
import java.io.*;
import java.awt.image.*;
import javax.imageio.ImageIO;
import java.awt.event.*;

class MyFrame extends Frame implements KeyListener 

    BufferedImage img;
    Image _img;
    Graphics gfx;
    int x = 100, y = 100;

    public MyFrame() 
    super("Box");
    this.setSize(1000,780);
    this.setVisible(true);
    this.addKeyListener(this);
    this.requestFocus();
    this.setResizable(false);
    try 
        img = ImageIO.read(new File("c:/users/udesh_2/desktop/Boundary.jpg"));   
     catch (IOException io) 
        io.printStackTrace();
    
    _img=createImage(getWidth(),getHeight());
    gfx=_img.getGraphics();

    

    @Override
    public void paint(Graphics g) 
        if(img!=null)
        gfx.drawImage((Image)img,0,0,getWidth(),getHeight(),this);
        gfx.fillOval(x,y,30,30);

        g.drawImage(_img, 0, 0, getWidth(), getHeight(), this);

        try
        
            Thread.sleep(70);

        catch(Exception e)System.out.println(e);
        
    

    public static void main(String $[]) 
        MyFrame f = new MyFrame();
        f.repaint();
    

    public void keyPressed(KeyEvent key) 
    boolean found = false;

        if (key.getKeyCode() == KeyEvent.VK_UP) 
            found = true;
            y-=2;
        
        if (key.getKeyCode() == KeyEvent.VK_DOWN) 
            found = true;
            y+=2;
        
        if (key.getKeyCode() == KeyEvent.VK_LEFT) 
            found = true;
            x-=2;
        
        if (key.getKeyCode() == KeyEvent.VK_RIGHT) 
            found = true;
            x+=2;
        
        if (found) 
            repaint();
        
    

    public void keyTyped(KeyEvent key) 
    

    public void keyReleased(KeyEvent key) 
    

【讨论】:

以上是关于如何解决由于加载图像而导致屏幕闪烁的问题?的主要内容,如果未能解决你的问题,请参考以下文章

如何修复 M1 Mac 外接显示器屏幕闪烁、白噪声、黑屏等问题?

Android SurfaceView导致屏幕闪烁

投影仪连接笔记本电脑屏幕显示闪烁问题如何消除?

CSS3 转换导致屏幕闪烁或字体别名

Unity 模型出现 条纹,闪烁的原因

神舟笔记本K480N-I7 D3笔记本屏幕闪烁?