为什么 ActionListener 在控制器中不起作用?
Why doesn't ActionListener work in the controller?
这个 post 是 的延续 在我的软件中基本上是基于 CardLayout
面板。现在我想从 cardLayout
之外更改面板。在提供的 link 中,我得到了帮助,并且成功了。现在我在我的软件中添加了一个控制器,它位于内部面板 (CardLayout
) 和外部面板之间。在外部面板 (leftBar
) 中,我有一个按钮,如果它的 actionListener
位于 class 内部,则它可以正常工作并打开选择的 CardLayout
内部面板。但是,如果我将 ActionListener
带入控制器,它就不起作用了。没有出现错误。
这是我的示例代码:
基地:
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
。我在控制器中调用该方法并给它一个 class。但它不起作用。但是,如果 ACtionListener
位于 LeftBar class(内联)中,则 ACtionListener
有效。
知道如何解决吗?
您正在创建 LeftBar
的两个实例,一个在 Base
构造函数中,它被添加到屏幕...
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
附加到屏幕上永远不可见的按钮
我要做的第一件事是开始解耦你的代码,而不是传递你的 class 实例,你需要建立一系列你的控制器和视图可以同意的契约,例如,您的 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");
}
}
}
}
现在,就个人而言,这只是对您的代码进行一些修改,就个人而言,我更希望有一个与单个 view/contract 交互的控制器,它使它变得更加简单...
这个 post 是 CardLayout
面板。现在我想从 cardLayout
之外更改面板。在提供的 link 中,我得到了帮助,并且成功了。现在我在我的软件中添加了一个控制器,它位于内部面板 (CardLayout
) 和外部面板之间。在外部面板 (leftBar
) 中,我有一个按钮,如果它的 actionListener
位于 class 内部,则它可以正常工作并打开选择的 CardLayout
内部面板。但是,如果我将 ActionListener
带入控制器,它就不起作用了。没有出现错误。
这是我的示例代码: 基地:
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
。我在控制器中调用该方法并给它一个 class。但它不起作用。但是,如果 ACtionListener
位于 LeftBar class(内联)中,则 ACtionListener
有效。
知道如何解决吗?
您正在创建 LeftBar
的两个实例,一个在 Base
构造函数中,它被添加到屏幕...
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
附加到屏幕上永远不可见的按钮
我要做的第一件事是开始解耦你的代码,而不是传递你的 class 实例,你需要建立一系列你的控制器和视图可以同意的契约,例如,您的 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");
}
}
}
}
现在,就个人而言,这只是对您的代码进行一些修改,就个人而言,我更希望有一个与单个 view/contract 交互的控制器,它使它变得更加简单...