有 Java 编程相关的问题?

你可以在下面搜索框中键入要查询的问题!

java使用panel类中的button调用frame类中的ActionListener

我上周末开始编写CodigJava,我已经阅读了大部分基本内容。我试图将我的框架与主方法分离,并将面板与框架分离,以便它们都位于单独的类文件中。我在调用“框架1”类中的ActionLister时遇到问题,在“TheGame”类中使用按钮(buttonBack)。该按钮应触发监听器,监听器应依次移除游戏面板并将主菜单面板添加到frame1。我知道CardLayout更适合交换面板,但我想先了解一下限制和解决方法,然后再以“简单”的方式进行交换,我觉得这样可以学到更多

以下是我的一些代码:

主要内容:

public class Main {


public static void main(String[] args){

    Frame1 frame1 = new Frame1();
    frame1.frame1();

    }
}

框架1:

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

import javax.swing.JDialog;
import javax.swing.JFrame;
import javax.swing.JMenu;
import javax.swing.JMenuBar;
import javax.swing.JMenuItem;
import javax.swing.JOptionPane;


class Frame1 {

private JFrame frame1 = new JFrame("Name");

public void frame1() {

    TheGame theGame = new TheGame();
    MainMenu mainMenu = new MainMenu();

// Frame options
    frame1.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
    frame1.setLocationRelativeTo(null);


// Creating a top menu
    JMenuBar menubar = new JMenuBar();
    frame1.setJMenuBar(menubar);

    JMenu file = new JMenu("File");
    menubar.add(file);

    JMenu help = new JMenu("Help");
    menubar.add(help);

    JMenuItem exit = new JMenuItem("Exit");
    file.add(exit);

    JMenuItem about = new JMenuItem("About");
    help.add(about);


// Creating action for the menuitem "exit".
class exitaction implements ActionListener{
    public void actionPerformed (ActionEvent e){
        System.exit(0);
    }
}
exit.addActionListener(new exitaction());


// Creating listener for the menuitem "about".
    class aboutaction implements ActionListener{
        public void actionPerformed (ActionEvent e){
            JDialog dialogabout = new JDialog();
            JOptionPane.showMessageDialog(dialogabout, "Made by: ");
        }
    }
    about.addActionListener(new aboutaction());


// Add the panels, pack and setVisible
    theGame.theGame();
    mainMenu.mainMenu();
    frame1.add(theGame.getGUI());


// This is the ActionListener i have trouble connecting with the buttonBack in the "theGame" class
    class Action implements ActionListener{
        public void actionPerformed (ActionEvent e){
            frame1.remove(theGame.getGUI());
            frame1.add(MainMenu.getGUI());
        }
    }

    frame1.pack();
    frame1.setVisible(true);



    }

    public JFrame getGUI() {
        return frame1;
    }



}

主菜单:

import java.awt.Dimension;
import java.awt.GridBagConstraints;
import java.awt.GridBagLayout;
import java.awt.Insets;

import javax.swing.JButton;
import javax.swing.JComponent;
import javax.swing.JLabel;
import javax.swing.JPanel;

class MainMenu {

private JPanel mainMenu = new JPanel (new GridBagLayout());

public void mainMenu() {

// Using the GridBagLayout therefore creating the constraints "grid"
    GridBagConstraints grid = new GridBagConstraints();

// Adjusting grid insets
    grid.insets = new Insets(10, 10, 10, 10);


// Creating Label
    JLabel introduction = new JLabel("Name");
    grid.gridx = 1;
    grid.gridy = 3;
    mainMenu.add(introduction, grid);


// Creating buttons Start Game, Highscore and Exit Game
    JButton buttonNewGame = new JButton("New Game");
    buttonNewGame.setPreferredSize(new Dimension(200, 50));
    grid.gridx = 1;
    grid.gridy = 5;
    mainMenu.add(buttonNewGame, grid);

    JButton buttonHighscore = new JButton("Highscore");
    buttonHighscore.setPreferredSize(new Dimension(200, 50));
    grid.gridx = 1;
    grid.gridy = 6;
    mainMenu.add(buttonHighscore, grid);

    JButton buttonExit = new JButton("Exit Game");
    buttonExit.setPreferredSize(new Dimension(200, 50));
    grid.gridx = 1;
    grid.gridy = 7;
    mainMenu.add(buttonExit, grid);


    }


    public JComponent getGUI() {
        return mainMenu;
    }
}

游戏:

import java.awt.GridBagConstraints;
import java.awt.GridBagLayout;
import java.awt.Insets;

