CardLayout中显示错误的JPanel。 getGraphics()的问题

时间:2011-11-28 19:24:37

标签: java swing graphics jpanel cardlayout

我有一个名为SpacePotaters(JFrame的子类)的顶级GUI类,我在其内容窗格中添加了一个名为panelViews的JPanel(它使用CardLayout布局管理器)。除此之外,我将一个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吗?换句话说,不管majorView内部发生了什么,主菜单都不应该是唯一可见的卡吗?

我认为这个问题是gameView中的问题,它使用主动渲染和双缓冲。 GameView有这种方法,每次循环都会调用一次:

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()时,它不应该返回gameView面板的图形上下文,而不是spTop或panelViews的图形上下文吗?并且因为它只改变了特定的图形上下文,如果gameView面板不可见(如果我在mainMenu对象上使用CardLayout的show()方法则不应该这样),那么它不应该影响我对主菜单的看法。有什么想法吗?

注意:如果我使用isVisible()测试gameView和mainMenu,则gameView返回false,mainMenu返回true。另外,我使用getGraphics()来测试mainMenu,spTop和gameView图形上下文是否都不同 - 它们是。所以gameView在自己的图形上下文中绘制图像并且不可见,但paintScreen()中的drawImage()效果仍然显示!真的很困惑。

1 个答案:

答案 0 :(得分:0)

在花费太多时间试图弄清楚发生了什么之后,我只能得出结论,嵌入式图形组件中的主动渲染(至少以我正在使用它的形式)忽略了该组件的可见性。因此,paintScreen()中的drawImage()将始终显示可见结果,无论调用它的JPanel是否可见。

我不完全确定,但我认为这种混淆可能与尝试将主动渲染与被动渲染混合有关。 mainMenu覆盖paintComponent(),因此使用被动渲染来绘制自身。可能是通过将我的gameView的可见性设置为false,顶级JFrame根本不会调用gameView的paintComponent()。但是,由于gameView使用paintScreen()绘制,因此将其可见性设置为false不会影响其行为。这是基于实验的所有推测,因为我找不到任何关于此的具体信息。

另外,如果我试图使用BufferStrategy执行主动渲染(即如果BufferStrategy的show()也会忽略其相关图形组件的可见性并绘制到,那么我不确定是否会得到相同的结果)可见的屏幕也是如此)。这仍然需要研究。

至于我如何将这种理解与我当前的程序相协调 - 因为我不想重写所有内容,所以我决定使用混合方法。我将使用被动渲染在我的panelViews /“cards”之间切换(使用CardLayout)。只有当我切换到gameView时,才会打开其活动呈现行为。当我退出并返回另一张卡片时,我将gameView的活动渲染关闭。我知道不鼓励混合被动和主动渲染,但希望没有问题出现,因为我从不同时使用这两种策略。这种方法目前适用于在mainMenu和gameView之间切换,所以我希望它在我添加其他被动渲染组件时能够正常工作。