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.