使用面板类中的按钮在框架类中调用ActionListener

时间:2016-01-03 19:08:39

标签: java swing class actionlistener

我上周末开始使用Java,我已经阅读了大部分基本内容。我试图将我的框架与主方法和框架中的面板分开,因此它们都在单独的类文件中。我在" Frame1"中调用ActionLister时遇到问题。在" TheGame"中有一个按钮(buttonBack)的类类。该按钮应该触发监听器,而监听器应该移除游戏面板并将mainMenu面板添加到frame1。我知道CardLayout更适合交换面板,但我想在我去做之前了解限制和变通方法" easy"方式,我觉得你学到的东西更多。

以下是我的一些代码:

主:

public class Main {


public static void main(String[] args){

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

    }
}

Frame1中:

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



}

的MainMenu:

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

TheGame:

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 个答案:

答案 0 :(得分:2)

最佳答案 - 使用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);
    }
}