Java 如何观察来自不同类的JButton?

Java 如何观察来自不同类的JButton?,java,swing,model-view-controller,jbutton,observer-pattern,Java,Swing,Model View Controller,Jbutton,Observer Pattern,因此,我有一个类扩展了JPanel,在构造函数中我添加了JButtons以及其他需要添加的内容。我还有一个MainFrame类,它是容器(JFrame),这个类将从名为FrameSwitcher(Controller)的类中获取一个参数,该类将评估单击了哪些按钮,并将信息传递给MainFrame 我做这件事有困难,我找不到合适的方法。我也希望保持JButtons私有和非静态 JPanel示例: public class MainMenu() { private JButton btnS

因此,我有一个类扩展了
JPanel
,在构造函数中我添加了
JButtons
以及其他需要添加的内容。我还有一个
MainFrame
类,它是容器(
JFrame
),这个类将从名为
FrameSwitcher
(Controller)的类中获取一个参数,该类将评估单击了哪些按钮,并将信息传递给
MainFrame

我做这件事有困难,我找不到合适的方法。我也希望保持JButtons私有和非静态

JPanel示例:

public class MainMenu() {

    private JButton btnSinglePlayer, btnMultiPlayer;

    public MainMenu() {
        setLayout(null);

        btnSinglePlayer = new JButton("singlePlayer");
        btnSinglePlayer.setBounds(320, 25, 275, 130);
        add(btnSinglePlayer);

        btnMultiPlayer = new JButton("MultiPlayer");
        btnMultiPlayer.setBounds(320, 170 , 275, 130);
        add(btnMultiPlayer);

   }
}
帧切换器:

public class FrameSwitcher implements panelListener { // panelListener is an interface defined else where.

    public FrameSwitcher(MainFrame frame) {
        // This is irrelevant to the question. 
    } 

    @Override
    public void gamePanel() {
        System.out.println("GamePanel Event: Recieved");
    }
    @Override
    public void mainMenu() {
        System.out.println("mainMenu Event: Recieved");
    }
    @Override
    public void scoreBoardPanel() {
        System.out.println("scoreBoardPanel Event: Recieved");
    }
}
然后我的主机:

public class MainFrame extends JFrame implements ActionListener {

    private PanelListener panelListener;
    private JFrame mainContainer = new JFrame("Game");
    private JPanel mainMenu = new MainMenu();

    public void start() {
         mainContainer(mainMenu);
    }

    public MainFrame(JPanel frame) {
        mainContainer.getContentPane().add(frame);
        mainContainer.pack();
        // Other methods to initialize the frame
        return mainContainer;
     }

    public void switchFrames(PanelListener panelListener) {
        this.panelListener = panelListener; // PanelListener is an interface.
    }

    public void actionPerformed(ActionEvent e) {

        JButton source = (JButton)e.getsource();

        if(source == MainMenu.btnSinglePlayer) {
            if(panelListener != null) {
                System.out.println("Recieved the event approriately.");
            }
        }
    }
}

在本例中,它进行编译,但不执行它应该执行的操作。另一件事是,我目前将JButtons设置为公共和静态,我不希望这样

首先,您必须创建一个像这样的ActionListener

class MyActionListener implements ActionListener{
    public void actionPerformed(ActionEvent ae){
        //do your stuff
    }
}
然后打电话,

yourButton.addActionListener(new MyActionListener());

在您的
main菜单
类中,您需要添加一些相关方可以注册的侦听器,以便在发生某些事件时通知他们

最简单的解决方案是提供一个委派给每个按钮的
addActionListener
方法。但是,这可能会暴露应用程序中未公开的部分(侦听器现在可以直接访问
JButton
,并且可以对其执行各种讨厌的操作)

一个更好的解决方案是创建一个类似于
MainMenuListener
的东西,它的方法类似于
startingleplayer
startMultiPlayer

然后在
main菜单
类中提供一个
add/removeMainMenuListener
方法

然后,每个按钮都会注册自己的
actionListener
,并触发相应的菜单侦听器事件

import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.util.EventListener;
import javax.swing.JButton;
import javax.swing.JPanel;

public class MainMenu extends JPanel {

    private JButton btnSinglePlayer, btnMultiPlayer;

    public MainMenu() {
        setLayout(null);

        btnSinglePlayer = new JButton("singlePlayer");
        btnSinglePlayer.setBounds(320, 25, 275, 130);
        add(btnSinglePlayer);
        btnSinglePlayer.addActionListener(new ActionListener() {
            @Override
            public void actionPerformed(ActionEvent e) {
                fireStartSinglePlayer();
            }
        });

        btnMultiPlayer = new JButton("MultiPlayer");
        btnMultiPlayer.setBounds(320, 170, 275, 130);
        add(btnMultiPlayer);
        btnMultiPlayer.addActionListener(new ActionListener() {
            @Override
            public void actionPerformed(ActionEvent e) {
                fireStartMultiPlayer();
            }
        });

    }

    public void addMainMenuListener(MainMenuListener listener) {
        listenerList.add(MainMenuListener.class, listener);
    }

    public void removeMainMenuListener(MainMenuListener listener) {
        listenerList.remove(MainMenuListener.class, listener);
    }

    public void fireStartSinglePlayer() {
        MainMenuListener[] listeners = listenerList.getListeners(MainMenuListener.class);
        if (listeners != null && listeners.length > 0) {
            for (MainMenuListener listener : listeners) {
                listener.startSinglePlayer();
            }
        }
    }

    public void fireStartMultiPlayer() {
        MainMenuListener[] listeners = listenerList.getListeners(MainMenuListener.class);
        if (listeners != null && listeners.length > 0) {
            for (MainMenuListener listener : listeners) {
                listener.startMultiPlayer();
            }
        }
    }

    public interface MainMenuListener extends EventListener {

        public void startSinglePlayer();
        public void startMultiPlayer();

    }

}

actionPerformed
ActionListener
接口的一种方法,您的
大型机
类目前未实现该接口。那么,您期望得到什么呢?整个设计都很糟糕。回到基础。在FrameSwitcher类中实现ActionListener,并在MainMenu类中为每个按钮添加一个ActionListener(FrameSwitcher)。这不会迫使我在实际的MainMenu类中编写ActionListener吗?如果没有,它将如何允许我访问按钮从另一个类这样做呢?我假设MyActionListener将包含一个数组?中的JButtons,然后我将它们通过FrameSwitcher传递,FrameSwitcher将在大型机上返回必要的数据?您的应用程序的架构非常奇怪--快速阅读后,我无法真正理解您在谈论什么,或者您试图实现什么。你能简单地描述一下你想让你的应用程序完成什么,我会建议一个简化的设计吗?当然,这就是我的应用程序的GUI。这意味着有一个主菜单,将有四个按钮,单人,多人,记分牌和退出。每个按钮将初始化不同的内容。此外,根据单击的按钮,某些逻辑将随之出现,例如,单击singleplayer,然后调用singleplayer逻辑,游戏将继续。此外,在这些面板中,像单人游戏一样,会有一个JMenu栏,可以带您进入主菜单或记分板。