【问题标题】:Java Swing GUI with CardLayout: Window not closing in 2nd Card when going back to 1st带有 CardLayout 的 Java Swing GUI:回到第一张卡片时,第二张卡片中的窗口没有关闭
【发布时间】:2015-07-02 14:50:38
【问题描述】:

我有一个 Swing GUI,它使用带有两张卡片的 CardLayout

  • 主卡

  • 过道卡

当我进入 aisle_card 时,它会正确切换到 aisle_card 并关闭 main_card:

public class Runner
{

    private static JFrame frame;
    private static JPanel cards;

    void createAndShowGUI()
    {
                //ItemsInAisleGUI gui = new ItemsInAisleGUI();
        // Create and set up the window.
        ItemsInAisleGUI gui = new ItemsInAisleGUI();

        frame = new JFrame("Shopping List");
        frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
        cards = new JPanel(new CardLayout());
        JPanel mainCard = buildMainPanel();

        //JPanel aisleCard = new ItemsInAisleGUI(mainCard).aisleCard;
        JPanel aisleCard = gui.createAndShowGUI();

        cards.add(mainCard, MAIN_CARD);
        cards.add(aisleCard, AISLE_CARD);
        // Display the window.
        frame.getContentPane().add(cards);
        frame.pack();
        frame.setVisible(true);
    }


    private JPanel buildMainPanel()
    {
        JPanel mainCard = new JPanel();
        mainCard.setLayout(new GridLayout());
        mainCard.setName(MAIN_CARD);
        JPanel topRowPanel = new JPanel();
        topRowPanel.setLayout(new GridLayout(12, 2));
        topRowPanel.setName("TopRowPanel");

        //Button for the Search by Aisle Card
        JButton aisleButton = new JButton("\u25BA Search by Aisle");
        aisleButton.setName(AISLE_BUTTON);
        aisleButton.addActionListener(new ActionListener()
        {
            @Override
            public void actionPerformed(ActionEvent e)
            {
                CardLayout cl = (CardLayout) (cards.getLayout());
                cl.show(cards, AISLE_CARD);
            }
        });

        //panels and labels of mainCard

        mainCard.add(topRowPanel);
        return mainCard;
    }

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

    }

    /**
     * @return the frame containing the application view
     */
    static JFrame getFrame()
    {

        return frame;
    }

    /**
     * @return the card that is current visible
     */
    Component getVisibleCard()
    {
        for (int i = 0; i < cards.getComponentCount(); i++)
        {
            if (cards.getComponent(i).isVisible())
            {
                return cards.getComponent(i);
            }
        }
        return null;
    }

}

但是,当我在 aisle_card 中并想返回时,它确实打开了 main_card 但没有关闭 aisle_card,并且控制台显示 NPE:

