繁体   English   中英

JFrame super.paint(g)导致闪烁

[英]JFrame super.paint(g) Causing Flickering

我正在使用自己的双缓冲在渲染循环上工作,我没有JPanel而是JFrame(据我所知,JPanel会自动双缓冲)。 我的问题是,当我调用super.paint(g)时,它会导致屏幕闪烁。 当我对此发表评论时,它就消失了。

在ATM上,我创建一个BufferedImage并获取它的Graphics2D,然后每个渲染循环用纯色冲洗图像并调用repaint()。 在paint方法中,我调用super并使用paint()方法的图形绘制图像。 即使渲染1 fps,这也会导致我的屏幕闪烁。

public void run()
{
    long startTime;
    long runTime;
    double residualTime = 0;

    while(isRunning)
    {
        startTime = System.nanoTime();
        **update.update();**
        render.render();

        runTime = System.nanoTime() - startTime;
        if(runTime < 1e9/fpsTarget)
        {
            Double sleepTime = (1e9/fpsTarget - runTime) / 1e6;

            residualTime += sleepTime % 1;
            sleepTime -= sleepTime % 1;

            if(residualTime > 1)
            {
                sleepTime++;
                residualTime--;
            }

            try
            {
                sleep(sleepTime.longValue());
            }
            catch (InterruptedException e)
            {
                e.printStackTrace();
            }
            finally
            {
                /*
                System.out.println("\n     Run time: " + runTime / 1e6);
                System.out.println("   Sleep time: " + sleepTime);
                System.out.println("Residual Time: " + residualTime);
                */
            }
        }
        //fps(startTime);
    }
}

public class Render
{
    private Screen screen;

    Graphics2D graphics;
    BufferedImage image;

    public Render()
    {
        screen = new Screen();

        image = new BufferedImage(screen.getWidth(), screen.getHeight(), BufferedImage.TYPE_INT_RGB);
        graphics = image.createGraphics();
    }

    public void render()
    {
        flush();
        screen.setImage(image);
        screen.repaint();
    }

    private void flush()
    {
        graphics.setPaint(Color.BLUE);
        graphics.fillRect(0, 0, image.getWidth(), image.getHeight());
    }
}

public class Screen extends JFrame
{   
    private BufferedImage image;

    public Screen()
    {
        super(TITLE);
        setSize(WINDOW_WIDTH, WINDOW_HEIGHT);
        setLocation(300, 150);
        setResizable(false);
        setVisible(true);
        setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
    }

    @Override
    public void paint(Graphics g)
    {
        super.paint(g);
        g.drawImage(image, 0, 0, null);
    }

    public void setImage(BufferedImage image)
    {
        this.image = image;
    }

我尝试过添加一个JPanel并通过paintComponent()进行渲染,但是存在相同的问题。 任何想法建议都会有所帮助!

编辑-解决

在Render.render()方法中设置图像时,可能自动调用了repaint()。 然后,我在引起两次刷新后立即调用repaint()。 删除我自己的repaint()调用即可解决此问题。

奇怪的是,当我调用repaint()之前,删除super.paint()也解决了这个问题。 有什么想法吗?

看来您在处理循环中正在调用睡眠。

 sleep(sleepTime.longValue());

如果在单独的线程中调用它,那么您正在从另一个线程(而不是Swing的AWT线程)调用重绘。 不建议从AWT线程外部调用Swing组件。 如果它是AWT线程,它将在睡眠期间阻止绘画。

尽管这可能不是导致闪烁的主要问题,但是您应该修改代码以使用Swing计时器,以便在AWT线程上调用重新绘制逻辑并且不会阻塞。

好吧,我不确定这是否是答案,但是我试图向安德鲁展示当我使用面板渲染而不是框架但没有成功时我的代码是什么样的。 我删除了所有更改内容,并尝试遵循Ashwinee的线程理论。 在更改任何内容之前,我运行了我的代码一次,它运行良好。

将我当前的代码与提交时的代码进行比较,我认为不同之处在于我在Render.render()方法中删除了repaint()语句。 我唯一的猜测是,JFrame识别出它先前绘制的内容已更改,因此它会自动重新绘制,因此我实际上每个循环都重新绘制了两次。

如果我添加repaint(),则在闪烁的返回中进行回调。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM