【问题标题】:Can't stop flickering on JPanel无法停止在 JPanel 上闪烁
【发布时间】:2015-11-05 09:36:37
【问题描述】:

我有一个创建新线程的类。

`

public ScreenG(JPanel PanelR)
{
    Panel = PanelR;
    RenderImage = new BufferedImage(1, 1, BufferedImage.TYPE_INT_RGB);
    FPS = 25;
    Hide = false;

    (new Thread() 
    {
        public void run() 
        {   
              while(true)
              {
                  if(Hide == false)
                  {
                    Timer = System.currentTimeMillis() + (1000/FPS);

                    if(!DrawRendering)
                    {
                        Graphics g = Panel.getGraphics();
                        g.drawImage(RenderImage, 0, 0, null);
                    }

                    DrawRendering = false;

                    while(System.currentTimeMillis() <= Timer) try { Thread.sleep(1); } catch (InterruptedException e) {Thread.currentThread().interrupt();}
                  }
              }
        }
    }).start();
}

public void draw(BufferedImage ImageR)
{
    DrawRendering = true;
    RenderImage = ImageR;
    Graphics g = Panel.getGraphics();
    g.drawImage(RenderImage, 0, 0, null);
}`

在我的主目录中,我创建了一个 ScreenG 的新实例。这将启动一个新线程,该线程将 bufferedImage 绘制到具有一致 FPS 的 JPanel 上。 然后我主要用我创建的图像调用draw。有时它可以工作,但有时面板上的图像会闪烁。我尝试了一些变化,比如 draw 函数接管了绘图。他们都不工作。我只能减少闪烁。

【问题讨论】:

  • 您应该按照 Swing 图形教程使用被动图形。此外,您的代码通过在后台线程中进行关键 Swing 调用完全忽略了 Swing 线程规则。我劝你不要这样做。
  • 变量名不应以大写字符开头。遵循任何教科书或教程中演示的 Java 约定。不要自己编造!

标签: java swing jpanel flicker drawimage


【解决方案1】:

设计上不可能。 Swing 不会与实际将屏幕数据发送到监视器的位图光栅 DMA 同步,因此当您忙于向它渲染时,屏幕缓冲区总是可能被 DMA 读取(可能的例外是全屏模式)。

要至少最小化闪烁,请遵循自定义 Swing 绘画的推荐方法:https://docs.oracle.com/javase/tutorial/uiswing/painting/

您可以使用 Swing 计时器或 SwingUtilities.invokeAndWait/invokeLater 从另一个线程轻松触发 EDT 上的定期重绘(无论哪种方式最适合您的设计)。

【讨论】:

    【解决方案2】:

    闪烁可能是因为更新后渲染速度不够快。

    现在我建议您在渲染其组件时使用Swings paintComponent (Graphics g)。话虽如此。为您解决闪烁问题,在您的JFrame 中添加BufferStrategy

    如果没有可用的代码,我只能提供一个通用的解决方案。

    JFrame jframe = new JFrame ();
    
    ...
    
    BufferStrategy bufferstrategy = jframe.getBufferStrategy ();
    
    if (bufferstrategy == null) {
        jframe.createBufferStrategy(3);
        return;
    }
    
    g.dispose();
    bufferstrategy.show();
    

    要阅读有关BufferStrategy 的更多信息,我建议阅读documentation。

    小笔记

    您的代码中没有理由存储JPanel PanelR 或BufferedImage ImageR。您可以直接在 PanelR 上直接调用方法。 ImageR.

    【讨论】:

      【解决方案3】:

      感谢您的回答。我阅读了您推荐的 Oracle 教程,并让我的 paintComponent() 函数在主线程上正常工作。为此,我从 draw() 函数中调用 JPanel().repaint()。接下来我将学习使用 BufferStrategy。

      【讨论】:

        猜你喜欢
        • 2014-03-19
        • 2010-12-29
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2016-03-06
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多