Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Loop to beginning with JFrame, accessing method in different class

Tags:

java

swing

jframe

So I'm revising a random number generator I made a while back and instead of making it in JOptionPane, I decided to try to create it in JFrame. The 2 problems I'm having is:

  1. I can't figure out how to access the number of attempts in class "Easy" to use for class "PlayAgain".

  2. How could I loop back to the beginning of the program and start at the Menu screen again if they decide to click btnPlayAgain? Creating a new instance of Menu does not work the way I want it to, as the Menu frame doesn't close after you choose a difficulty.

The code is for the 3 classes, Menu, Easy, and PlayAgain. I didn't include the code for buttons Medium or Hard as it is pretty much identical to Easy.

Menu

import java.awt.BorderLayout;
import java.awt.EventQueue;

import javax.swing.JFrame;
import javax.swing.JPanel;
import javax.swing.border.EmptyBorder;
import javax.swing.JLabel;
import javax.swing.SwingConstants;

import java.awt.Font;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;

import javax.swing.JButton;

public class Menu extends JFrame {

    private JPanel contentPane;
    public static Menu frame;
    public static Easy eFrame;
    public static Medium mFrame;
    public static Hard hFrame;

    /**
     * Launch the application.
     */
    public static void main(String[] args) {
        EventQueue.invokeLater(new Runnable() {
            public void run() {
                try {
                    frame = new Menu();
                    frame.setVisible(true);
                } catch (Exception e) {
                    e.printStackTrace();
                }
            }
        });
    }

    public Menu() {
        setResizable(false);
        setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
        setBounds(100, 100, 450, 149);
        contentPane = new JPanel();
        contentPane.setBorder(new EmptyBorder(5, 5, 5, 5));
        setContentPane(contentPane);
        contentPane.setLayout(null);

        JLabel lblSelectADifficulty = new JLabel("Select a difficulty");
        lblSelectADifficulty.setBounds(10, 49, 424, 19);
        lblSelectADifficulty.setFont(new Font("Tahoma", Font.PLAIN, 15));
        lblSelectADifficulty.setHorizontalAlignment(SwingConstants.CENTER);
        contentPane.add(lblSelectADifficulty);

        JLabel lblRandomNumberGuessing = new JLabel("Random Number Guessing Game");
        lblRandomNumberGuessing.setHorizontalAlignment(SwingConstants.CENTER);
        lblRandomNumberGuessing.setFont(new Font("Tahoma", Font.PLAIN, 22));
        lblRandomNumberGuessing.setBounds(10, 11, 424, 27);
        contentPane.add(lblRandomNumberGuessing);

        JButton btnEasy = new JButton("Easy (0-100)");
        btnEasy.setBounds(10, 79, 134, 23);
        contentPane.add(btnEasy);

        JButton btnMedium = new JButton("Medium (0-1000)");
        btnMedium.setBounds(155, 79, 134, 23);
        contentPane.add(btnMedium);

        JButton btnHard = new JButton("Hard (0-10000)");
        btnHard.setBounds(300, 79, 134, 23);
        contentPane.add(btnHard);

        btnEasy.addActionListener(new ActionListener() {
            public void actionPerformed(ActionEvent e) {
                frame.setVisible(false);

                EventQueue.invokeLater(new Runnable() {
                    public void run() {
                        try {
                            eFrame = new Easy();
                            eFrame.setVisible(true);
                        } catch (Exception e) {
                            e.printStackTrace();
                        }
                    }
                });
            }
        });
    }
}

Easy

import java.awt.BorderLayout;
import java.awt.EventQueue;

import javax.swing.JFrame;
import javax.swing.JPanel;
import javax.swing.border.EmptyBorder;
import javax.swing.JLabel;
import javax.swing.SwingConstants;

import java.awt.Font;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.util.Random;

import javax.swing.JTextField;
import javax.swing.JButton;


public class Easy extends JFrame {

    private JPanel contentPane;
    private JTextField textField;
    private int rand;
    public int attempts;

