Rikkokiri
Rikkokiri

Reputation: 85

CardLayout, panels from separate class not showing

I'm making my very first GUI for a rather simple board game. Besides game view I also need main menu and some other views too. Unfortunately my GUI was looking uglier than me in the morning, as the entire menu structure was in one class. I'm using card layout to switch between different views, so I figured I could separate those views into different classes. Sadly, this is where I ran into problems. All I got was a blank window.

After four hours of reserach I haven't been able to solve my problem so I'm asking you guys, do you have any idea what's wrong with my code? Even tough I think I've ruled out the obvious problems (not adding panels to my panel with card layout, not setting the layout etc.) I still think the problem must be something really simple. Yet nothing I've found, has helped.

So to the business, here's my "base GUI"

package teekkariloikka.gui;

import java.awt.*;
import java.awt.event.*;
import javax.swing.*;


public class TLGui extends JFrame {

    private static final long serialVersionUID = 1L;

    private static final int WIDTH = 1000;
    private static final int HEIGHT = 800;

    private static final String MAINMENU = "mainmenu";
    private static final String GAME = "game";

    private JPanel basePanel;

    private GameViewPanel gameViewPanel;
    private MainMenuPanel mainMenuPanel;

    JFrame frame = new JFrame();

    //Layout
    private CardLayout cardL = new CardLayout();

    public TLGui(){

        //Frame stuff
        frame.setTitle("Teekkariloikka");
        frame.setSize(WIDTH, HEIGHT);
        frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
        frame.setVisible(true);
        frame.setResizable(false);      

        //This is the panel where I add the ohter panels for menu and game
        basePanel = new JPanel();
        basePanel.setLayout(cardL);

        //Creating the panels I want to add. Excuse the confusing naming.
        gameViewPanel = new GameViewPanel(); 
        mainMenuPanel = new MainMenuPanel();

        //Adding the panels to the basePanel
        basePanel.add(mainMenuPanel, MAINMENU);
        basePanel.add(gameViewPanel, GAME);
        cardL.show(basePanel, MAINMENU);        

        //ADDING basePanel to the frame
        frame.add(basePanel);

        //Action listeners for buttons. Take a look at the classes.
        mainMenuPanel.setNewGameButtonListener(new ActionListener(){
            @Override
            public void actionPerformed(ActionEvent e){
                cardL.show(basePanel, GAME);
            }
        });

        gameViewPanel.setMainMenuButtonListener(new ActionListener(){
            @Override
            public void actionPerformed(ActionEvent e){{
                cardL.show(basePanel, MAINMENU);
            }
        }); 
    }

    public static void main(String[] args){
        SwingUtilities.invokeLater(new Runnable() {
            @Override
            public void run(){
                new TLGui();
            }
        }); 
    }
}

Then my MainMenuPanel class. It's a work in progress but should at least show the buttons. I tried my very best to translate everything I had written in Finnish (my mother tongue) and I really hope I'm not so blind to my code that I forgot something.

package teekkariloikka.gui;

import java.awt.*;
import java.awt.event.*;
import javax.swing.*;

public class MainMenuPanel extends JPanel{

    private static final long serialVersionUID = 1L;

    //Buttons
    private JPanel panel;
    private JButton newGameButton;
    private JButton quitButton;

    //Font
    Font menuFont = new Font("Arial", Font.BOLD, 24);
    //Layout
    private GridBagLayout menuLayout = new GridBagLayout();
    private GridBagConstraints c1 = new GridBagConstraints();

    public MainMenuPanel(){

        panel = new JPanel();

        //For testing //TODO remove
        panel.setBackground(Color.BLACK);

        newGameButton = new JButton("New Game");
        quitButton = new JButton("Quit");

        //New Game -button
        newGameButton.setPreferredSize(new Dimension(200, 100));
        newGameButton.setFont(menuFont);

        //Quit-button
        quitButton.setPreferredSize(new Dimension(200, 100));
        quitButton.setFont(menuFont);

        panel.setLayout(menuLayout);
        c1.insets = new Insets(10, 10, 10, 10);
        c1.gridx = 0;
        c1.gridy = 1;
        panel.add(newGameButton, c1);
        c1.gridx = 0;
        c1.gridy = 2;
        panel.add(quitButton, c1);
    }

    //Idea: http://stackoverflow.com/questions/19104014/add-an-actionlistener-to-a-jbutton-from-another-class
    public void setNewGameButtonListener(ActionListener listener){
        newGameButton.addActionListener(listener);
    }

    public void setQuitButtonListener(ActionListener listener){
        quitButton.addActionListener(listener);
    }
}

And GameViewPanel class. Also work in progress but like the previous class, this should look just fine.

package teekkariloikka.gui;

import java.awt.*;
import java.awt.event.*;
import javax.swing.*;
import javax.swing.border.*;

public class GameViewPanel extends JPanel{

