如何让我的 CardLayout UI 更新?

How do I get my CardLayout UI to update?

我正在尝试使用 CardLayout 为游戏构建 UI,尽管在我的卡片切换方法中使用了 revalidate() 和 repaint(),但我似乎无法更新它。该程序旨在作为使用 CardLayout 在 JFrame 内切换 JPanel 的概念证明,因为如果我能成功做到这一点,我就可以用其他 JPanel 重复该过程。不确定该错误是否与线程有关或只是更新 UI。不管怎样,这是我的代码:

/*
 * To change this license header, choose License Headers in Project Properties.
 * To change this template file, choose Tools | Templates
 * and open the template in the editor.
 */
package nationsapp;

import javax.swing.JFrame;
import javax.swing.JPanel;
import javax.swing.JButton;
import javax.swing.JLabel;
import javax.swing.SwingUtilities;
import java.awt.event.ActionListener;
import java.awt.event.ActionEvent;
import java.awt.CardLayout;
/**
 *
 * @author StephenAHyberger
 */
public abstract class NationsApp {
    //Initiates the JFrame for the application
    public static JPanel deck = new JPanel();

    //Initiates the CardLayout and its elements for the application
    public static CardLayout deckShuffle = new CardLayout();
    public static String MENUCARD = "MENUCARD";
    public static String GAMECARD = "GAMECARD";

    //Initiates all the children of the JFrame. Uses CardLayout. 
    public static void init() {
        //Initiates the JFrame
        JFrame frame = new JFrame("Nations");

        //Initiates the first card and its children
        JPanel menuPanel = new JPanel();
        JButton newGameBtn = new JButton("New Game");
        JLabel noteOne = new JLabel("Panel 1");

        //Adds the children of the first card into the component heiarchy
        menuPanel.add(newGameBtn);
        menuPanel.add(noteOne);

        //Adds all event listeners on the first card
        newGameBtn.addActionListener(new NewGame());

        //Initiates the second card and its children
        JPanel gamePanel = new JPanel();
        JLabel noteTwo = new JLabel("Panel 2");

        //Adds the children of the second card into the component heiarchy 
        gamePanel.add(noteTwo);

        //Adds the cards to the deck
        deck.add(menuPanel);
        deck.add(gamePanel);

        //Adds the deck to the JFrame
        frame.add(deck);

        //Sets up the CardLayout 
        deck.setLayout(new CardLayout());
        deckShuffle.addLayoutComponent(frame, MENUCARD);
        deckShuffle.addLayoutComponent(frame, GAMECARD);

        //Sets up JFrame behavior and renders the application
        frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
        frame.pack();
        frame.setVisible(true);
    }
    public static void setWindow(String PLACEHOLDER) {
        CardLayout cl = (CardLayout)(deck.getLayout());
        cl.show(deck, PLACEHOLDER);
        deck.revalidate();
        deck.repaint();
    }
    private static class NewGame implements ActionListener {
        @Override
        public void actionPerformed(ActionEvent e) {
            NationsApp.setWindow(GAMECARD);
        } 
    }
    public static void main(String[] args) {
        SwingUtilities.invokeLater(new Runnable() {
            @Override
            public void run() {
                NationsApp.init();
            }
        });
    }
}

非常感谢您的宝贵时间,

已解决:

我通过 camickr 提供的 the link 中 CardLayoutDemo 的 class 结构进行了大量更改(感谢 camickr 的帮助)。

这是我的解决方案:

/*
 * To change this license header, choose License Headers in Project Properties.
 * To change this template file, choose Tools | Templates
 * and open the template in the editor.
 */
package nationsapp;

import java.awt.*;
import java.awt.event.*;
import javax.swing.*;
/**
 *
 * @author StephenAHyberger
 */
public class NationsApp implements ActionListener {
    //Creates a JPanel to implement a CardLayout
    JPanel deck;

    //Creates constraints for the CardLayout
    final static String MENUCARD = "MENUCARD";
    final static String GAMECARD = "GAMECARD";

    public void init(Container pane) {
        //Creates the first card
        JPanel menuCard = new JPanel();
        JButton newGameBtn = new JButton("New Game");
        menuCard.add(new JLabel("Panel 1"));
        menuCard.add(newGameBtn);

        //Adds EventListeners to the first card
        newGameBtn.addActionListener(this);

        //Creates the second card
        JPanel gameCard = new JPanel();
        gameCard.add(new JLabel("Panel 2"));

        //Creates the deck for the cards
        deck = new JPanel(new CardLayout());
        deck.add(menuCard, MENUCARD);
        deck.add(gameCard, GAMECARD);

        pane.add(deck);
    }
    private static void render() {
        //Create and set up the window
        JFrame frame = new JFrame("Nations");
        frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);

        //Create application class
        NationsApp app = new NationsApp();
        app.init(frame.getContentPane());

        //Display the window
        frame.pack();
        frame.setVisible(true);
    }
    @Override
    public void actionPerformed(ActionEvent e) {
        CardLayout cl = (CardLayout)(deck.getLayout());
        cl.show(deck, GAMECARD);
    } 
    public static void main(String[] args) {
        SwingUtilities.invokeLater(new Runnable() {
            @Override
            public void run() {
                render();
            }
        });
    }
}

你 class 的整个结构是错误的。为此,您不应该使用所有静态变量和方法。

    deckShuffle.addLayoutComponent(frame, MENUCARD);
    deckShuffle.addLayoutComponent(frame, GAMECARD);

以上不需要。

只需使用 add(...) 方法将组件添加到面板,就像使用任何其他布局管理器一样。

    deck.add(menuPanel, ...);
    deck.add(gamePanel, ...);

您需要指定 CardLayout 使用的约束。

当您尝试换卡时,不需要 revalidate() 和 repaint()。

我建议您首先阅读 How to Use CardLayout 上 Swing 教程中的部分以获取工作示例。该示例将向您展示如何更好地构建代码以遵循 Swing 约定。然后您可以根据您的要求修改工作示例。