CardLayout中显示错误的JPanel。 getGraphics()的问题 [英] Wrong JPanel displayed in CardLayout. Issues with getGraphics()

查看:149
本文介绍了CardLayout中显示错误的JPanel。 getGraphics()的问题的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我有一个名为SpacePotaters(JFrame的子类)的顶级GUI类,我在其内容窗格中添加了一个名为panelViews(使用CardLayout布局管理器)的JPanel。除此之外,我还将一个MainMenu对象(JPanel的子类)和一个GameView对象(JPanel的子类)作为卡片添加到panelView。

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

//初始化组件
gameView = new GameView(this);
mainMenu = new MainMenu(this);
排行榜=新排行榜(本);
instructions = new JPanel(); //做
cLayout = new CardLayout();

//将cards添加到CardLayout管理器
panelViews = new JPanel(cLayout);
panelViews.setPreferredSize(new Dimension(WINDOW_WIDTH,WINDOW_HEIGHT));
panelViews.add(gameView,gameView);
panelViews.add(mainMenu,mainMenu);
panelViews.add(排行榜,排行榜);
panelViews.add(说明,说明);

//最初显示菜单菜单
content.add(panelViews);
cLayout.show(panelViews,mainMenu);

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

//将窗口重定位到屏幕中心
setLocationRelativeTo(getRootPane());
}

如果它有用,主菜单的paint方法就在这里:

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


$ / code>

现在我只画了背景图片 - 我们会添加JButtons,点击时会切换到不同的卡片。



这个想法是,我从主菜单卡开始,在必要时切换到其他卡。我运行了程序并注意到主菜单卡在被为gameView创建的图像替换之前短暂闪烁。我知道我应该等待渲染gameView图形,直到我切换到该卡,以便游戏不会过早启动。这不是我困惑的地方。即使我不等待,gameView不应该开始运行而不能查看它吗?换句话说,不应该mainMenu保持唯一的可见卡,无论gameView内部发生了什么?



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

  public void paintScreen(){
//每次为GameView获取新鲜的图形上下文
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()效果仍然显示出来!真的很困惑。

解决方案

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



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



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



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


I have a top-level GUI class called SpacePotaters (subclass of JFrame) and I add a JPanel called panelViews (which uses the CardLayout layout manager) to its content pane. Among other things, I add a MainMenu object (subclass of JPanel) and a GameView object (subclass of JPanel) as cards to 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());
}

In case its useful, the main menu paint method is here:

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

}

Right now I just paint the background image - later I'll add JButtons that when clicked will switch to different cards.

The idea is that I start off with the main menu card and switch to the other cards when necessary. I ran the program and noticed that the main menu card briefly flashes before being replaced by the image created for gameView. I know that I should wait to render the gameView graphics until I actually switch to that card, so that the game doesn't start prematurely. That's not where I get confused. Even if I don't wait, shouldn't gameView just start running without being able to view it? In other words, shouldn't mainMenu remain the only visible card regardless of what is going on inside gameView?

I figured the issue was something within gameView, which uses active rendering and double-buffering. GameView has this method which is called once every loop of the game:

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();
}

Commenting out the body of this method produces the desired results - only the mainMenu is shown. I'm confused as to why this is the case. I thought each component (JFrame, JPanel, etc) has its own graphics context. So when I call getGraphics() inside GameView, shouldn't it return the graphics context for the gameView panel, not the graphics context for spTop or panelViews? And since it only changes that specific graphics context, if the gameView panel is not visible (which it shouldn't be if I use CardLayout's show() method on the mainMenu object), then it shouldn't affect my view of the main menu. Any ideas?

Note: If I test both gameView and mainMenu with isVisible(), gameView returns false and mainMenu returns true. Also, I used getGraphics() to test if the mainMenu, spTop, and gameView graphics contexts were all different - they were. So gameView is drawing an image on its own graphics context and is not visible, but the effects of drawImage( ) within paintScreen() are still showing! Really confused.

解决方案

After spending way too much time trying to figure out what's going on, I can only conclude that active rendering within an embedded graphics component (at least in the form I'm using it) ignores the visibility of that component. Therefore, drawImage() within paintScreen() will always show visible results, regardless of whether the JPanel it is called from is visible or not.

I'm not entirely sure, but I think this confusion might have something to do with trying to mix active rendering with passive rendering. The mainMenu overrides paintComponent() and so uses passive rendering to paint itself. It might be that by setting the visibility of my gameView to false, the top-level JFrame simply does not call gameView's paintComponent(). However, since gameView draws with paintScreen(), setting its visibility to false does not affect its behavior. This is all speculation based on experimentation, since I could not find any concrete information about this.

Also, I'm not sure if I would have gotten the same results if I would have tried to perform active rendering using a BufferStrategy (i.e. if BufferStrategy's show() would also ignore the visibility of its related graphics component and draw to the visible screen as well). That's something that still needs to be researched.

As far as how I'm going to reconcile this understanding with my current program - since I don't want to rewrite everything, I've decided to use a hybrid approach. I'm going to use passive rendering for switching between my panelViews/"cards" (using CardLayout). Only when I switch to gameView do I turn on its active-rendering behavior. When I exit and return to another card, I turn the active-rendering of gameView back off. I know that mixing passive and active rendering is discouraged, but hopefully no issues arise since I never use both strategies concurrently. This approach currently works for switching between mainMenu and gameView, so I expect it to work when I add other passively-rendered components.

这篇关于CardLayout中显示错误的JPanel。 getGraphics()的问题的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