繁体   English   中英

为什么ActionListener在控制器中不起作用?

[英]Why doesn't ActionListener work in the controller?

这篇文章是这篇文章的继续 我的软件基本上是基于CardLayout面板的。 现在,我想从cardLayout外部更改面板。 在提供的链接中,我得到了帮助,并且可以正常工作。 现在,我在软件中添加了一个控制器,该控制器位于内部面板( CardLayout )和外部面板之间。 在外部面板( leftBar )中,有一个按钮,如果它的actionListener位于该类的内部,则它可以正常工作,并打开CardLayout的选定内部面板。 但是,如果我将ActionListener放入控制器,它将无法正常工作。 没有错误出现。

这是我的示例代码:BASE:

public class Base {
        JFrame frame = new JFrame("Panel");
        BorderLayout bl = new BorderLayout();

    public Base(){
        MainPanel mainPanel = new MainPanel();
        LeftBar leftBar = new LeftBar(mainPanel);
        frame.setLayout(bl);
        frame.setSize(800, 600);
        frame.add(leftBar, BorderLayout.WEST);
        frame.add(mainPanel, BorderLayout.CENTER);

        frame.setLocationRelativeTo(null);
        frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
        frame.setVisible(true);
    }
    public static void main(String[] args) throws IOException {
        new Base();
    }
}

MainPanel(CardLAyout基座)

public class MainPanel extends JPanel {
    private CardLayout cl = new CardLayout();
    private JPanel panelHolder = new JPanel(cl);

    public MainPanel(){
        FirstPage firstPage = new FirstPage(this);
        SecondPage secondPage = new SecondPage(this);
        LeftBar leftBar = new LeftBar(this);

        Controller controller = new Controller(secondPage, leftBar, this);
        setLayout(new GridLayout(0,1));

        panelHolder.add(firstPage, "firstPage");
        panelHolder.add(secondPage, "secondPage");

        cl.show(panelHolder, "firstPage");
        add(panelHolder);

    }
    public void showPanel(String panelIdentifier){
        cl.show(panelHolder, panelIdentifier);
    }
}

左栏

public class LeftBar extends JPanel{
    private JButton button;
    private MainPanel mainPanel;

    public LeftBar(MainPanel mainPanel){
        this.mainPanel = mainPanel;

        setPreferredSize(new Dimension(200, 40));
        setLayout(new BorderLayout());
        setBackground(Color.black);

        button = new JButton("Show Second Page");


       add(button, BorderLayout.NORTH);
    }
    public void addPageListener(ActionListener listenForButton){
        button.addActionListener(listenForButton);
    }
}

第二页:

public class SecondPage extends JPanel{
    MainPanel mainPanel;
    JButton button;
    public SecondPage(MainPanel mainPanel){
       this.mainPanel = mainPanel;
        setBackground(Color.white);
       add(new JLabel("This is second page"));
    }
}

第一页:

public class FirstPage extends JPanel {
    MainPanel mainPanel;
    JButton button;

    public FirstPage(MainPanel mainPanel) {
       this.mainPanel = mainPanel;
       setBackground(Color.GRAY);

       button = new JButton("Show page");
       button.addActionListener(new ActionListener(){
           @Override
           public void actionPerformed(ActionEvent ae) {
               mainPanel.showPanel("secondPage");
           }

       });

       add(button);
    }
}

和控制器:

public class Controller {
    private SecondPage secondPage;
    private LeftBar leftBar;
    private MainPanel mainPanel;
    public Controller(SecondPage secondPage, LeftBar leftBar, MainPanel mainPanel){
        this.secondPage=secondPage;
        this.leftBar=leftBar;
        this.mainPanel=mainPanel;

        this.leftBar.addPageListener(new ButtonListener());
    }

    class ButtonListener implements ActionListener{
        @Override
        public void actionPerformed(ActionEvent ae) {
            System.out.println("Works");
            mainPanel.showPanel("secondPage");
        }
    }
}

如您在LeftBar中看到的,我有一个用作actionListener的按钮方法。 然后在控制器中调用该方法并为其提供一个类。 但它不起作用。 但是,如果ACtionListener位于LeftBar类(内联)中,则它可以工作。

知道如何解决吗?

您将在Base构造函数中创建两个LeftBar实例,将其添加到屏幕中。

