当另一个类调用Singleton.instance.show()时,带有CardLayout的Singleton将不会显示卡片

public class MainWindow extends JPanel { public static MainWindow instance = new MainWindow(); private CardLayout cards = new CardLayout(); public MainWindow() { setLayout(cards); add(new FirstPage(), Pages.FIRST.toString()); add(new SecondPage(), Pages.SECOND.toString()); add(new ThirdPage(), Pages.THIRD.toString()); } public void showPage(Pages page) { cards.show(this, page.toString()); } } 

showPage(page); 如果我在MainWindow的构造函数中调用它,方法工作正常。 但是当我尝试调用MainWindow.instance.showPage(Pages.SECOND); 来自FirstPage的ActionListener没有任何反应。 我已经检查过showPage(page)方法是否正常工作。 我已经检查过ActionEvent被触发并输入正确的if / else子句。 我做错了什么,为什么不是我的第二页显示?

 public class FirstPage extends JPanel { private JButton showSecond = new JButton("Show Second"); private JButton showThird = new JButton("Show Third"); public FirstPage() { insertButton(showSecond); insertButton(showThird); } private void insertButton(JButton button) { button.addActionListener(new ActionListener() { @Override public void actionPerformed(ActionEvent e) { if (e.getSource() == showSecond) { MainWindow.instance.showPage(Pages.SECOND); } else { MainWindow.instance.showPage(Pages.THIRD); } } }); this.add(button); } } 

它会提出一个参考问题。 public static MainWindow instance = new MainWindow(); 看起来很可疑,因为你必须首先创建一个MainWindow实例才能进行初始化,这表明你现在有两个MainWindow实例,一个在屏幕上,一个不是

以这种方式使用static是一个坏主意,因为它会导致这样的问题。 相反,您应该将控制器的引用传递给页面。 控制器将定义每个页面可以执行的操作(如果正确完成,将被定义为interface

或者,您可以将导航与页面分离为单独的机制,这意味着页面不关心并且可以按照您想要的任何顺序显示或重复使用其他位置

示例#1 – 基于控制器的页面

此示例定义了一个简单的控制器,页面可以调用该控制器以实现页面的导航

 import java.awt.BorderLayout; import java.awt.CardLayout; import java.awt.EventQueue; import java.awt.FlowLayout; import java.awt.event.ActionEvent; import java.awt.event.ActionListener; import java.util.ArrayList; import java.util.List; import javax.swing.JButton; import javax.swing.JComponent; import javax.swing.JFrame; import javax.swing.JLabel; import javax.swing.JPanel; import javax.swing.UIManager; import javax.swing.UnsupportedLookAndFeelException; public class CardLayoutExample { public static void main(String[] args) { new CardLayoutExample(); } public CardLayoutExample() { EventQueue.invokeLater(new Runnable() { @Override public void run() { try { UIManager.setLookAndFeel(UIManager.getSystemLookAndFeelClassName()); } catch (ClassNotFoundException | InstantiationException | IllegalAccessException | UnsupportedLookAndFeelException ex) { } JFrame frame = new JFrame("Testing"); frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); frame.setLayout(new BorderLayout()); frame.add(new Wizard()); frame.pack(); frame.setLocationRelativeTo(null); frame.setVisible(true); } }); } public interface NavigationController { public void nextPage(); public void previousPage(); public void lastPage(); public void firstPage(); } public interface Page { public NavigationController getNavigationController(); public JComponent getView(); public String getName(); } public class Wizard extends JPanel implements NavigationController { private List pages; private Page currentPage; private CardLayout cardLayout; public Wizard() { cardLayout = new CardLayout(); pages = new ArrayList<>(25); setLayout(cardLayout); pages.add(new FirstPage("Page01", this)); pages.add(new SecondPage("Page02", this)); pages.add(new ThirdPage("Page03", this)); for (Page page : pages) { add(page.getView(), page.getName()); } firstPage(); } @Override public void nextPage() { int index = pages.indexOf(currentPage); index++; if (index < pages.size()) { cardLayout.next(this); currentPage = pages.get(index); } } @Override public void previousPage() { int index = pages.indexOf(currentPage); index--; if (index >= 0) { cardLayout.previous(this); currentPage = pages.get(index); } } @Override public void lastPage() { Page page = pages.get(pages.size() - 1); showPage(page); } @Override public void firstPage() { Page page = pages.get(0); showPage(page); } protected void showPage(Page page) { cardLayout.show(this, page.getName()); currentPage = page; } } public abstract class AbstractPage extends JPanel implements Page, ActionListener { private NavigationController navigationController; private JPanel buttons; private String name; public AbstractPage(String name, NavigationController navigationController) { this.name = name; this.navigationController = navigationController; setLayout(new BorderLayout()); buttons = new JPanel(new FlowLayout(FlowLayout.RIGHT)); add(buttons, BorderLayout.SOUTH); } protected void insertButton(JButton button) { button.addActionListener(this); buttons.add(button); } @Override public NavigationController getNavigationController() { return navigationController; } @Override public JComponent getView() { return this; } @Override public String getName() { return super.getName(); } } public class FirstPage extends AbstractPage implements Page { private JButton next = new JButton("Next >"); public FirstPage(String name, NavigationController controller) { super(name, controller); JLabel label = new JLabel("First page"); label.setHorizontalAlignment(JLabel.CENTER); add(label); insertButton(next); } @Override public void actionPerformed(ActionEvent e) { if (e.getSource() == next) { getNavigationController().nextPage(); } } } public class SecondPage extends AbstractPage implements Page { private JButton next = new JButton("Next >"); private JButton previous = new JButton("< Previous"); public SecondPage(String name, NavigationController controller) { super(name, controller); JLabel label = new JLabel("Second page"); label.setHorizontalAlignment(JLabel.CENTER); add(label); insertButton(previous); insertButton(next); } @Override public void actionPerformed(ActionEvent e) { if (e.getSource() == next) { getNavigationController().nextPage(); } else if (e.getSource() == previous) { getNavigationController().previousPage(); } } } public class ThirdPage extends AbstractPage implements Page { private JButton previous = new JButton("< Previous"); public ThirdPage(String name, NavigationController controller) { super(name, controller); JLabel label = new JLabel("Third page"); label.setHorizontalAlignment(JLabel.CENTER); add(label); insertButton(previous); } @Override public void actionPerformed(ActionEvent e) { if (e.getSource() == previous) { getNavigationController().previousPage(); } } } } 

