【问题标题】:How to switch cards from a button on a card?如何从卡片上的按钮切换卡片?
【发布时间】:2017-06-10 14:58:16
【问题描述】:

我一直在寻找解决方案一段时间,尽管有所有类似的问题和答案,但似乎没有找到任何可行的方法。我希望用户能够通过卡片布局中设置的各种面板进行操作。但是,我希望用于在这些卡之间切换的按钮位于卡本身上,而不是一组不会在程序中更改的单独按钮。这是创建框架的主文件:

public class BattleGraphs_V1 
{
    JPanel cards;

    public int cardNumber = 1;

    public void addComponentToPane (Container pane)
    {
        JPanel MainMenuCard = new MainMenu_V1();
        JPanel DifficultySelectorCard = new DifficultySelector_V1();

        cards = new JPanel(new CardLayout());

        cards.add(MainMenuCard);
        cards.add(DifficultySelectorCard);

        pane.add(cards, BorderLayout.CENTER);
    }

    private static void createAndShowGUI() 
    {
        JFrame frame = new JFrame("BattleGraphs");
        frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);

        frame.setDefaultCloseOperation(javax.swing.WindowConstants.EXIT_ON_CLOSE);
        frame.setPreferredSize(new java.awt.Dimension(725, 420));
        frame.setResizable(false);

        BattleGraphs_V1 containerPanel = new BattleGraphs_V1();
        containerPanel.addComponentToPane(frame.getContentPane());

        frame.pack();
        frame.setVisible(true);
    }

    public static void main(String[] args) 
    {
        javax.swing.SwingUtilities.invokeLater(new Runnable() 
        {
            public void run() 
            {
                createAndShowGUI();
            }
        });
    }
}

这两个面板(将来会更多)位于项目的两个单独文件中。除了每个面板上单个按钮的动作监听器之外,我还没有为它们添加代码,它都是自动生成的代码。

编辑: 我向 MainMenu JPanel 的按钮添加了一个自动生成的动作侦听器,如下所示:

private void MainMenuCardSBActionPerformed(java.awt.event.ActionEvent evt) {                                               
        BattleGraphs_V1 BG_V1 = new BattleGraphs_V1();
        CardLayout cardLayout = (CardLayout) (BG_V1.cards.getLayout());
        cardLayout.show(BG_V1.cards, "DifficultyCard");
    }

将名称添加到主文件(主文件为 BattleGraphs_V1)中添加的卡片后,如下所示:

cards.add(MainMenuCard, "MainMenuCard");
cards.add(DifficultySelectorCard, "DifficultyCard");

当我运行程序并单击按钮时,出现空指针异常错误,就像我使用类似的解决方案所做的那样。如果我认为这更多地归结为范围问题,我会错吗?

第二次编辑: 是的,希望这对您有所帮助,我已将 enite 项目添加到 GitHub 存储库 - https://github.com/charga600/BattleGraphs/tree/master

【问题讨论】:

  • 哪一行给出了 NPE?
  • 另外,你不应该创建new BattleGraphs,你应该有一个你想要的引用,否则你永远不会初始化 BG_V1.cards。所以这可能是给你 NPE 的那一行。
  • 这里有一个问题,卡/面板有什么责任来确定下一个导航点?回答,没有,为什么?因为以这种方式修改导航是一场噩梦。解决方案?有一个模型/控制器可以被要求从面板导航到下一步
  • 我认为您不应该在您的 ActionListener 中创建 BattleGraphs_V1 的新实例,这也是您不应该这样做的另一个原因,面板应该与必须做出这些决定相隔离,因为它正在假设它是如何设置的

标签: java jframe jpanel


【解决方案1】:

当您将卡片添加到面板时,您应该为其命名,以便您可以选择要在特定事件中显​​示的切换卡片。

cards = new JPanel(new CardLayout());

cards.add(MainMenuCard, "first");
cards.add(DifficultySelectorCard, "second");

pane.add(cards, BorderLayout.CENTER);

图形界面:

JButton button = new JButton("Click here");
button.addActionListener(new ActionListener() {
    @Override
    public void actionPerformed(ActionEvent e) {
        CardLayout cl = (CardLayout) (cards.getLayout());
        cl.show(cards, "second");
    }
});

编辑

这是一个演示 CardLayout 的简短示例,因为您没有分享您的完整代码。

主类

    public class MainMenu_V1 extends JFrame {

    private JMenuBar menuBar;
    private JMenu file;
    private JMenuItem exit;
    private JPanel mainPanel;

    public MainMenu_V1() {
        setTitle("Main Panel");
        setResizable(false);
        setSize(new Dimension(400, 200));
        setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
        setJMenuBar(createMainMenu());
        setLocationRelativeTo(null);

        mainPanel = new JPanel();
        mainPanel.setLayout(new CardLayout());
        mainPanel.add(new FirstPanel(mainPanel), "FIRST");
        mainPanel.add(new SecondPanel(mainPanel), "SECOND");

        setContentPane(mainPanel);
    }

    public JMenuBar createMainMenu() {
        menuBar = new JMenuBar();
        file = new JMenu("File");
        exit = new JMenuItem("Exit");
        exit.addActionListener(new ActionListener() {
            @Override
            public void actionPerformed(ActionEvent e) {
                System.exit(0);
            }
        });

        file.add(exit);
        menuBar.add(file);

        return menuBar;
    }

    public void switchPanel(Container container, String panelName) {
        CardLayout card = (CardLayout) (container.getLayout());
        card.show(container, panelName);
    }

    public static void main(String[] args) {
        javax.swing.SwingUtilities.invokeLater(new Runnable() {
            public void run() {
                new MainMenu_V1().setVisible(true);
            }
        });
    }
}

第一面板

public class FirstPanel extends JPanel {

    private JButton button;
    private JPanel mainPanel;

    public FirstPanel(JPanel mainPanel) {
        this.mainPanel = mainPanel;
        setPreferredSize(new Dimension(400, 200));
        setBackground(Color.GRAY);
        add(createButton());        
    }   

    private JButton createButton() {
        button = new JButton("Switch to the second Panel");
        button.addActionListener(new ActionListener() {
            @Override
            public void actionPerformed(ActionEvent e) {
                MainMenu_V1 main = new MainMenu_V1();
                main.switchPanel(mainPanel, "SECOND");                
            }
        });
        return button;
    }
}

第二面板

public class SecondPanel extends JPanel {

    private JButton button;
    private JPanel mainPanel;

    public SecondPanel(JPanel mainPanel) {
        this.mainPanel = mainPanel;
        setPreferredSize(new Dimension(400, 200));
        setBackground(Color.ORANGE);
        add(createButton());
    }   

    private JButton createButton() {
        button = new JButton("Switch to the first Panel");
        button.addActionListener(new ActionListener() {
            @Override
            public void actionPerformed(ActionEvent e) {
                MainMenu_V1 main = new MainMenu_V1();
                main.switchPanel(mainPanel, "FIRST");                
            }
        });
        return button;
    }
}

【讨论】:

  • 还可以查看这篇文章:cardLayout
  • 很难说是什么问题,我们看不到你的完整代码。我在帖子中添加了一个示例。
  • 我已经链接到一个 gitHub 存储库,应该可以让您访问完整代码,而无需将此页面作为无限滚动条。
  • 另外,当我使用您提供的示例代码并从中创建一个 netbeans 项目时,当我尝试运行该项目时,它给了我这个“线程中的异常”AWT-EventQueue-0 java.lang.RuntimeException:无法编译的源代码 - 错误的树类型:”。问题源于第 31 行 - “mainPanel.add(new FirstPanel(mainPanel), “FIRST”);”和 66" 新 MainMenu_V1().setVisible(true);"
猜你喜欢
  • 2016-04-21
  • 1970-01-01
  • 2022-01-03
  • 1970-01-01
  • 2016-10-24
  • 1970-01-01
  • 1970-01-01
  • 2022-10-21
  • 2021-05-19
相关资源
最近更新 更多