    private static final long serialVersionUID = 1L;

    private JButton lopetaButton;
    private JButton tallennaButton;
    private JButton menuButton;

    BorderLayout bordL = new BorderLayout();    

    public GameViewPanel(){

        JPanel gameViewPanel = new JPanel();

        gameViewPanel.setLayout(bordL);
        gameViewPanel.setBorder(new EmptyBorder(10, 10, 10, 10)); 

        //Creating toolbar
        JToolBar toolbar = new JToolBar();
        toolbar.setFloatable(false);

        gameViewPanel.setLayout(bordL);
        gameViewPanel.setBorder(new EmptyBorder(10, 10, 10, 10)); 
        gameViewPanel.add(toolbar, BorderLayout.PAGE_START);        

        //Buttons
        lopetaButton = new JButton("Lopeta");
        menuButton = new JButton("Päävalikko");
        tallennaButton = new JButton("Tallenna");

        //Adding buttons to game view toolbar
        toolbar.add(lopetaButton); //TODO Add functionality!
        toolbar.add(tallennaButton); //TODO Add functionality!
        toolbar.add(menuButton); //TODO Add functionality!
    }

    public void setMainMenuButtonListener(ActionListener listener){
        menuButton.addActionListener(listener);
    }
}

I hope someone could point out mistake I've made - not matter how stupid I'd feel.

Also, any other feedback would be highly appreciated. As I said, this is my very first time writing GUI and I must say I feel pretty lost from time to time.

Upvotes: 0

Views: 663

Answers (3)

MadProgrammer
MadProgrammer

Reputation: 347214

In your MainMenuPanel pane you create an instance of JPanel...

public MainMenuPanel(){
    // A new panel
    panel = new JPanel();

    //For testing //TODO remove
    panel.setBackground(Color.BLACK);

    newGameButton = new JButton("New Game");
    quitButton = new JButton("Quit");

    //New Game -button
    newGameButton.setPreferredSize(new Dimension(200, 100));
    newGameButton.setFont(menuFont);

    //Quit-button
    quitButton.setPreferredSize(new Dimension(200, 100));
    quitButton.setFont(menuFont);

    panel.setLayout(menuLayout);
    c1.insets = new Insets(10, 10, 10, 10);
    c1.gridx = 0;
    c1.gridy = 1;
    panel.add(newGameButton, c1);
    c1.gridx = 0;
    c1.gridy = 2;
    panel.add(quitButton, c1);
    // But what do you do with panel??
}

But never add it to your MainMenuPanel...

You also do the same thing in your GameMenu...

 public GameViewPanel(){

    // Create JPanel...
    JPanel gameViewPanel = new JPanel();

    gameViewPanel.setLayout(bordL);
    gameViewPanel.setBorder(new EmptyBorder(10, 10, 10, 10)); 

    //Creating toolbar
    JToolBar toolbar = new JToolBar();
    toolbar.setFloatable(false);

    gameViewPanel.setLayout(bordL);
    gameViewPanel.setBorder(new EmptyBorder(10, 10, 10, 10)); 
    gameViewPanel.add(toolbar, BorderLayout.PAGE_START);        

    //Buttons
    lopetaButton = new JButton("Lopeta");
    menuButton = new JButton("Päävalikko");
    tallennaButton = new JButton("Tallenna");

    //Adding buttons to game view toolbar
    toolbar.add(lopetaButton); //TODO Add functionality!
    toolbar.add(tallennaButton); //TODO Add functionality!
    toolbar.add(menuButton); //TODO Add functionality!
    // But never do anything with it...
}

My recommendation is, don't. Both MainMenuPanel and GameMenu are extend from JPanel, simply create the UI ontop of these panels directly. There doesn't seem to be a need for these "inner" panels...

Upvotes: 0

Rikkokiri
Rikkokiri

Reputation: 85

Alright, I actually figured out the answer myself when I moved on to other things. While I was researching some layout design, I saw this piece of code and got the idea to use "this" reference in my panel classes.

So I deleted this piece of code from both MainMenuPanel and GameviewPanel

// A new panel
panel = new JPanel();

and then replaced references to that panel with this. Example from MainMenuPanel:

this.setLayout(menuLayout);
c1.insets = new Insets(10, 10, 10, 10);
c1.gridx = 0;
c1.gridy = 1;
this.add(newGameButton, c1);
c1.gridx = 0;
c1.gridy = 2;
this.add(quitButton, c1);

I can't say I'd perfectly understand why this works and the other way doesn't, but for now, a working solution is all I need. I hope this is someday useful to someone else too.

Upvotes: 0

camickr
camickr

Reputation: 324118

 cardL.show(basePanel, "2");

The name of the panel was not "2".

You define variables MAINMENU and GAME to represent the names of each panel.

Upvotes: 1

Related Questions