问题描述
此文章是基本上,我的软件中是基于CardLayout
面板的.现在,我想从cardLayout
外部更改面板.在提供的链接中,我得到了帮助,并且可以正常工作.现在,我在软件中添加了一个控制器,该控制器位于内部面板(CardLayout
)和外部面板之间.在外部面板(leftBar
)中,我有一个按钮,如果它的actionListener
位于该类的内部,则它可以正常工作,并打开选择的内部面板CardLayout
.但是,如果我将ActionListener
放入控制器,它将无法正常工作.没有错误出现.
This post is continue of this post. Basically in my software is based on CardLayout
panels. And now I want to change panels from outside of cardLayout
. in the provided link, I got helped to do this and it worked. Now I added a controller to my software, that is between an inner panel (CardLayout
) and an outside panel. In the outside panel(leftBar
) I have a button that if its actionListener
is located inside that class it works correctly and open the chose inner panel of CardLayout
. But if I take the ActionListener
into the controller, it just doesnt work. No error comes up.
这是我的示例代码:基础:
Here is my sample code: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基础)
MainPanel (CardLAyout base)
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类(内联)中,则可以工作.
As you can see in LeftBar
I have a method for the button that works as an actionListener
. and I call that method in controller and give it a class. But it doesnt work. However the ACtionListener
works if it is located in LeftBar class (inline).
有什么想法要解决吗?
推荐答案
您正在创建LeftBar
的两个实例,一个在Base
构造函数中,该实例被添加到屏幕中.
You're creating two instances of LeftBar
, one in the Base
constructor, which gets added to the screen...
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
构造函数中的一个传递给控制器...
And one in the MainPanel
constructor which gets passed to the controller...
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
附加到在屏幕上永远不可见的按钮上
This means the controller is attach a ActionListener
to a button which is never visible on the screen
我要做的第一件事是开始分离代码,而不是传递类的实例,您需要建立一系列控制器和视图可以同意的合同,例如,您的MainPanel
应该提供一种切换视图的方法,您的LeftBar
应该在用户想要切换视图时提供通知
The first thing I would do is start decoupling your code, rather then passing instances of your class, you need to establish a series of contracts to which you controller and views can agree to, for example, your MainPanel
should provide a way to switch views, your LeftBar
should provide notification when the user wants to switch views
例如...
public interface Pageable {
public void showView(String name);
}
public interface Navigatable {
public void addActionListener(ActionListener listener);
}
然后您的主视图将实现Pageable
界面
Then your main view would implement the Pageable
interface
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);
}
这只是定义任何实现的合同功能,您的控制器不应关心其他任何事情(也不应允许它执行原本不希望做的事情,例如从您的视图中删除顽皮的控制器中的所有组件)
This simply defines the contractual capabilities of any implementation, your controller should not care about anything else (nor should you allow it to do things it wasn't meant to, like remove all the components from your views, naughty controller)
您的控制器然后负责管理接口之间的合同...
Your controller then just becomes responsible for managing the contracts between the interfaces...
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");
}
}
}
}
现在,就个人而言,这只是围绕您的代码的一小部分,我个人更希望有一个与单个视图/合同进行交互的控制器,这使它变得非常简单...
Now personally, this is just a bit of hacking around your code, personally, I would prefer to have a controller which interacted with a single view/contract, it makes it SO much simpler...
这篇关于为什么ActionListener在控制器中不起作用?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持!