提问者:小点点

如何完全摆脱JPanel和其中的所有内容?


如何在运行时完全摆脱JPanel及其中的所有内容?

package textgame;

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

public class EscapeFromPrison extends JFrame implements ActionListener{
    JButton startGameButton;
    JButton creditsButton;

    JButton choice1;
    Button choice2;

    JLabel mainTitleLabel;
    JLabel question;
    JLabel space;
    JLabel credits;

    JPanel titleScreen;

    public EscapeFromPrison(){
        super("Escape From Prison");
        setLookAndFeel();
        setSize(500,500);
        setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);

        mainTitleLabel = new JLabel("<html>Escape From Prison</html>");

        startGameButton = new JButton("<html>START<html>");
        startGameButton.setActionCommand("StartGameButton");

        creditsButton = new JButton("<html>CREDITS</html>");
        creditsButton.addActionListener(this);
        creditsButton.setActionCommand("CreditsButton");

        question = new JLabel("");
        space = new JLabel("");
        credits = new JLabel("");

        choice1 = new JButton("");
        choice2 = new JButton("");

        JPanel titleScreen = new JPanel();
        BoxLayout titleScreenLayout = new BoxLayout(titleScreen,      BoxLayout.Y_AXIS);
        titleScreen.setLayout(titleScreenLayout);
        titleScreen.add(mainTitleLabel);
        titleScreen.add(startGameButton);
        titleScreen.add(creditsButton);
        add(titleScreen);

        setVisible(true);
    }

    @Override
    public void actionPerformed(ActionEvent buttonClick){
        String event = buttonClick.getActionCommand();

在这个if语句中,我想去掉main TitleLabelstartGameButton信用按钮。所以问题可以在左上角位置,因为现在它们是不可见的,问题在右上角位置。我正在使用网格布局。

            if(event.equals("StartGameButton")){
            GridLayout grid = new GridLayout(2,2);
            setLayout(grid);

            question.setText("<html>text</html>");
            choice1.setActionCommand("");
            choice1.setText("");
            choice2.setActionCommand("");
            choice2.setText("");

            mainTitleLabel.setVisible(false);
            startGameButton.setVisible(false);
            creditsButton.setVisible(false);

            add(question);
            add(choice1);
            add(choice2);

            setVisible(true);

        }
        if(event.equals("CreditsButton")){
            FlowLayout flo = new FlowLayout();
            setLayout(flo);

            credits.setText("<html></html>");

            mainTitleLabel.setVisible(false);
            startGameButton.setVisible(false);
            creditsButton.setVisible(false);

            add(credits);

            setVisible(true);
        }
    }

    private void setLookAndFeel(){
        try{
            UIManager.setLookAndFeel(
                "com.sun.java.swing.plaf.nimbus.NimbusLookAndFeel"
            );
        }catch(Exception exc){
            //ignore error
        }
    }

    public static void main(String[] arguments){
        EscapeFromPrison frame = new EscapeFromPrison();
    }
}

共1个答案

匿名用户

当前代码的基本问题是startGameButton永远不会注册到ActionListener,因此它永远不会做任何事情。

最大的问题是,随着您添加更多内容,您的代码将变得非常复杂,难以管理。更好的解决方案是在自己的类中分离每个视图,然后您可以独立管理这些视图,并根据需要切换。

这是模型-视图-控制器概念的开始,您可以将功能分离到自包含的域中,这些域可以通过诸如观察者模式之类的东西进行通信(作为一个想法)。

有了这个,您可以使用CardLayout来更轻松地在视图之间切换。

这只是实现这一目标的众多可能方法之一

首先,我们需要定义某种“控制器”,它可以用来控制可见的内容。我们使用接口作为主要契约,因为它们限制了实现的公开,并定义了我们期望在类之间维护的确切契约,这通常被称为“程序到接口”,有关更多详细信息,请参阅SmarterJava开发和Code to Interface

public interface CardGameController {
    public void showMainMenu();
    public void showQuestion();
    public void showCredits();
}

现在,因为我想使用CardLayout作为控制视图的底层机制,我需要一个可以做到这一点的CardGameController的实现…

public class DefaultCardGameController implements CardGameController {
    
    public static final String MAIN_MENU_PANE = "mainMenuPane";
    public static final String CREDITS_PANE = "creditsPane";
    public static final String QUESTION_PANE = "questionPane";
    
    private Container parent;
    private CardLayout cardLayout;

    public DefaultCardGameController(Container parent, CardLayout cardLayout) {
        this.parent = parent;
        this.cardLayout = cardLayout;
    }

    public Container getParent() {
        return parent;
    }

    public CardLayout getCardLayout() {
        return cardLayout;
    }
    
