Java 中的双缓冲

发布于 2024-09-01 12:33:24 字数 2762 浏览 2 评论 0原文

我在程序中实现 DoubleBuffer 时遇到一些问题。在你被文字墙晕倒之前,你应该知道其中有很多内容是为了以防万一你需要知道。我认为我遇到问题的实际地方是在一种方法中。

我最近在 gpwiki 上查找了有关双缓冲的教程,并决定尝试将他们的代码实现到我正在尝试实现双缓冲的代码中。我收到以下错误:“java.lang .IllegalStateException:组件必须有一个有效的对等点”。

我不知道你知道与否有什么区别,但下面是带有 main 方法的代码。这只是一个在其内部显示 ChronosDisplay 类的框架。我用“...”省略了不相关的代码

public class CDM extends JFrame
{
    public CDM(String str)
    {
        super("CD:M - "+str);
        try
        {
            ...
            ChronosDisplay theGame = new ChronosDisplay(str);
            ((Component)theGame).setFocusable(true);
            add(theGame);
        }
        catch(Exception e)
        {
            System.out.println("CDM ERROR: " +e);
        }
    }
    public static void main( String args[] )
    {
        CDM run = new CDM("DP_Mini");
    }
}

这是我认为问题所在的代码(我认为问题出在paint()方法中)。该类显示在 CDM 类中。

public class ChronosDisplay extends Canvas implements  Runnable
{
    String mapName;
    public ChronosDisplay (String str)
    {
        mapName = str;
        new Thread(this).start();
        setVisible(true);
        createBufferStrategy(2);
    }
    public void paint( Graphics window )
    {
        BufferStrategy b = getBufferStrategy();
        Graphics g = null; 
        window.setColor(Color.white);
        try
        {
             g = b.getDrawGraphics();
            paintMap(g);
            paintUnits(g);
            paintBullets(g);
        }
        finally
        { g.dispose(); }
        b.show();
        Toolkit.getDefaultToolkit().sync(); 
    }
    public void paintMap( Graphics window )
    {
        TowerMap m = new TowerMap();
        try
        {
            m = new TowerMap(mapName);
            for(int x=0; x<m.getRows()*50; x+=50)
            {
                for(int y = 0; y<m.getCols()*50; y+=50)
                    {
                        int tileType = m.getLocation(x/50,y/50);
                        Image img;
                        if(tileType == 0)
                        {
                            Tile0 t = new Tile0(x,y);
                            t.draw(window);
                        }
                        ...// More similar if statements for other integers
            }
            catch(Exception e) ...
    }
    ...// Additional methods not shown here
    public void run()
    {
        try
        {
            while(true)
            {
                Thread.currentThread().sleep(20);
                repaint();
            }
        }
        catch(Exception e) ...
    }
}

如果您很好奇(我怀疑它很重要),Tile0 类中的 draw() 方法是:

public void draw( Graphics window )
{
    window.drawImage(img,getX(),getY(),50,50,null);
}

非常感谢任何指针、提示或解决方案。感谢您抽出时间! :D

I'm having some trouble implementing DoubleBuffer into my program. Before you faint from the wall of text, you should know that a lot of it is there just in case you need to know. The actual place where I think I'm having problems is in one method.

I've recently looked up a tutorial on the gpwiki about double buffering, and decided to try and implement the code they had into the code I have that I'm trying to implement doublebuffer in. I get the following error: "java.lang.IllegalStateException: Component must have a valid peer".

I don't know if it makes any difference if you know it or not, but the following is the code with the main method. This is just a Frame that displays the ChronosDisplay class inside it. I omitted irrelevant code with "..."

public class CDM extends JFrame
{
    public CDM(String str)
    {
        super("CD:M - "+str);
        try
        {
            ...
            ChronosDisplay theGame = new ChronosDisplay(str);
            ((Component)theGame).setFocusable(true);
            add(theGame);
        }
        catch(Exception e)
        {
            System.out.println("CDM ERROR: " +e);
        }
    }
    public static void main( String args[] )
    {
        CDM run = new CDM("DP_Mini");
    }
}

Here is the code where I think the problem resides (I think the problem is in the paint() method). This class is displayed in the CDM class

public class ChronosDisplay extends Canvas implements  Runnable
{
    String mapName;
    public ChronosDisplay (String str)
    {
        mapName = str;
        new Thread(this).start();
        setVisible(true);
        createBufferStrategy(2);
    }
    public void paint( Graphics window )
    {
        BufferStrategy b = getBufferStrategy();
        Graphics g = null; 
        window.setColor(Color.white);
        try
        {
             g = b.getDrawGraphics();
            paintMap(g);
            paintUnits(g);
            paintBullets(g);
        }
        finally
        { g.dispose(); }
        b.show();
        Toolkit.getDefaultToolkit().sync(); 
    }
    public void paintMap( Graphics window )
    {
        TowerMap m = new TowerMap();
        try
        {
            m = new TowerMap(mapName);
            for(int x=0; x<m.getRows()*50; x+=50)
            {
                for(int y = 0; y<m.getCols()*50; y+=50)
                    {
                        int tileType = m.getLocation(x/50,y/50);
                        Image img;
                        if(tileType == 0)
                        {
                            Tile0 t = new Tile0(x,y);
                            t.draw(window);
                        }
                        ...// More similar if statements for other integers
            }
            catch(Exception e) ...
    }
    ...// Additional methods not shown here
    public void run()
    {
        try
        {
            while(true)
            {
                Thread.currentThread().sleep(20);
                repaint();
            }
        }
        catch(Exception e) ...
    }
}

If you're curious (I doubt it matters), the draw() method in the Tile0 class is:

public void draw( Graphics window )
{
    window.drawImage(img,getX(),getY(),50,50,null);
}

Any pointers, tips, or solutions are greatly appreciated. Thanks for your time! :D

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(3

送你一个梦 2024-09-08 12:33:24

Swing 默认情况下是双缓冲的,因此您无需自己实现。

您不应该在 Swing 应用程序中使用 Canvas 类。也就是说,不要混合使用 AWT 和 Swing 组件。

所有 Swing 组件都应在 EDT 上创建。请阅读 Swing 教程以获取有关如何执行此操作的示例。

Swing is double buffered by default so you don't need to implement it yourself.

You should not be using the Canvas class in a Swing application. That is don't mix AWT and Swing components.

All Swing components should be created on the EDT. Read the Swing tutorial for examples on on how to do this.

混吃等死 2024-09-08 12:33:24

重写 addNotify() 并从那里创建 BufferStrategy

public ChronosDisplay (String str)
{
    mapName = str;
    new Thread(this).start();
    // Note: no createBufferStrategy() or setVisible()
}

public void addNotify() {
    super.addNotify();
    createBufferStrategy(2);
}

Override addNotify() and create the BufferStrategy from there:

public ChronosDisplay (String str)
{
    mapName = str;
    new Thread(this).start();
    // Note: no createBufferStrategy() or setVisible()
}

public void addNotify() {
    super.addNotify();
    createBufferStrategy(2);
}
浅笑依然 2024-09-08 12:33:24

通常,与双缓冲有关的错误意味着目标尚不可见。尝试将线程启动推到窗口设置可见并创建双缓冲区策略之后

Usually that error in regards to double buffering means the target isn't visible yet. Try pushing the thread start to after the window is set visible and the double buffer strategy is created

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文