Singleton with CardLayout won't show card when another class calls Singleton.instance.show()

后端 未结 1 679
生来不讨喜
生来不讨喜 2020-12-12 07:33
public class MainWindow extends JPanel {

public static MainWindow instance = new MainWindow();

private CardLayout cards = new CardLayout();

public MainWindow() {
         


        
相关标签:
1条回答
  • 2020-12-12 07:43

    It would suggest a reference issue. public static MainWindow instance = new MainWindow(); looks suspicious, as you would have had to create an instance of MainWindow first for it to be initialise which suggests you now have two instances of MainWindow, one on the screen and one that is not

    Using static in this way is a bad idea, as it leads to issues like this. Instead you should pass a reference of the controller to the page. The controller would define the actions that each page could perform (and if done right, would be defined as an interface)

    Alternatively, you could separate the navigation from the pages into a separate mechanism, this means the pages don't care and can simply displayed in any order you want or reused else where

    Example #1 - Controller based pages

    This examples defines a simple controller which the pages can call in order to effect the navigation of the pages

    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<Page> 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();
                }
            }
    
        }
    }
    

    Example #2 - central controller example

    This example separates the controller from the pages, so that the buttons are not part of the pages themselves. This frees up the pages/views to be anything you need them to be

    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<String> 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);
            }
    
        }
    }
    

    Example #3 - Model based

    Or you could use a model based approach (which is probably more preferable), which defines the order in which components are displayed. For example

    0 讨论(0)
提交回复
热议问题