如何多次创建新的和处理 jcomponents?

How to create new and dispose jcomponents multiple times?

(对不起,如果这个问题没有正确完成,我是新手。但至少我在问自己的问题之前研究了很多)

您好。我正在 java 中编写一个 21 点游戏,它变得非常庞大。 我的问题是如何处理swing组件的多个实例,我猜你可以调用它。我不知道是将组件(例如 jpanels 和 jbuttons)创建为 class 级别,还是以特定方法创建。

如果我在相应的方法中创建它们,那么我的动作侦听器就看不到它们,但是如果我将它们创建为 class 级别,那么当我调用 dispose() 时它们会被删除。

 class BlackjackGame extends JFrame implements ActionListener{

    public void mainMenu(){

        JPanel menuPane = new JPanel(new GridBagLayout()); //Init of main menu
        GridBagConstraints c = new GridBagConstraints();
        menuPane.setBackground(new Color(125,0,0));
        menuPane.setBounds(620,220,175,250);

        JLabel menuTitle = new JLabel("Welcome to Blackjack!");//Main menu-content
        c.gridx = 1;
        c.gridy = 0;
        c.insets = new Insets(0,0,20,0);
        menuPane.add(menuTitle, c);

        JButton playButton = new JButton("Play!");
        playButton.addActionListener(this);
        c.gridx = 0;
        c.gridy = 1;
        c.gridwidth = 3;
        c.ipadx = 25;
        c.ipady = 25;
        c.insets = new Insets(0,0,0,0);
        menuPane.add(playButton, c);

        JButton exitButton = new JButton("Exit!");
        exitButton.addActionListener(this);
        c.gridx = 0;
        c.gridy = 2;
        c.gridwidth = 3;
        menuPane.add(exitButton, c);

        JButton rulesButton = new JButton("Set rules.");
        rulesButton.addActionListener(this);
        c.gridx = 0;
        c.gridy = 3;
        c.gridwidth = 3;
        menuPane.add(rulesButton, c);

        this.add(menuPane,0);
    }

    //This is where I get problems
    public void actionPerformed (ActionEvent event){
        if(event.getSource() == playButton){
            //I want the menuPane to disappear, and a transition into the game.
            menuPane.dispose();
            //Call method for the rest of the game.

        }else if(event .getSource() etcetera etcetera){
            etcetera etcetera
        }
    }
}

这样做后,actionlistener 找不到我的组件,例如 playButton 或 menuPane。但如果我将它们介绍为 class 级对象:

class BlackjackGame extends JFrame implements ActionListener{

    JPanel menuPane = new JPanel(new GridBagLayout());
    JLabel menuTitle = new JLabel("Welcome to Blackjack!");
    JButton playButton = new JButton("Play!");
    JButton exitButton = new JButton("Exit!");
    JButton rulesButton = new JButton("Set rules.");

    public void mainMenu(){
        //Rest of code
    }

    public void actionPerformed(ActionEvent event){
        menuPane.dispose();
        //Rest of code
    }
}

...那么当我调用menuPane.dispose()时,我想再次调用mainMenu()时如何取回它?如果我想返回主菜单,那么我需要创建一个新的 menuPane 实例,以及所有按钮,但由于它们是 class 级别并且已经处理完毕,所以我不能。

请帮帮我,谢谢!

PS。如果有帮助,我可以 post 我的完整代码,因为它是 atm。

编辑:Dan 的回答已被接受,因为它确实是正确的答案,并且非常适合我的特定程序。谢谢,圣诞快乐!

首先,除非我误解了您的代码,否则 menuPane.dispose() 不应该工作,因为 JPanel 没有名为 dispose()

的函数

如果您想对菜单使用相同的 menuPane,这是做您想做的事情的最佳方式。而不是 menuPane.dispose(); 使用 remove(menuPane); 然后 add(yourOtherPanel);

工作示例

import java.awt.Color;
import java.awt.EventQueue;
import java.awt.GridBagConstraints;
import java.awt.GridBagLayout;
import java.awt.Insets;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;

import javax.swing.JButton;
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.JPanel;

@SuppressWarnings("serial")
public class BlackjackGame extends JFrame implements ActionListener {
    private JPanel menuPane;
    private JLabel menuTitle;
    private JButton playButton;
    private JButton exitButton;
    private JButton rulesButton;

