打开第二帧将清除第一帧中ArrayLists持有的所有对象

时间:2016-12-22 17:20:31

标签: java swing arraylist jframe

所以我正在尝试编写RPG棋盘游戏或至少其中的一部分。

我有两个框架,一个是游戏发生的主框架。第二帧用于创建角色。

我正在使用第一帧内的按钮初始化第二帧。在新打开的框架中,玩家可以设置他/她的值并创建角色。

我遇到的问题是,只要我点击

cw = new CreationWindow();

包含字符对象的ArrayList播放器列表似乎已被清除。我在调试模式中测试了这个,并且在此行之前和之后的断点显示这是ArrayList丢失其保持的对象的位置。

我真的不明白那里发生了什么,如果有人能向我解释,我会很高兴的!

使用的类:

主窗口

public class MainWindow extends JFrame {

private CreationWindow cw;

private JPanel contentPane;

// Startscreen
private ArrayList<JButton> startscreenCreateList = new ArrayList<JButton>();
private ArrayList<JLabel[]> playerValuelist = new ArrayList<JLabel[]>();

// Objects
private ArrayList<Character> playerlist = new ArrayList<Character>();

public static void main(String[] args) {
    EventQueue.invokeLater(new Runnable() {
        public void run() {
            try {
                MainWindow frame = new MainWindow();
                frame.setVisible(true);
            } catch (Exception e) {
                e.printStackTrace();
            }
        }
    });
}

public MainWindow() {
    setTitle("Legends of Andor");
    setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
    setBounds(100, 100, 550, 460);
    setResizable(false);
    contentPane = new JPanel();
    contentPane.setBorder(new EmptyBorder(5, 5, 5, 5));
    contentPane.setLayout(null);
    setContentPane(contentPane);

    // Startscreen
    setStartscreen();

}

private void setStartscreen() {
    for (int x = 0; x < 4; x++) {
        startscreenCreateList.add(new JButton("Add"));
        startscreenCreateList.get(x).setBounds(40, 45 + x * 95, 100, 30);
        startscreenCreateList.get(x).addActionListener(new ActionListener() {
            public void actionPerformed(ActionEvent ae) {
                /*
                 * 1. the initialization of the CreationWindow Object seems to set every ArrayList of MainWindow "null"
                 * "null"
                 */
                cw = new CreationWindow();
                cw.setVisible(true);
            }
        });
        contentPane.add(startscreenCreateList.get(x));

        // Start-Button
        JButton start = new JButton("Start!");
        start.setBounds(410, 370, 100, 30);
        contentPane.add(start);
    }

}

// Methods
public void createCharacter(Character c) {
    /*
     * 5. adds Character Object received from CreationWindow to ArrayList
     */
    playerlist.add(c);
    System.out.println(playerlist.size());
 }
}

CreationWindow

