代码之家  ›  专栏  ›  技术社区  ›  CourtJester5

JFrame超级。油漆(g)引起闪烁

  •  0
  • CourtJester5  · 技术社区  · 7 年前

    我正在使用我自己的双缓冲进行渲染循环,我没有JPanel,而是JFrame(据我所知,JPanel自动双缓冲)。我的问题是,当我叫super时。画图(g)它使我的屏幕闪烁。当我把它评论出来时,它就消失了。

    我创建一个BuffereImage并抓取它的图形2D,然后每个渲染循环我用纯色刷新图像并调用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()进行渲染,但也遇到了同样的问题。任何想法和建议都会很有帮助!

    编辑-已解决

    奇怪的是,之前我调用repaint()时,删除了super。paint()也解决了这个问题。知道为什么吗?

    2 回复  |  直到 7 年前
        1
  •  0
  •   Ashwinee K Jha    7 年前

    看起来您正在处理循环中调用sleep。

     sleep(sleepTime.longValue());
    

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

        2
  •  0
  •   CourtJester5    7 年前

    嗯,我不确定这是否是答案,但我试图向Andrew展示我的代码是什么样子的,当我使用面板渲染而不是框架时,但没有任何成功。我删除了我所改变的一切,并试图追求阿什温的线程理论。在更改任何内容之前,我只运行了一次代码,它运行得很好。

    将我当前的代码与提交时的代码进行比较,我认为区别在于我删除了渲染中的repaint()语句。render()方法。我唯一的猜测是,JFrame识别出它之前绘制的内容发生了更改,因此它会自动重新绘制,因此每次循环我都会有效地重新绘制两次。

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