首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >使用覆盖for update方法的Java双缓冲区引发堆栈溢出

使用覆盖for update方法的Java双缓冲区引发堆栈溢出
EN

Stack Overflow用户
提问于 2011-03-19 10:58:24
回答 3查看 1.4K关注 0票数 1

我试图通过重写我的JPanel的更新方法来实现我的游戏的双缓冲,我做了所有常见的代码等,但它仍然不能工作,它抛出一个堆栈溢出错误,下面是具体的错误:

代码语言:javascript
复制
Exception in thread "AWT-EventQueue-0" java.lang.StackOverflowError
        at java.awt.Rectangle.<init>(Rectangle.java:193)
        at java.awt.Rectangle.<init>(Rectangle.java:208)
        at sun.awt.image.BufImgSurfaceData.getBounds(BufImgSurfaceData.java:369)
        at sun.java2d.loops.GraphicsPrimitive.convertFrom(GraphicsPrimitive.java:533)
        at sun.java2d.loops.GraphicsPrimitive.convertFrom(GraphicsPrimitive.java:523)
        at sun.java2d.loops.MaskBlit$General.MaskBlit(MaskBlit.java:171)
        at sun.java2d.loops.Blit$GeneralMaskBlit.Blit(Blit.java:186)
        at sun.java2d.pipe.DrawImage.blitSurfaceData(DrawImage.java:927)
        at sun.java2d.pipe.DrawImage.renderImageCopy(DrawImage.java:550)
        at sun.java2d.pipe.DrawImage.copyImage(DrawImage.java:54)
        at sun.java2d.pipe.DrawImage.copyImage(DrawImage.java:982)
        at sun.java2d.SunGraphics2D.drawImage(SunGraphics2D.java:2979)
        at sun.java2d.SunGraphics2D.drawImage(SunGraphics2D.java:2964)
        at epicgame.Menu.displayMenu(Menu.java:71)
        at epicgame.GUI$1.paintComponent(GUI.java:64)
        at javax.swing.JComponent.paint(JComponent.java:1029)
        at epicgame.GUI$1.update(GUI.java:117)
        at epicgame.GUI$1.paintComponent(GUI.java:98)
        at javax.swing.JComponent.paint(JComponent.java:1029)

我的代码也不是特别复杂:

代码语言:javascript
复制
mainPanel = new JPanel()
        {
            @Override protected void paintComponent(Graphics g)
            {
                //super.paintComponent(g);

                if(menuEnabled == 1)
                {
                    Menu.displayMenu(g, mainPanel);
                }
                else if(gameNum == 1)
                { 
                    StreetFighter.StreetFighter(g, mainPanel);

                    // Calls the controls method within the controls class.
                    Controls.controls(Calendar.getInstance().getTimeInMillis() - timeOld);
                    timeOld = Calendar.getInstance().getTimeInMillis();
                }
                else if(gameNum == -1)
                {
                    Menu.scoreBoard(g, mainPanel);
                    if(loaded != true)
                    {
                        Menu.loadScoreBoard(mainPanel);
                        loaded = true;
                    }
                }
                if(gameNum > 0)
                {
                    if(longcat == true && longcatloaded != true)
                    {
                        Extras.loadLongCat();
                        longcatloaded = true;
                    }
                    if(longcatloaded == true && longcat == true)
                    {
                        Extras.displayLongCat(g, mainPanel);
                    }
                }

                // Causes an infinite loop, e.g makes the screen render over and over.
                //repaint();
                update(g);
            }

            @Override public void update(Graphics g)
            {
                System.err.println("Updating screen and using double buffer!");

                // initialize buffer
                if(dbImage == null)
                {
                    dbImage = createImage (this.getSize().width, this.getSize().height);
                    dbg = dbImage.getGraphics ();
                }
                // clear screen in background
                dbg.setColor (getBackground ());
                dbg.fillRect (0, 0, this.getSize().width, this.getSize().height);
                // draw elements in background
                dbg.setColor (getForeground());

                paint(dbg);

                // draw image on the screen
                g.drawImage (dbImage, 0, 0, this);

                try
                {
                    Thread.sleep(200);

                }
                catch (InterruptedException ex)
                {
                    System.err.print("cant delay repaint.");
                }
            }
        };

我希望有人能指出我哪里错了,我在想也许是因为更新被调用了太多次,或者更新是错误的方法?

EN

回答 3

Stack Overflow用户

回答已采纳

发布于 2011-03-19 11:07:03

不要从paintComponent()调用paint()update()方法。

另外,不要在任何绘制方法中调用Thread.sleep()。相反,创建一个每x毫秒更新一次游戏模型的线程,然后在已覆盖paintComponent()的自定义组件上调用repaint(),以便它绘制游戏状态。

票数 1
EN

Stack Overflow用户

发布于 2011-03-19 11:13:20

您将在组件的paintComponent中调用paint,这将导致组件不断地重新绘制自身。这将导致StackOverflowException。此外,API还警告开发人员在应用程序中显式调用paint

由 Swing 调用以绘制组件。 应用程序不应直接调用paint,而应使用repaint 方法来安排组件重绘。

该方法实际上将绘画工作委托给了三个受保护的方法:paintComponent、paintBorder 和paintChildren。 它们按列出的顺序调用,以确保子组件出现在组件本身的顶部。 一般来说,组件及其子组件不应该在分配给边框的 insets 区域中进行绘制。 子类可以像往常一样覆盖这个方法。 只想专门化 UI(外观和感觉)委托的绘制方法的子类应该重写paintComponent。

票数 1
EN

Stack Overflow用户

发布于 2011-03-19 11:03:26

您需要在完成后的每一帧调用g.dispose(),否则它将永远不会从内存中释放,并且您会看到堆栈溢出错误。http://download.oracle.com/javase/1.3/docs/api/java/awt/Graphics.html

票数 0
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/5359757

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档