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

时间:2016-12-25 05:02:50

标签: java swing user-interface actionlistener jcomponent

(对不起,如果这个问题做得不好,我是新的。但至少我在问自己的问题之前已经研究了很多)

您好。我正在用Java写一个二十一点游戏,它变得非常庞大。 我的问题是如何处理swing组件的多个实例,我想你可以调用它。我无法弄清楚如何在类级别或特定方法中创建组件(例如jpanel和jbuttons)。

如果我使用相应的方法创建它们,那么我的动作监听器就无法看到它们,但如果我将它们创建为类级别,那么当我调用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 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实例,以及所有按钮,但因为它们是类级别而且已经处理好了我不能。

请帮助我,谢谢你!

PS。如果它有帮助,我可以发布我的完整代码。

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

1 个答案:

答案 0 :(得分:1)

首先,除非我误解了您的代码,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);
}

执行此操作后,JPanel中将有两个JFrame,但它们会有所不同,但您只需使用一个JPanel

这是声明它的另一种方式,它产生一个局部变量。除非您传递它们,否则局部变量对您使用的方法之外的其他方法不可见。

JPanel panel = new JPanel();

我不会说这是最轻微的骗局。我认为有时在一个不应该对其他方法可见的方法中使用局部变量是好的。

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

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