示例#2 - 中央控制器示例

此示例将控制器与页面分开,因此按钮不是页面本身的一部分。 这样可以将页面/视图释放为您需要的任何内容

 import java.awt.BorderLayout; import java.awt.CardLayout; import java.awt.Component; import java.awt.EventQueue; import java.awt.GridBagConstraints; import java.awt.GridBagLayout; import java.awt.event.ActionEvent; import java.awt.event.ActionListener; import java.util.ArrayList; import java.util.HashMap; import java.util.List; import java.util.Map; import javax.swing.JButton; import javax.swing.JFrame; import javax.swing.JLabel; import javax.swing.JPanel; import javax.swing.UIManager; import javax.swing.UnsupportedLookAndFeelException; import javax.swing.border.EmptyBorder; public class CardLayoutExample2 { public static void main(String[] args) { new CardLayoutExample2(); } public CardLayoutExample2() { EventQueue.invokeLater(new Runnable() { @Override public void run() { try { UIManager.setLookAndFeel(UIManager.getSystemLookAndFeelClassName()); } catch (ClassNotFoundException | InstantiationException | IllegalAccessException | UnsupportedLookAndFeelException ex) { } JFrame frame = new JFrame("Testing"); frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); frame.setLayout(new BorderLayout()); frame.add(new WizardPane()); frame.pack(); frame.setLocationRelativeTo(null); frame.setVisible(true); } }); } public class WizardPane extends JPanel { private List pages; private String currentPage; private JButton first; private JButton previous; private JButton next; private JButton last; private CardLayout cardLayout; private JPanel contentPane; public WizardPane() { setLayout(new BorderLayout()); cardLayout = new CardLayout(); pages = new ArrayList<>(3); contentPane = new JPanel(cardLayout); contentPane.setBorder(new EmptyBorder(4, 4, 4, 4)); pages.add("Page01"); pages.add("Page02"); pages.add("Page03"); contentPane.add(new FirstPage(), "Page01"); contentPane.add(new SecondPage(), "Page02"); contentPane.add(new ThirdPage(), "Page03"); JPanel actionsPane = new JPanel(new GridBagLayout()); actionsPane.setBorder(new EmptyBorder(4, 4, 4, 4)); GridBagConstraints gbc = new GridBagConstraints(); gbc.gridx = 0; gbc.gridy = 0; actionsPane.add((first = new JButton("<< First")), gbc); gbc.gridx++; gbc.weightx = 1; gbc.anchor = GridBagConstraints.WEST; actionsPane.add((previous = new JButton("< Previous")), gbc); gbc.gridx++; gbc.anchor = GridBagConstraints.EAST; actionsPane.add((next = new JButton("Next >")), gbc); gbc.gridx++; gbc.weightx = 0; actionsPane.add((last = new JButton("Last >>")), gbc); add(contentPane); add(actionsPane, BorderLayout.SOUTH); NavigationHandler handler = new NavigationHandler(); first.addActionListener(handler); previous.addActionListener(handler); next.addActionListener(handler); last.addActionListener(handler); gotoFirstPage(); } protected void gotoFirstPage() { currentPage = pages.get(0); cardLayout.show(contentPane, currentPage); } protected void gotoPreviousPage() { int index = pages.indexOf(currentPage); index--; if (index >= 0) { currentPage = pages.get(index); cardLayout.show(contentPane, currentPage); } } protected void gotoNextPage() { int index = pages.indexOf(currentPage); index++; if (index < pages.size()) { currentPage = pages.get(index); cardLayout.show(contentPane, currentPage); } } protected void gotoLastPage() { currentPage = pages.get(pages.size() - 1); cardLayout.show(contentPane, currentPage); } protected class NavigationHandler implements ActionListener { @Override public void actionPerformed(ActionEvent e) { if (e.getSource() == first) { gotoFirstPage(); } else if (e.getSource() == previous) { gotoPreviousPage(); } else if (e.getSource() == next) { gotoNextPage(); } else if (e.getSource() == last) { gotoLastPage(); } } } } public class FirstPage extends JPanel { public FirstPage() { setLayout(new BorderLayout()); JLabel label = new JLabel("Page One"); label.setHorizontalAlignment(JLabel.CENTER); add(label); } } public class SecondPage extends JPanel { public SecondPage() { setLayout(new BorderLayout()); JLabel label = new JLabel("Page Two"); label.setHorizontalAlignment(JLabel.CENTER); add(label); } } public class ThirdPage extends JPanel { public ThirdPage() { setLayout(new BorderLayout()); JLabel label = new JLabel("Page Three"); label.setHorizontalAlignment(JLabel.CENTER); add(label); } } } 

示例#3 - 基于模型

或者您可以使用基于模型的方法(可能更优选),该方法定义组件的显示顺序。 例如