    private JPanel otherPane;
    private JLabel otherTitle;
    private JButton otherButton;

    public BlackjackGame() {
        mainMenu();
        otherPanel();
        setSize(400, 400);
        setVisible(true);
    }

    private void mainMenu() {

        menuPane = new JPanel(new GridBagLayout());
        GridBagConstraints c = new GridBagConstraints();
        menuPane.setBackground(new Color(125,0,0));
        menuPane.setBounds(620,220,175,250);

        menuTitle = new JLabel("Welcome to Blackjack!");
        c.gridx = 1;
        c.gridy = 0;
        c.insets = new Insets(0,0,20,0);
        menuPane.add(menuTitle, c);

        playButton = new JButton("Play!");
        playButton.addActionListener(this);
        c.gridx = 0;
        c.gridy = 1;
        c.gridwidth = 3;
        c.ipadx = 25;
        c.ipady = 25;
        c.insets = new Insets(0,0,0,0);
        menuPane.add(playButton, c);

        exitButton = new JButton("Exit!");
        exitButton.addActionListener(this);
        c.gridx = 0;
        c.gridy = 2;
        c.gridwidth = 3;
        menuPane.add(exitButton, c);

        rulesButton = new JButton("Set rules.");
        rulesButton.addActionListener(this);
        c.gridx = 0;
        c.gridy = 3;
        c.gridwidth = 3;
        menuPane.add(rulesButton, c);

        add(menuPane);
    }

    private void otherPanel() {
        otherPane = new JPanel(new GridBagLayout());
        GridBagConstraints c = new GridBagConstraints();
        otherPane.setBackground(new Color(125,0,0));
        otherPane.setBounds(620,220,175,250);

        otherTitle = new JLabel("Welcome to Second Pane!");
        c.gridx = 1;
        c.gridy = 0;
        c.insets = new Insets(0,0,20,0);
        otherPane.add(otherTitle, c);

        otherButton = new JButton("Go Back!");
        otherButton.addActionListener(this);
        c.gridx = 0;
        c.gridy = 1;
        c.gridwidth = 3;
        c.ipadx = 25;
        c.ipady = 25;
        c.insets = new Insets(0,0,0,0);
        otherPane.add(otherButton, c);
    }

    public void actionPerformed (ActionEvent event) {
        if(event.getSource() == playButton) {
            remove(menuPane);
            add(otherPane);
            validate();
            repaint();

        } else if(event.getSource() == otherButton) {
            remove(otherPane);
            add(menuPane);
            validate();
            repaint();
        }
    }

    public static void main(String[] args) {
        EventQueue.invokeLater(() -> new BlackjackGame());
    }
}

编辑评论

因此 java 方法 remove() 仅从容器中删除对象,在本例中为 JFrame。此方法不会影响它移动的对象,因此该对象可以在以后重复使用。因此,为什么在上面的代码中我可以只使用 remove()add() 方法而无需重新声明或重新制作 menuPaneotherPane.

至于为什么我这样声明对象

`private JPanel menuPane;`

然后像这样初始化

menuPane = new JPanel(new GridBagLayout());

这是因为我希望 ActionListener 能够在不立即初始化对象的情况下看到它们。 private JPanel menuPane; 行使对象成为全局变量,menuPane = new JPanel(new GridBagLayout()); 行使它成为我要使用的对象。这样做而不是 JPanel menuPane = new JPanel(new GridBagLayout()); 也意味着我可以在多个方法中重用同一个变量。例如

private JPanel panel;

private void createPanelOne() {
    panel = new JPanel(new FlowLayout());
    ...
    add(panel);
}

private void createPanelTwo() {
    panel = new JPanel(new GridBagLayout());
    ...
    add(panel);
}

这样做之后,你的JFrame中会有两个JPanel,它们会有所不同,但你只需要使用一个JPanel

这是声明它的另一种方式,它创建了一个局部变量。局部变量对您正在使用的方法之外的其他方法不可见,除非您传递它们。

JPanel panel = new JPanel();

我不会说这是丝毫的骗局。我认为有时在不应该对其他方法可见的方法中使用局部变量是很好的。

最后,要将局部变量传递给其他方法,您可以在您创建的方法中使用参数。例如

public void setSomeValue(int val) {
    someValue = val;
}