线程“AWT-EventQueue-0”中的异常 java.lang.NullPointerException 在 view.ItemsInAisleGUI$2.CloseFrame(ItemsInAisleGUI.java" 指 到这一行 jFrame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);

public class ItemsInAisleGUI {

private static JFrame jFrame;

    public ItemsInAisleGUI() {

    }

    public JPanel createAndShowGUI()
    {
        JPanel content = new JPanel();
        content.setLayout(new GridLayout(2, 1));
        content.setName("aislePanel");

        //panel stuff

        backButton = new JButton("\u25C4 Back to Item Search");
        backButton.setName("BackButton");


        //button for going back to the main screen (Search by Item Name)
        backButton.addActionListener(new ActionListener()
        {

            @Override
            public void actionPerformed(ActionEvent e)
            {
                Runner myrunner = new Runner();
                myrunner.createAndShowGUI();
                CloseFrame();
            }
            public void CloseFrame(){
            jFrame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
            jFrame.setVisible(false);
            }
        });     

        topRowPanel.add(aisleNumberLabel);
        topRowPanel.add(aisleNumberText);
        topRowPanel.add(itemsInAisleLabel);
        topRowPanel.add(itemsInAisleText);
        topRowPanel.add(searchItemButton);
        topRowPanel.add(backButton);    
        content.add(topRowPanel);
        return content;
    }

    public static Container getContainer()
    {
        return jFrame;
    }

    /**
     * @param args
     */
    public static void main(String[] args)
    {

    }

}

有什么建议吗?谢谢。

【问题讨论】:

  • 这可能不是你问题的症结所在,但是你有没有将过道按钮添加到父组件中?
  • 这意味着变量jFrame 为空。我看不到您将此变量设置为 null 的任何地方(甚至就此而言,它被声明为类 JFrame 的实例。所以我认为问题可能出在您尚未提出的其他代码中。
  • @NoseKnowsAll 我忘了提到我在 ItemsinAisleGUI 类中声明了private static JFrame jFrame

标签: java swing


【解决方案1】:

首先,您的静态变量不是必需的。此外,您对正在发生的事情有一些误解:

它会打开 main_card 但不会关闭 aisle_card

这是错误的。它实际上并没有满足您正在考虑的 main_card 。正如您在此处的代码中所见,它正在完全打开一个新的 gui:

public void actionPerformed(ActionEvent e)
        {
            Runner myrunner = new Runner();
            myrunner.createAndShowGUI(); // Creates completely new GUI
            CloseFrame();
        }

我不知道您的应用程序的确切结构,但以下内容应该可以编译,并且至少应该为您提供 CardLayouts 如何工作的基础:

import javax.smartcardio.Card;
import javax.swing.*;
import java.awt.*;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;

public class Runner {

    private final JFrame frame;

    private final JPanel home;
    private final JPanel second;

    public static void main(String[] args) {
        Runner runner = new Runner();
        runner.show();
    }

    public Runner() {
        this.frame = new JFrame();
        this.frame.setSize(new Dimension(500, 500));
        this.frame.setLocationRelativeTo(null);

        JPanel contentPanel = new JPanel(new CardLayout());
        frame.setContentPane(contentPanel);

        home = buildMainPanel();
        second = buildSecondPanel();

        contentPanel.add("home", home);
        contentPanel.add("second", second);

    }

    public JPanel buildMainPanel() {
        JPanel something = new JPanel(null);
        something.setBounds(0,0,500,500);
        something.setBackground(Color.black);

        JButton flipButton = new JButton("Second");
        flipButton.setBounds(0,0,100,80);
        flipButton.addActionListener(new ActionListener() {
            @Override
            public void actionPerformed(ActionEvent e) {
                CardLayout layout = (CardLayout) frame.getContentPane().getLayout();
                layout.show(frame.getContentPane(), "second");
            }
        });

        something.add(flipButton);
        return something;
    }

    public JPanel buildSecondPanel() {
        JPanel something = new JPanel(null);
        something.setBounds(0,0,500,500);
        something.setBackground(Color.blue);

        JButton flipButton = new JButton("Second");
        flipButton.setBounds(0,0,100,80);
        flipButton.addActionListener(new ActionListener() {
            @Override
            public void actionPerformed(ActionEvent e) {
                CardLayout layout = (CardLayout) frame.getContentPane().getLayout();
                layout.show(frame.getContentPane(), "home");
            }
        });

        something.add(flipButton);
        return something;
    }

    public void show() {
        frame.setVisible(true);
    }
}

如果你编译这个并点击按钮,你可以看到背景从黑色变成蓝色,这意味着不同的卡片正在显示。希望这有助于您走上正轨。

【讨论】:

  • 如果将第二张卡放在单独的类中,这将如何工作?
  • 解决方法是该类将具有一个 getDisplay() 函数,该函数将返回该类所代表的面板,但由于维护,这通常不受欢迎。研究 MVC 技术 - 它是最广泛接受的 GUI 模型,并且代码更简洁。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2021-06-09
  • 1970-01-01
  • 1970-01-01
  • 2021-07-07
  • 1970-01-01
  • 2012-09-21
  • 1970-01-01
相关资源
最近更新 更多