    public Easy() {
        attempts = 1;
        Random rnd = new Random();
        rand = rnd.nextInt(100 + 1);

        setResizable(false);
        setTitle("Take a guess");
        setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
        setBounds(100, 100, 300, 135);
        contentPane = new JPanel();
        contentPane.setBorder(new EmptyBorder(5, 5, 5, 5));
        setContentPane(contentPane);
        contentPane.setLayout(null);

        final JLabel lblGuessANumber = new JLabel("Guess a number between 0 - 100");
        lblGuessANumber.setBounds(10, 11, 274, 19);
        lblGuessANumber.setFont(new Font("Tahoma", Font.PLAIN, 15));
        lblGuessANumber.setHorizontalAlignment(SwingConstants.CENTER);
        contentPane.add(lblGuessANumber);

        textField = new JTextField();
        textField.setBounds(20, 41, 110, 20);
        contentPane.add(textField);
        textField.setColumns(10);

        final JButton btnGuess = new JButton("Guess");
        btnGuess.setBounds(164, 41, 110, 20);
        contentPane.add(btnGuess);

        final JLabel label = new JLabel("");
        label.setFont(new Font("Tahoma", Font.PLAIN, 12));
        label.setHorizontalAlignment(SwingConstants.CENTER);
        label.setBounds(10, 72, 274, 24);
        contentPane.add(label);

        btnGuess.addActionListener(new ActionListener() {
            public void actionPerformed(ActionEvent e) {
                if((Integer.parseInt(textField.getText())) >= 0 && (Integer.parseInt(textField.getText())) <= 100){
                    if((Integer.parseInt(textField.getText())) < rand){
                        label.setText("You guessed too low.");
                        System.out.println(rand);
                        attempts++;
                    }
                    else if((Integer.parseInt(textField.getText())) > rand){
                        label.setText("You guessed too high.");
                        attempts++;
                    }
                    else if((Integer.parseInt(textField.getText())) == rand){
                        dispose();
                        PlayAgain pl = new PlayAgain();
                        pl.setVisible(true);
                    }
                }
                else
                    label.setText("Please enter a valid input.");   
            }
        });
    }

    public int returnAttempts(){
        return attempts;
    }
}

PlayAgain

import java.awt.BorderLayout;
import java.awt.EventQueue;

import javax.swing.JFrame;
import javax.swing.JPanel;
import javax.swing.border.EmptyBorder;
import javax.swing.JLabel;
import javax.swing.SwingConstants;

import java.awt.Font;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;

import javax.swing.JButton;


public class PlayAgain extends JFrame {

    private JPanel contentPane;


    public PlayAgain() {
        setResizable(false);
        setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
        setBounds(100, 100, 240, 110);
        contentPane = new JPanel();
        contentPane.setBorder(new EmptyBorder(5, 5, 5, 5));
        setContentPane(contentPane);
        contentPane.setLayout(null);

        JLabel lblPlayAgain = new JLabel("Play Again?");
        lblPlayAgain.setFont(new Font("Tahoma", Font.PLAIN, 15));
        lblPlayAgain.setHorizontalAlignment(SwingConstants.CENTER);
        lblPlayAgain.setBounds(10, 27, 214, 23);
        contentPane.add(lblPlayAgain);

        JButton btnYes = new JButton("Yes");
        btnYes.setBounds(10, 49, 89, 23);
        contentPane.add(btnYes);

        JButton btnQuit = new JButton("Quit");
        btnQuit.setBounds(135, 49, 89, 23);
        contentPane.add(btnQuit);

        //Need to return number of attempts from Easy.java in lblYouGuessedCorrectly
        JLabel lblYouGuessedCorrectly = new JLabel("You guessed correctly! Attempts: ");
        lblYouGuessedCorrectly.setHorizontalAlignment(SwingConstants.CENTER);
        lblYouGuessedCorrectly.setBounds(10, 11, 214, 14);
        contentPane.add(lblYouGuessedCorrectly);

        btnYes.addActionListener(new ActionListener() {
            public void actionPerformed(ActionEvent e) {
                //Need to start the program over again, starting with from the Menu screen
            }
        });

        btnQuit.addActionListener(new ActionListener() {
            public void actionPerformed(ActionEvent e) {
                System.exit(0);
            }
        });
    }
}
like image 806
Auxive Avatar asked Jul 14 '26 18:07

