【问题标题】:Why does my applet flash for every repaint?为什么每次重绘我的小程序都会闪烁?
【发布时间】:2012-11-04 01:00:43
【问题描述】:

我在网上找到了一些Java游戏代码,我正在尝试修改它。我将它从 JFrame 转换为 Applet,但是每次重新绘制屏幕时我的游戏都会开始闪烁。我尝试了双缓冲,但没有区别。

来源:

    private void paintDisks(Graphics g) {
        try {
            for (Disk d : disk)
                paintDisk(g, d);
        } catch (Exception ex) {
            //System.out.println(ex.getMessage());
            paintDisks(g); // retry so the disks never not get painted
        }
    }
    private void paintDisk(Graphics g, Disk d) {
        if (d == null)
            return;
        if (diskimg[d.player] == null) {
            g.setColor(colour[d.player]);
            g.fillOval((int)d.x - 1, (int)d.y - 1, 32, 32);
        } else {
            g.drawImage(diskimg[d.player],
                       (int)d.x - 1, (int)d.y - 1,
                        32, 32, this);
        }
    }

    @Override
    public void paint(Graphics g) {
        // paint real panel stuff
        super.paint(g);

        Graphics gr; 
        if (offScreenBuffer==null ||
              (! (offScreenBuffer.getWidth(this) == this.size().width
              && offScreenBuffer.getHeight(this) == this.size().height)))
        {
            offScreenBuffer = this.createImage(size().width, size().height);
        }

        gr = offScreenBuffer.getGraphics();

        gr.clearRect(0,0,offScreenBuffer.getWidth(this),offScreenBuffer.getHeight(this));

        // paint the disks
        paintDisks(gr);

        // paint the curser ontop of the disks
        paintCurser(gr);

        g.drawImage(offScreenBuffer, 0, 0, this);   
    }

    @Override
    public void run() {

        while (true) {
            repaint();

            try {
                Thread.sleep(9, 1);
            } catch (InterruptedException ex) {
                System.out.println(ex.getMessage());
            }
        }
    }

}

【问题讨论】:

  • 如果您首先将其分解为一个更简单的自包含示例来说明问题,那么对于您和我们来说,调试可能会更容易。

标签: java applet awt


【解决方案1】:

简答:不要在您的Board.paint() 方法中调用super.paint()

长答案: Applet 也是一个具有自己的显示属性的容器,包括您通过 setBackground(Color.WHITE); 作为构造函数的一部分设置的背景颜色。通过调用super.paint(g),您正在使小程序将其白色背景绘制到显示图形上,并调用任何包含的组件绘制。这就是闪烁的原因 - 每个绘制周期,它会将屏幕显示涂成白色,然后将您的 offscreenBuffer 图像复制到屏幕显示。

最好是明确的,忘记Applet背景,删除super.paint(g),然后自己完成所有绘制步骤。您需要将clearRect() 替换为setColor()fillRect()

你也应该实现update()

@Override
public void update(Graphics g) { paint(g); }

@Override
public void paint(Graphics g) {
    // no super.paint(g)

    if (offScreenBuffer==null ||
          (! (offScreenBuffer.getWidth(this) == this.size().width
          && offScreenBuffer.getHeight(this) == this.size().height)))
    {
        offScreenBuffer = this.createImage(size().width, size().height);
    }

    Graphics gr = offScreenBuffer.getGraphics();

    // blank the canvas
    gr.setColor(Color.WHITE);
    gr.fillRect(0,0,offScreenBuffer.getWidth(this),offScreenBuffer.getHeight(this));

    // paint the disks
    paintDisks(gr);

    // paint the curser ontop of the disks
    paintCurser(gr);

    g.drawImage(offScreenBuffer, 0, 0, this);   
}

【讨论】:

    【解决方案2】:

    Ivo Wetzel 看一下游戏引擎Bonsai。我很喜欢。

    它使用BufferStrategy,这是我认为双缓冲的最佳方式。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2021-10-14
      • 2020-10-31
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多