簡體   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