Auxive


1 Answers

Suggestions:

  • You're creating an event-driven Swing GUI, and so you won't "loop" back to the beginning of your program as you would in a linear console program, because that's not how event driven programs work. Rather you'd simply display the menu view when needed, usually in response to some event such as within the ActionListener of a JButton and/or JMenuItem.
  • So add a reset JButton or JMenuItem or both, have them share the same ResetAction AbstractAction, and inside of that Action, re-show the menu view.
  • Side recommendation 1 (not related to your main problem): Don't use null layouts or setBounds as that will lead to rigid hard to debug and enhance GUI's that look good on one platform only.
  • Side recommendation 2: Don't code towards creation of JFrames but rather JPanel views as this will increase the flexibility of your program greatly, allowing you to swap JPanel views if need be using a CardLayout, or displaying views within a JFrame or JDialog or anywhere else they're needed.

For example using a CardLayout to swap JPanel views and a JOptionPane to get user input on re-starting:

import java.awt.BorderLayout;
import java.awt.CardLayout;
import java.awt.Font;
import java.awt.GridBagLayout;
import java.awt.GridLayout;
import java.awt.Window;
import java.awt.event.ActionEvent;

import javax.swing.AbstractAction;
import javax.swing.BorderFactory;
import javax.swing.Box;
import javax.swing.BoxLayout;
import javax.swing.JButton;
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.JOptionPane;
import javax.swing.JPanel;
import javax.swing.JTextField;
import javax.swing.SwingConstants;
import javax.swing.SwingUtilities;

@SuppressWarnings("serial")
public class Main2 extends JPanel {
    private MenuPanel menuPanel = new MenuPanel(this);
    private GamePanel gamePanel = new GamePanel(this);
    private CardLayout cardLayout = new CardLayout();

    public Main2() {
        setLayout(cardLayout);
        add(menuPanel, MenuPanel.NAME);
        add(gamePanel, GamePanel.NAME);
    }

    public void setDifficulty(Difficulty difficulty) {
        gamePanel.setDifficulty(difficulty);
    }

    public void showCard(String name) {
        cardLayout.show(Main2.this, name);
    }

    private static void createAndShowGui() {
        JFrame frame = new JFrame("Main2");
        frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
        frame.getContentPane().add(new Main2());
        frame.pack();
        frame.setLocationRelativeTo(null);
        frame.setVisible(true);
    }

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

}

@SuppressWarnings("serial")
class MenuPanel extends JPanel {
    public static final String NAME = "menu panel";
    private static final String MAIN_TITLE = "Random Number Guessing Game";
    private static final String SUB_TITLE = "Select a difficulty";
    private static final int GAP = 3;
    private static final float TITLE_SIZE = 20f;
    private static final float SUB_TITLE_SIZE = 16;

    private Main2 main2;

    public MenuPanel(Main2 main2) {
        this.main2 = main2;
        JLabel titleLabel = new JLabel(MAIN_TITLE, SwingConstants.CENTER);
        titleLabel.setFont(titleLabel.getFont().deriveFont(Font.BOLD, TITLE_SIZE));
        JPanel titlePanel = new JPanel();
        titlePanel.add(titleLabel);

        JLabel subTitleLabel = new JLabel(SUB_TITLE, SwingConstants.CENTER);
        subTitleLabel.setFont(subTitleLabel.getFont().deriveFont(Font.PLAIN, SUB_TITLE_SIZE));
        JPanel subTitlePanel = new JPanel();
        subTitlePanel.add(subTitleLabel);

        JPanel buttonPanel = new JPanel(new GridLayout(1, 0, GAP, GAP));
        for (Difficulty difficulty : Difficulty.values()) {
            buttonPanel.add(new JButton(new DifficultyAction(difficulty)));
        }

        setBorder(BorderFactory.createEmptyBorder(GAP, GAP, GAP, GAP));
        setLayout(new BoxLayout(this, BoxLayout.PAGE_AXIS));
        add(titlePanel);
        add(subTitlePanel);
        add(buttonPanel);
    }