    protected void show(String name) {
        getCardLayout().show(getParent(), name);
    }

    @Override
    public void showMainMenu() {
        show(MAIN_MENU_PANE);
    }

    @Override
    public void showCredits() {
        show(CREDITS_PANE);
    }

    @Override
    public void showQuestion() {
        show(QUESTION_PANE);
    }
    
}

查看如何使用CardLayout了解更多详细信息

现在,我们需要我们想要管理的视图…

public class MenuPane extends JPanel {

    private JButton startGameButton;
    private JButton creditsButton;
    private JLabel mainTitleLabel;
    
    private CardGameController controller;

    public MenuPane(CardGameController controller) {
        this.controller = controller;
        setLayout(new GridBagLayout());
        GridBagConstraints gbc = new GridBagConstraints();
        gbc.gridwidth = GridBagConstraints.REMAINDER;
        
        mainTitleLabel = new JLabel("<html>Escape From Prison</html>");

        startGameButton = new JButton("<html>START<html>");
        startGameButton.setActionCommand("StartGameButton");
        startGameButton.addActionListener(new ActionListener() {
            @Override
            public void actionPerformed(ActionEvent e) {
                controller.showQuestion();
            }
        });

        creditsButton = new JButton("<html>CREDITS</html>");
        creditsButton.addActionListener(new ActionListener() {
            @Override
            public void actionPerformed(ActionEvent e) {
                controller.showCredits();
            }
        });
        creditsButton.setActionCommand("CreditsButton");
        
        add(mainTitleLabel, gbc);
        add(startGameButton, gbc);
        add(creditsButton, gbc);
    }

}

public class QuestionPane extends JPanel {

    private JButton choice1;
    private JButton choice2;

    private JLabel question;
    
    private CardGameController controller;

    public QuestionPane(CardGameController controller) {
        this.controller = controller;
        setLayout(new GridBagLayout());
        GridBagConstraints gbc = new GridBagConstraints();
        gbc.gridx = 0;
        gbc.gridy = 0;
        
        question = new JLabel("The meaning of life, the universe and everything!?");
        choice1 = new JButton("42");
        choice2 = new JButton("46");
        
        add(question, gbc);
        
        JPanel panel = new JPanel();
        panel.add(choice1);
        panel.add(choice2);
        
        gbc.gridy++;
        add(panel, gbc);
        
        // Have some mechanism to control the questions
    }

}

public class CreditsPane extends JPanel {
    
    private JLabel credits;
    
    private CardGameController controller;

    public CreditsPane(CardGameController controller) {
        this.controller = controller;
        setLayout(new GridBagLayout());
        GridBagConstraints gbc = new GridBagConstraints();
        gbc.gridwidth = GridBagConstraints.REMAINDER;
        credits = new JLabel("Happy Bunnies");
        add(credits);
    }
    
}

最后,将这一切结合在一起的“大师”观点…

public class EscapeFromPrison extends JPanel {

    private MenuPane menuPane;
    private QuestionPane questionPane;
    private CreditsPane creditsPane;

    public EscapeFromPrison() {

        CardLayout cardLayout = new CardLayout();
        setLayout(cardLayout);
        DefaultCardGameController controller = new DefaultCardGameController(this, cardLayout);

        menuPane = new MenuPane(controller);
        questionPane = new QuestionPane(controller);
        creditsPane = new CreditsPane(controller);

        add(menuPane, DefaultCardGameController.MAIN_MENU_PANE);
        add(questionPane, DefaultCardGameController.QUESTION_PANE);
        add(creditsPane, DefaultCardGameController.CREDITS_PANE);

        controller.showMainMenu();
    }

    private static void setLookAndFeel() {
        try {
            UIManager.setLookAndFeel(
                            "com.sun.java.swing.plaf.nimbus.NimbusLookAndFeel"
            );
        } catch (Exception exc) {
            //ignore error
        }
    }

    public static void main(String[] arguments) {
        EventQueue.invokeLater(new Runnable() {
            @Override
            public void run() {
                setLookAndFeel();
                JFrame frame = new JFrame("Testing");
                frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
                frame.add(new EscapeFromPrison());
                frame.pack();
                frame.setLocationRelativeTo(null);
                frame.setVisible(true);
            }
        });
    }
}

现在,这是一个非常有限的例子,它采用了你已经做过的,并演示了一些基本原理。

因为你会问一个以上的问题,你将需要一些方法来更有效地管理问题(和答案),这最好通过某种模型来完成,该模型包含所有问题、可能的答案和用户的答案。这样,你将只需要一个问题视图,但它可以使用问题模型中的信息来重新配置自己以显示每个新问题

举个例子