public class CreationWindow extends JDialog {

private JPanel contentPane;

private JLabel[] labels = new JLabel[5];
private JTextField name;
private ArrayList<JComboBox<String[]>> inputFields = new ArrayList<JComboBox<String[]>>();
private JButton create;

private MainWindow hf = new MainWindow();
private Character c;

public CreationWindow() {
    setTitle("Create a Character!");
    setDefaultCloseOperation(JFrame.DISPOSE_ON_CLOSE);
    setBounds(100, 100, 300, 250);
    setResizable(false);
    setModal(true);
    contentPane = new JPanel();
    contentPane.setBorder(new EmptyBorder(5, 5, 5, 5));
    contentPane.setLayout(null);
    setContentPane(contentPane);

    setCreationScreen();

    // Create Character
    create.addActionListener(new ActionListener() {
        public void actionPerformed(ActionEvent ae) {

            /*
             *  2. As the class Character is abstract, the Object needs to be initialized with a subclass
             */

            switch (inputFields.get(0).getSelectedIndex()) {
            case 0:
                c = new Bowman();
                break;
            case 1:
                c = new Warrior();
                break;
            case 2:
                c = new Sorcerer();
                break;
            case 3:
                c = new Dwarf();
                break;
            }

            /*
             *  3. setting values of the Character Object
             */

            c.setCharacter(name.getText(), inputFields.get(1).getSelectedIndex() + 1,
                    inputFields.get(2).getSelectedIndex(), inputFields.get(3).getSelectedIndex());

            /*
             *  4. goes back into MainWindow
             */

            hf.createCharacter(c);
            dispose();
        }
    });
}

private void setCreationScreen() {
    // Erstellung Arrays für combobox-items
    String[] points = new String[29];
    String[] hours = new String[10];
    String[] classes = new String[4];

    // Initialisierung Arrays
    for (int x = 0; x < 29; x++) {
        if (x < 10) {
            hours[x] = String.valueOf(x);
        }
        points[x] = String.valueOf(x + 1);
    }
    classes[0] = "Bowman";
    classes[1] = "Warrior";
    classes[2] = "Sorcerer";
    classes[3] = "Dwarf";

    int a = -20;
    for (int x = 0; x < 5; x++) {
        labels[x] = new JLabel();
        if (x < 4) {
            if (x < 1) {
                inputFields.add(new JComboBox(classes));
            } else if (x < 2) {
                inputFields.add(new JComboBox(points));
            } else {
                inputFields.add(new JComboBox(hours));
            }
            if (x < 1) {
                inputFields.get(x).setBounds(25, a + 120, 110, 20);
                labels[x].setBounds(25, a + 105, 100, 15);
            } else {
                inputFields.get(x).setBounds(160, a + 100 + (x - 2) * 40, 80, 20);
                labels[x].setBounds(160, a + 85 + (x - 2) * 40, 90, 15);
            }
            contentPane.add(inputFields.get(x));
        } else {
            labels[x].setBounds(25, a + 45, 100, 15);
        }
        contentPane.add(labels[x]);
    }
    labels[0].setText("Character-Class");
    labels[1].setText("Willpoints");
    labels[2].setText("Strengthpoints");
    labels[3].setText("Hours");
    labels[4].setText("Name");

    name = new JTextField();
    name.setBounds(25, a + 60, 110, 20);
    contentPane.add(name);

    create = new JButton("Create");
    create.setBounds(160, 165, 100, 30);
    contentPane.add(create);
}

}

字符

public abstract class Character {

private String name;
private int willpoints;
private int strenghtpoints;
private int hours;
private boolean isKo = false;

// Constructor
public Character() {

}

public Character(String n, int wp, int sp, int h) {
    name = n;
    willpoints = wp;
    strenghtpoints = sp;
    hours = h;
}

public void setCharacter(String n, int wp, int sp, int h) {
    name = n;
    willpoints = wp;
    strenghtpoints = sp;
    hours = h;
}

// Getters and Setters

// Methods

}

子类继承自Character,并且到目前为止没有任何差异。

子类是:Bowman,Dwarf,Sorcerer,Warrior

非常感谢!

1 个答案:

答案 0 :(得分:1)

你在这里遇到了问题:

allprojects {
    tasks.withType(JavaCompile) {
        sourceCompatibility = "1.7"
         targetCompatibility = "1.7"
   }
}

您在CreationWindow中创建了一个全新的唯一MainWindow实例,对此对象所做的任何更改都不会反映在显示GUI的原始MainWindow中。

解决方案是将对原始MainWindow实例的有效引用传递给新的CreationWindow对象。使用CreationWindow构造函数。

即,

public class CreationWindow extends JDialog {

     // ....

    private MainWindow hf = new MainWindow();

并称之为:

public class CreationWindow extends JDialog {

     // ....

    private MainWindow hf;  // do not instantiate

    public CreationWindow(MainWindow hf) {    
         this.hf = hf;

无关的问题 - 你真的不想这样做:

    cw = new CreationWindow(MainWindow.this);

使用空布局和contentPane.setLayout(null); 似乎是轻松创建复杂GUI的好方法,但是一旦超越新手阶段,您就会发现这种方式是错误的,它只会让您和您的用户更加困难。除了非常确定的例外情况(这不是一个例外)之外,请避免这种情况,而是学习并使用布局管理器。