    private class DifficultyAction extends AbstractAction {
        private Difficulty difficulty;

        public DifficultyAction(Difficulty difficulty) {
            this.difficulty = difficulty;
            String name = String.format("%s (0-%d)", difficulty.getText(), difficulty.getMaxValue());
            putValue(NAME, name);

            int mnemonic = (int) name.charAt(0);
            putValue(MNEMONIC_KEY, mnemonic);
        }

        @Override
        public void actionPerformed(ActionEvent e) {
            main2.setDifficulty(difficulty);
            main2.showCard(GamePanel.NAME);
        }
    }


}

enum Difficulty {
    EASY("Easy", 100), MEDIUM("Medium", 1000), HARD("Hard", 10000);
    private String text;
    private int maxValue;

    private Difficulty(String text, int maxValue) {
        this.text = text;
        this.maxValue = maxValue;
    }

    public String getText() {
        return text;
    }

    public int getMaxValue() {
        return maxValue;
    }
}

@SuppressWarnings("serial")
class GamePanel extends JPanel {
    public static final String NAME = "game panel";
    private String labelText = "Guess a number between 0 - ";
    private JLabel label = new JLabel(labelText + Difficulty.HARD.getMaxValue(), SwingConstants.CENTER);
    private Main2 main2;
    GuessAction guessAction = new GuessAction("Guess");
    private JTextField textField = new JTextField(10);
    private JButton guessButton = new JButton(guessAction);
    private boolean guessCorrect = false;

    private Difficulty difficulty;

    public GamePanel(Main2 main2) {
        this.main2 = main2;
        textField.setAction(guessAction);

        JPanel guessPanel = new JPanel();
        guessPanel.add(textField);
        guessPanel.add(Box.createHorizontalStrut(10));
        guessPanel.add(guessButton); 

        JPanel centerPanel = new JPanel(new GridBagLayout());
        centerPanel.add(guessPanel);

        setLayout(new BorderLayout());
        add(label, BorderLayout.PAGE_START);
        add(centerPanel, BorderLayout.CENTER);
    }

    public void setDifficulty(Difficulty difficulty) {
        this.difficulty = difficulty;
        label.setText(labelText + difficulty.getMaxValue());
    }

    private class GuessAction extends AbstractAction {
        private int attempts = 1;

        public GuessAction(String name) {
            super(name);
            int mnemonic = (int) name.charAt(0);
            putValue(MNEMONIC_KEY, mnemonic);
        }

        @Override
        public void actionPerformed(ActionEvent e) {
            // TODO use difficulty and all to check guesses, and reply to user

            // we'll just show the go back to main menu dialog
            guessCorrect = true; // TODO: Delete this later

            if (guessCorrect) {
                String message = "Attempts: " + attempts + ". Play Again?";
                String title = "You've Guessed Correctly!";
                int optionType = JOptionPane.YES_NO_OPTION;
                int selection = JOptionPane.showConfirmDialog(GamePanel.this, message, title, optionType);
                if (selection == JOptionPane.YES_OPTION) {
                    textField.setText("");
                    main2.showCard(MenuPanel.NAME);
                } else {
                    Window window = SwingUtilities.getWindowAncestor(GamePanel.this);
                    window.dispose();
                }
            }

        }
    }

}
like image 107
Hovercraft Full Of Eels Avatar answered Jul 16 '26 09:07

Hovercraft Full Of Eels