java - 循环以 JFrame 开始,访问不同类中的方法

标签 java swing jframe

因此,我正在修改前一段时间制作的随机数生成器,而不是在 JOptionPane 中制作它,我决定尝试在 JFrame 中创建它。我遇到的两个问题是:

  1. 我不知道如何访问“Easy”类中用于“PlayAgain”类的尝试次数。

  2. 如果他们决定单击 btnPlayAgain,我如何循环回到程序开头并再次从菜单屏幕开始?创建 Menu 的新实例无法按我希望的方式工作,因为在您选择难度后 Menu 框架不会关闭。

该代码适用于 3 个类,Menu、Easy 和 PlayAgain。我没有包含按钮 Medium 或 Hard 的代码,因为它们与 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 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();
                        }
                    }
                });
            }
        });
    }
}

简单

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;
    }
}

再玩一次

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);
            }
        });
    }
}

最佳答案

建议:

  • 您正在创建一个事件驱动的 Swing GUI,因此您不会像在线性控制台程序中那样“循环”回到程序的开头,因为这不是事件驱动程序的工作方式。相反,您只需在需要时显示菜单 View ,通常是为了响应某些事件,例如在 JButton 和/或 JMenuItem 的 ActionListener 中。
  • 因此添加一个 reset JButton 或 JMenuItem 或两者,让它们共享相同的 ResetAction AbstractAction,并在该 Action 内部重新显示菜单 View 。
  • 侧面建议 1(与您的主要问题无关):不要使用空布局或 setBounds,因为这会导致难以调试和增强仅在一个平台上看起来不错的 GUI。
  • 侧面建议 2:不要为创建 JFrames 而编写 JPanel View ,因为这会大大增加程序的灵 active ,允许您在需要时交换 JPanel View 使用 CardLayout,或在 JFrame 或JDialog 或任何其他需要它们的地方。

例如,使用 CardLayout 交换 JPanel View ,使用 JOptionPane 在重新启动时获取用户输入:

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();
                }
            }

        }
    }

}

关于java - 循环以 JFrame 开始,访问不同类中的方法,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/34161659/

相关文章:

java - JDICplus在Java中嵌入IE的问题

java - 无法在 JFrame 上绘图

java - JFrame 滚动条和 Canvas

java - 在 JFrame 内对齐主动渲染的 JPanel

java - Setter 和 getter 不工作

java - 如何为多种屏幕尺寸设置操作栏和标题窗口文本大小?

java - 如何使用 Swing 以编程方式制作这种网格?

java - 深度复制,JUnit 测试 Java

java - 删除elasticsearch中的自动化记录

java - 全屏独占模式