1

JPanel の更新メソッドをオーバーライドして、Java でゲームのダブル バッファリングを実現しようとしています。通常のコードなどをすべて実行しても機能しません。スタック オーバーフロー エラーがスローされます。具体的なエラーは次のとおりです。

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)

私のコードも特に複雑ではありません:

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.");
                }
            }
        };

私は誰かが私が間違っていた場所を指摘できることを望んでいました.更新が何度も呼び出されていることに関係があるのではないかと考えています.更新が間違った方法である可能性がありますか?

4

3 に答える 3

1

paintコンポーネントの 内で呼び出しているpaintComponentため、コンポーネントは再描画を続けます。これにより、 が発生しStackOverflowExceptionます。また、APIpaintは、アプリケーションで明示的に呼び出すことについて開発者に警告します。

コンポーネントを描画するために Swing によって呼び出されます。アプリケーションはペイントを直接呼び出すべきではなく、代わりに repaint メソッドを使用してコンポーネントの再描画をスケジュールする必要があります。

このメソッドは、ペイントの作業を、3 つの保護されたメソッド (paintComponent、paintBorder、および paintChildren) に実際に委譲します。それらはリストされた順序で呼び出され、子がコンポーネント自体の上に表示されるようにします。一般的に言えば、コンポーネントとその子は、境界線に割り当てられたインセット領域に描画されるべきではありません。いつものように、サブクラスはこのメソッドをオーバーライドできます。UI (ルック アンド フィール) デリゲートの paint メソッドを特殊化するだけのサブクラスは、paintComponent をオーバーライドする必要があります。

于 2011-03-19T03:13:20.453 に答える
1

paint()からまたはupdate()メソッドを呼び出さないでくださいpaintComponent()

Thread.sleep()また、描画メソッドを呼び出さないでください。repaint()代わりに、x ミリ秒ごとにゲーム モデルを更新し、オーバーライドしたカスタム コンポーネントを呼び出すスレッドを作成しpaintComponent()て、ゲームの状態を描画します。

于 2011-03-19T03:07:02.843 に答える
0

g.dispose()処理が完了したら、すべてのフレーム を呼び出す必要があります。そうしないと、メモリから解放されず、スタック オーバーフロー エラーが発生します。http://download.oracle.com/javase/1.3/docs/api/java/awt/Graphics.html

于 2011-03-19T03:03:26.487 に答える