I need to make a hangman game in Java using Swing. I made my hangman figures in photoshop and used the full image as the background layer and then placed the other components on top using JlayeredPane. However, there is always a slight delay when I add the JFrame and open the window. I tried to create a button to add and remove on JLayeredPane when clicked but this caused an even bigger delay. Any assistance will be very appreciated.
public class Game_Screen extends JLayeredPane {
private JLabel hangman;
public Game_Screen() {
super();
super.setBounds(0, 0, 1920, 1080);
hangman = new JLabel(new ImageIcon(Game_Screen.class.getResource("/images/hangman10.jpg")));
hangman.setBounds(0, 0, 1920, 1080);
add(hangman, Integer.valueOf(0));
}
}
An example of one of the Panes in the game
public class Home_Screen extends Game_Screen {
private JLabel title;
private JLabel score;
private JButton start;
public Home_Screen() {
super();
title = new JLabel("HANGMAN");
title.setBounds(490, 170, 942, 217);
title.setFont(new Font("Press Start", Font.PLAIN, 100));
add(title, Integer.valueOf(1));
score = new JLabel("High Score: 0");
score.setBounds(635, 330, 470, 67);
score.setFont(new Font("Press Start", Font.PLAIN, 30));
add(score, Integer.valueOf(1));
start = new JButton("START");
start.setBounds(635,400,400,120);
start.setBorderPainted(false);
start.setFont(new Font("Press Start", Font.PLAIN, 60));
add(start, Integer.valueOf(1));
}
public void addStartButtonListener(ActionListener a) {
start.addActionListener(a);
}
}
JFrame Class
public class HangmanGame extends JFrame {
private Home_Screen home;
private Level_Screen level;
private Win_Screen win;
private Lose_Screen lose;
private Play_Screen play;
public HangmanGame() {
super("Hangman");
home = new Home_Screen();
level = new Level_Screen();
win = new Win_Screen();
lose = new Lose_Screen();
play = new Play_Screen();
add(home);
setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
setSize(new Dimension(1920,1080));
setLayout(null);
setVisible(true);
}
public Home_Screen getHomeScreen() {
return home;
}
public Level_Screen getLevelScreen() {
return level;
}
public Win_Screen getWinScreen() {
return win;
}
public Lose_Screen getLoseScreen() {
return lose;
}
public Play_Screen getPlayScreen() {
return play;
}
}
Controller class
public class Controller {
private HangmanGame game;
public Controller() {
//game = g;
game = new HangmanGame();
game.getHomeScreen().addStartButtonListener(new startButtonListener());
}
class startButtonListener implements ActionListener{
@Override
public void actionPerformed(ActionEvent e) {
game.remove(game.getHomeScreen());
game.add(game.getLevelScreen());
}
}
}
I'm going to mess with you a little here, hang tight, I'm sure you'll appreciate it.
First, Swing is lazy. When ever you make a change to a component or a layout, you need to tell Swing that you'd like things to be updated.
This means, when you add or remove a component you'd, typically, call
revalidateandrepaint. Since you're not making a lot of use of layout manager, you could leaverevalidate.However. A simpler solution here would be to make use of a
CardLayout. This allows to you to "flip" between views as needed.One, glaring, issue I have with your approach, is the concept of responsibility. Who is actually responsible for what. You
Controlleris making a lot of decisions about what should happen, which, if you were using a controller properly might not be a bad idea, but, another idea might be to make each view some what independent and make use of an observer/delegate pattern instead.For example, you don't really care "how" the
Home_Screenstarts, only that it can. An observer would be interested in knowing when "start" occurs and take appropriate action.You've kind of done this with the
Controller, but I cringe at the notion that theControllerhas a deep understanding of the components, this is just me ;).Instead, I want things to be as dumb as I can make them, so if I need to change things, it's not a complete re-write each time.
Instead, in the following example, I've made use of a
CardLayouton theHangmanGameand supplied a "delegate" to theHome_Screenwhich tells when "start" occurs (I don't care how, just that it does) and then allowed theHangmanGameto control the navigation.This is generally a minor thing and you could argue that could use some kind of "navigation controller", but you'd need to do so in away which did expose the implementation details and ... it's a mess ... :P
Now, the initial load delay is expected of Swing, as it can take a few seconds for the Event Dispatching Thread to spin up and all the required initialisation to complete, but one part "might" be the loading of the image, although, before I started spending a lot of time worrying about, I'd focus on just making your game work