1

SpacePotaters (JFrame のサブクラス) というトップレベルの GUI クラスがあり、そのコンテンツ ペインに panelViews (CardLayout レイアウト マネージャーを使用) という JPanel を追加します。特に、MainMenu オブジェクト (JPanel のサブクラス) と GameView オブジェクト (JPanel のサブクラス) をカードとして panelView に追加します。

public SpacePotaters(){
    super("Space Potaters");
    Container content = getContentPane();

    // initialize components
    gameView = new GameView(this);
    mainMenu = new MainMenu(this);
    leaderboard = new Leaderboard(this);
    instructions = new JPanel(); // to do
    cLayout = new CardLayout();

    // add "cards" to CardLayout manager
    panelViews = new JPanel(cLayout);
    panelViews.setPreferredSize(new Dimension(WINDOW_WIDTH, WINDOW_HEIGHT));
    panelViews.add("gameView", gameView);
    panelViews.add("mainMenu", mainMenu);
    panelViews.add("leaderboard", leaderboard);
    panelViews.add("instructions", instructions);

    // initially display menu menu
    content.add(panelViews);
    cLayout.show(panelViews,"mainMenu");

    addWindowListener(this);
    pack();
    setResizable(false);

    // relocate window to center of screen
    setLocationRelativeTo(getRootPane());
}

便利な場合は、メイン メニューのペイント メソッドを次に示します。

@Override
public void paintComponent(Graphics g){
    super.paintComponent(g);
    g.drawImage(mainMenuBackground, 0, 0, spTop.getWindowWidth(), spTop.getWindowHeight(), null);

}

今は背景画像をペイントするだけです。後で、クリックすると別のカードに切り替わる JButton を追加します。

メイン メニュー カードから始めて、必要に応じて他のカードに切り替えるという考え方です。プログラムを実行したところ、gameView 用に作成された画像に置き換わる前に、メイン メニュー カードが一瞬点滅することに気付きました。ゲームが途中で開始されないように、実際にそのカードに切り替えるまで、gameView グラフィックスのレンダリングを待つ必要があることはわかっています。私が混乱するのはそこじゃない。待たなくても、gameView が表示されずに起動してしまうのではないでしょうか。つまり、gameView 内で何が起こっているかに関係なく、mainMenu だけが表示されるカードのままであるべきではありませんか?

問題は、アクティブ レンダリングとダブル バッファリングを使用する gameView 内にあると考えました。GameView には、ゲームのループごとに 1 回呼び出される次のメソッドがあります。

public void paintScreen(){
    // get fresh graphics context for GameView each time
    Graphics context = getGraphics();
    if (context != null && dbImage != null){
        context.drawImage(dbImage, 0, 0, null);
    }
    context.dispose();
}

このメソッドの本体をコメント アウトすると、必要な結果が生成されます。mainMenu のみが表示されます。どうしてこうなったのか不思議です。各コンポーネント (JFrame、JPanel など) には独自のグラフィックス コンテキストがあると思いました。では、GameView 内で getGraphics() を呼び出した場合、spTop または panelViews のグラフィック コンテキストではなく、gameView パネルのグラフィック コンテキストを返すべきではありませんか? また、その特定のグラフィックス コンテキストのみを変更するため、gameView パネルが表示されない場合 (mainMenu オブジェクトで CardLayout の show() メソッドを使用する場合は表示されないはずです)、メイン メニューのビューに影響を与えることはありません。 . 何か案は?

注: isVisible() を使用して gameView と mainMenu の両方をテストすると、gameView は false を返し、mainMenu は true を返します。また、getGraphics() を使用して、mainMenu、spTop、および gameView グラフィック コンテキストがすべて異なるかどうかをテストしました。そのため、gameView は独自のグラフィックス コンテキストで画像を描画しており、表示されませんが、paintScreen() 内の drawImage() の効果は引き続き表示されます。本当に混乱しています。

4

1 に答える 1

0

何が起こっているのかを理解するのにあまりにも多くの時間を費やした後、埋め込まれたグラフィックス コンポーネント (少なくとも私が使用している形式) 内でのアクティブなレンダリングは、そのコンポーネントの可視性を無視していると結論付けることができます。したがって、paintScreen() 内の drawImage() は、呼び出し元の JPanel が表示されているかどうかに関係なく、常に表示される結果を表示します。

完全にはわかりませんが、この混乱は、アクティブ レンダリングとパッシブ レンダリングを混在させようとすることに関係があるのではないかと思います。mainMenu は paintComponent() をオーバーライドするため、パッシブ レンダリングを使用してそれ自体をペイントします。gameView の可視性を false に設定すると、最上位の JFrame が単に gameView の paintComponent() を呼び出さない可能性があります。ただし、gameView は paintScreen() で描画するため、可視性を false に設定しても動作には影響しません。これについての具体的な情報を見つけることができなかったので、これはすべて実験に基づく推測です.

また、BufferStrategy を使用してアクティブなレンダリングを実行しようとした場合 (つまり、BufferStrategy の show() も関連するグラフィックス コンポーネントの可視性を無視し、可視画面に描画する場合) に同じ結果が得られたかどうかはわかりません。同じように)。まだまだ研究が必要なところです。

この理解を現在のプログラムとどのように調和させるかについては、すべてを書き直したくはないので、ハイブリッド アプローチを使用することにしました。panelViews/「カード」(CardLayout を使用) の切り替えにパッシブ レンダリングを使用します。gameView に切り替えたときにのみ、そのアクティブ レンダリング動作をオンにします。終了して別のカードに戻るときは、gameView のアクティブ レンダリングをオフに戻します。パッシブ レンダリングとアクティブ レンダリングを混在させることはお勧めできませんが、両方の戦略を同時に使用することはないため、問題が発生しないことを願っています。このアプローチは現在、mainMenu と gameView の切り替えに機能しているため、他のパッシブ レンダリング コンポーネントを追加するときに機能することを期待しています。

于 2011-11-29T18:51:39.423 に答える