public Base() {
    MainPanel mainPanel = new MainPanel();
    LeftBar leftBar = new LeftBar(mainPanel);
    frame.setLayout(bl);
    frame.setSize(800, 600);
    frame.add(leftBar, BorderLayout.WEST);
    frame.add(mainPanel, BorderLayout.CENTER);

还有MainPanel构造函数中的一个传递给控制器​​...

public class MainPanel extends JPanel {

    private CardLayout cl = new CardLayout();
    private JPanel panelHolder = new JPanel(cl);

    public MainPanel() {
        FirstPage firstPage = new FirstPage(this);
        SecondPage secondPage = new SecondPage(this);
        LeftBar leftBar = new LeftBar(this);

这意味着控制器将ActionListener附加到在屏幕上永远不可见的按钮

我要做的第一件事是开始分离代码,而不是传递类的实例,您需要建立一系列控制器和视图可以同意的MainPanel ,例如, MainPanel应该提供一种切换视图的方法,您的LeftBar应该在用户想要切换视图时提供通知

例如...

public interface Pageable {

    public void showView(String name);

}

public interface Navigatable {

    public void addActionListener(ActionListener listener);

}

然后您的主视图将实现Pageable接口

public class MainPanel extends JPanel implements Pageable {
    //...
    @Override
    public void showView(String name) {
        cl.show(panelHolder, name);
    }

您的LeftBar将实现Navigatable接口

public class LeftBar extends JPanel implements Navigatable {
    //...
    @Override
    public void addActionListener(ActionListener listener) {
        button.addActionListener(listener);
    }

这只是定义了任何实现的合同功能,您的控制器不应该关心其他任何事情(也不应该允许它执行原本不希望做的事情,例如从您的视图中删除顽皮的控制器中的所有组件)

然后,您的控制器仅负责管理接口之间的合同...

public class Controller {

    private final Navigatable navigatable;
    private final Pageable pageable;

    public Controller(Navigatable navigatable, Pageable pageable) {
        this.navigatable = navigatable;
        this.pageable = pageable;

        navigatable.addActionListener(new ButtonListener());
    }

    class ButtonListener implements ActionListener {

        @Override
        public void actionPerformed(ActionEvent ae) {
            pageable.showView("secondPage");
        }
    }
}

例如...

import java.awt.BorderLayout;
import java.awt.CardLayout;
import java.awt.Color;
import java.awt.Dimension;
import java.awt.GridLayout;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.io.IOException;
import javax.swing.JButton;
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.JPanel;

public class Base {

    JFrame frame = new JFrame("Panel");
    BorderLayout bl = new BorderLayout();

    public Base() {
        MainPanel mainPanel = new MainPanel();
        LeftBar leftBar = new LeftBar(mainPanel);
        frame.setLayout(bl);
        frame.setSize(800, 600);
        frame.add(leftBar, BorderLayout.WEST);
        frame.add(mainPanel, BorderLayout.CENTER);

        Controller controller = new Controller(leftBar, mainPanel);

        frame.setLocationRelativeTo(null);
        frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
        frame.setVisible(true);
    }

    public static void main(String[] args) throws IOException {
        new Base();
    }

    public interface Pageable {

        public void showView(String name);

    }

    public interface Navigatable {

        public void addActionListener(ActionListener listener);

    }

    public class MainPanel extends JPanel implements Pageable {

        private CardLayout cl = new CardLayout();
        private JPanel panelHolder = new JPanel(cl);

        public MainPanel() {
            FirstPage firstPage = new FirstPage(this);
            SecondPage secondPage = new SecondPage(this);
            setLayout(new GridLayout(0, 1));

            panelHolder.add(firstPage, "firstPage");
            panelHolder.add(secondPage, "secondPage");

            cl.show(panelHolder, "firstPage");
            add(panelHolder);

        }

        public void showPanel(String panelIdentifier) {
            cl.show(panelHolder, panelIdentifier);
        }

        @Override
        public void showView(String name) {
            cl.show(panelHolder, name);
        }
    }

    public class LeftBar extends JPanel implements Navigatable {

        private JButton button;
        private MainPanel mainPanel;

        public LeftBar(MainPanel mainPanel) {
            this.mainPanel = mainPanel;

            setPreferredSize(new Dimension(200, 40));
            setLayout(new BorderLayout());
            setBackground(Color.black);

            button = new JButton("Show Second Page");

            add(button, BorderLayout.NORTH);
        }

        @Override
        public void addActionListener(ActionListener listener) {
            button.addActionListener(listener);
        }
    }

    public class SecondPage extends JPanel {

        MainPanel mainPanel;
        JButton button;

        public SecondPage(MainPanel mainPanel) {
            this.mainPanel = mainPanel;
            setBackground(Color.white);
            add(new JLabel("This is second page"));
        }
    }

    public class FirstPage extends JPanel {

        MainPanel mainPanel;
        JButton button;

        public FirstPage(MainPanel mainPanel) {
            this.mainPanel = mainPanel;
            setBackground(Color.GRAY);

            button = new JButton("Show page");
            button.addActionListener(new ActionListener() {
                @Override
                public void actionPerformed(ActionEvent ae) {
                    mainPanel.showPanel("secondPage");
                }

            });

            add(button);
        }
    }

    public class Controller {

        private final Navigatable navigatable;
        private final Pageable pageable;

        public Controller(Navigatable navigatable, Pageable pageable) {
            this.navigatable = navigatable;
            this.pageable = pageable;

            navigatable.addActionListener(new ButtonListener());
        }

        class ButtonListener implements ActionListener {

            @Override
            public void actionPerformed(ActionEvent ae) {
                pageable.showView("secondPage");
            }
        }
    }
}

现在,就个人而言,这只是围绕您的代码的一些小技巧,就个人而言,我更希望有一个与单个视图/合同进行交互的控制器,这使它非常简单...

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM