所以我正在尝试编写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
非常感谢!
答案 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的好方法,但是一旦超越新手阶段,您就会发现这种方式是错误的,它只会让您和您的用户更加困难。除了非常确定的例外情况(这不是一个例外)之外,请避免这种情况,而是学习并使用布局管理器。