Reputation: 85
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
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
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
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