import javax.swing.JButton;
import javax.swing.JComponent;
import javax.swing.JLabel;
import javax.swing.JPanel;


class TheGame {

private JPanel theGame = new JPanel (new GridBagLayout());

public void  theGame() {

// Using the GridBagLayout therefore creating the constraints "grid"
    GridBagConstraints grid = new GridBagConstraints();

// Adjusting grid insets
    grid.insets = new Insets(10, 10, 10, 10);

// Creating a label
    JLabel label1 = new JLabel("Press the BACK button to go back to Main Menu");
    label1.setVisible(true);
    grid.gridx = 1;
    grid.gridy = 0;
    theGame.add(label1,grid);

// Creating BACK button
    JButton buttonBack = new JButton("BACK");
    buttonBack.setVisible(true);
    grid.gridx = 1;
    grid.gridy = 1;
    buttonBack.addActionListener(new --); // This is the button i want to connect with the ActionListener on Frame1 class
    theGame.add(buttonBack, grid);

    }


    public JComponent getGUI() {
        return theGame;
    }


}

我曾尝试将ActionListener移到方法之外、Main内部,声明它是静态的,但无论如何都无法调用它。我也看过其他类似的帖子:Add an actionListener to a JButton from another class,但还没能在我的代码中实现它

感谢您的帮助


共 (1) 个答案

  1. # 1 楼答案

    最佳答案是使用MVC(模型-视图-控制器)结构(和CardLayout)交换视图。如果您不想这样做,那么您的侦听器应该有一个对进行交换的容器的引用,这样侦听器就可以通知这个容器应该进行交换。然后容器将调用自己的代码来进行交换。要做到这一点,您需要将引用(包括对主GUI的引用)传递到任何需要的地方。这可能会变得一团糟,这就是为什么MVC工作更多,从长远来看,连接/复杂性更少通常更好

    旁注:不要将JDialog传递到JOptionPane,因为JOptionPane是专门的JDialog,并且不应该让顶级窗口显示顶级窗口。相反,请交一张JPanel

    例如:

    import java.awt.CardLayout;
    import java.awt.Dimension;
    import java.awt.event.ActionEvent;
    import javax.swing.*;
    
    public class PassRef {
    
        public static void main(String[] args) {
            SwingUtilities.invokeLater(() -> {
                createAndShowGui();
            });
        }
    
        private static void createAndShowGui() {
            MyMain mainPanel = new MyMain();
            JFrame frame = new JFrame("Pass Reference");
            frame.setDefaultCloseOperation(JFrame.DISPOSE_ON_CLOSE);
            frame.add(mainPanel);
            frame.pack();
            frame.setLocationByPlatform(true);
            frame.setVisible(true);
        }
    }
    
    class MyMain extends JPanel {
        private static final int PREF_W = 600;
        private static final int PREF_H = 450;
        private CardLayout cardLayout = new CardLayout();
        private MenuView menuView = new MenuView(this);
        private ActionView1 actionView1 = new ActionView1(this);
    
        public MyMain() {
            setLayout(cardLayout);
            add(menuView, MenuView.NAME);
            add(actionView1, ActionView1.NAME);
        }
    
        @Override
        public Dimension getPreferredSize() {
            if (isPreferredSizeSet()) {
                return super.getPreferredSize();
            } else {
                return new Dimension(PREF_W, PREF_H);
            }
        }
    
        public void showCard(String key) {
            cardLayout.show(this, key);
            // or swap by hand if you don't want to use CardLayout
            // but remember to revalidate and repaint whenever doing it by hand
        }
    }
    
    class MenuView extends JPanel {
        public static final String NAME = "Menu View";
    
        public MenuView(MyMain myMain) {
            setName(NAME);
            setBorder(BorderFactory.createTitledBorder("Menu"));
            add(new JButton(new GoToAction("Action 1", ActionView1.NAME, myMain)));
        }
    
    }
    
    class ActionView1 extends JPanel {
        public static final String NAME = "Action View 1";
    
        public ActionView1(MyMain myMain) {
            setName(NAME);
            setBorder(BorderFactory.createTitledBorder(NAME));
            add(new JButton(new GoToAction("Main Menu", MenuView.NAME, myMain)));
        }
    
    }
    
    class GoToAction extends AbstractAction {
        private String key;
        private MyMain myMain;
    
        public GoToAction(String name, String key, MyMain myMain) {
            super(name);
            this.key = key;
            this.myMain = myMain;
        }
    
        @Override
        public void actionPerformed(ActionEvent e) {
            myMain.showCard(key);
        }
    }