在内部侦听器 class 中将面板添加到框架?

add panel to frame in inner listener class?

class MemberBook extends Frame {
        MenuBar     mb;
        Menu        menu;
        MenuItem    miReg, miList, miExit;

        MemberBook() {
                super();

                mb      = new MenuBar();
                menu    = new Menu("Menu");
                miReg   = new MenuItem("Register");
                miList  = new MenuItem("List");
                miExit  = new MenuItem("Exit");

                menu.add(miReg);
                menu.add(miList);
                menu.addSeparator();
                menu.add(miExit);

                mb.add(menu);
                setMenuBar(mb);

                MenuHandler handler = new MenuHandler(this);
                miReg.addActionListener(handler);
                miList.addActionListener(handler);
                miExit.addActionListener(handler);

                setSize(300, 500);
                setVisible(true);
        }

        public static void main(String args[]) {
                MemberBook win = new MemberBook();
        }

        class MenuHandler implements ActionListener {
                MemberBook frame;

                // I want to add panel to outer class but I don't know 
                // other way to do it so, get _frame in constructor
                MenuHandler(MemberBook _frame) {
                        frame = _frame;
                }

                // show different panels for each menu
                public void actionPerformed(ActionEvent e) {
                        String command = e.getActionCommand();

                        if (command.equals("Register")) {
                                RegisterPanel panel = new RegisterPanel();
                                frame.add(panel, "Center");
                        }
                        // else if ...
                }
        }

        // predefined panel to show in MemberBook frame 
        class RegisterPanel extends Panel {
        }                   
}

我想制作预定义的会员注册面板、会员列表面板(您可以查看会员列表和编辑会员)并在选择菜单时显示,但当我选择注册菜单时RegisterPanel 不显示。我不知道在内部 Listener class 中将面板添加到框架的其他方法,因此将框架转移到 Listener 构造函数。

所以,基本答案是,使用 CardLayout,请参阅 How to Use CardLayout 了解更多详情。

import java.awt.CardLayout;
import java.awt.Color;
import java.awt.EventQueue;
import java.awt.GridBagLayout;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.JMenu;
import javax.swing.JMenuBar;
import javax.swing.JMenuItem;
import javax.swing.JPanel;
import javax.swing.border.EmptyBorder;

public class MemberBook {

    public static void main(String[] args) {
        new MemberBook();
    }

    private JMenuBar mb;
    private JMenu menu;
    private JMenuItem miReg, miList, miExit;

    public MemberBook() {
        EventQueue.invokeLater(new Runnable() {
            @Override
            public void run() {

                mb = new JMenuBar();
                menu = new JMenu("Menu");
                miReg = new JMenuItem("Register");
                miList = new JMenuItem("List");
                miExit = new JMenuItem("Exit");

                menu.add(miReg);
                menu.add(miList);
                menu.addSeparator();
                menu.add(miExit);

                mb.add(menu);

                MainPane mainPane = new MainPane();

                MenuHandler handler = new MenuHandler(mainPane);
                miReg.addActionListener(handler);
                miList.addActionListener(handler);
                miExit.addActionListener(handler);

                JFrame frame = new JFrame();
                frame.setJMenuBar(mb);
                frame.add(mainPane);
                frame.pack();
                frame.setLocationRelativeTo(null);
                frame.setVisible(true);
            }
        });
    }

    public interface MemberBookController {
        public void registerUser();
    }

    public class MainPane extends JPanel implements MemberBookController {

        private CardLayout cardLayout;

        public MainPane() {
            cardLayout = new CardLayout();
            setLayout(cardLayout);

            add(new WelcomePane(), "welcome");
            add(new RegisterPanel(), "register");

            cardLayout.show(this, "welcome");
        }

        @Override
        public void registerUser() {
            cardLayout.show(this, "register");
        }

    }

    public class MenuHandler implements ActionListener {

        private MemberBookController controller;

        // I want to add panel to outer class but I don't know 
        // other way to do it so, get _frame in constructor
        MenuHandler(MemberBookController controller) {
            this.controller = controller;
        }

        // show different panels for each menu
        public void actionPerformed(ActionEvent e) {
            String command = e.getActionCommand();

            if (command.equals("Register")) {
                controller.registerUser();
            }
            // else if ...
        }
    }

    public class WelcomePane extends JPanel {

        public WelcomePane() {
            setBorder(new EmptyBorder(16, 16, 16, 16));
            setLayout(new GridBagLayout());
            add(new JLabel("Welcome"));
            setBackground(Color.BLUE);
        }

    }

    // predefined panel to show in MemberBook frame 
    public class RegisterPanel extends JPanel {

        public RegisterPanel() {
            setBorder(new EmptyBorder(16, 16, 16, 16));
            setLayout(new GridBagLayout());
            add(new JLabel("Register"));
            setBackground(Color.RED);
        }

    }
}

此示例还演示了如何使用 interface 来提供“信息隐藏”。 MenuHandler 并不真正需要访问框架或基本窗格,事实上,它不应该关心。它需要做的就是告诉感兴趣的各方已经发生了一些动作。

我可能会考虑使用 Action API 来执行此操作,因此您可以将功能隔离得更多一些,请参阅 How to Use Actions 了解更多详细信息。