我已经在这里阅读了十几个与动作侦听器/循环相关的问题,但是我不确定是否找到了答案。我开始了我的第一个大型Java项目,一个文本RPG,它螺旋成约5K行的逻辑和游戏功能,仅使用控制台即可达到预期的功能-当我决定尝试为其构建Java swing GUI时。这是我的问题:
我使用一个Room对象,该对象处理播放器所在位置的描述,并具有一系列选项供播放器选择,以便下一步根据房间ID在csv文件中的哪个单元格以及在它旁边。我停止将其输出到控制台,而是开始基于options数组创建JButton,如下所示:
public void showNarrate(){
add(dd,gridConstraints);
optionCopy.clear();
int i = 0;
for(JButton j : optionButtons){
//adding and formatting buttons to gridBagConstraint I also set actionCommand for each button to the triggerValue (ID of the next room which the button should take the player to)
}
//I tried using a copy of my JButton array here so I could have something to iterate over in actionListener after clearing out the original
//(Since it needs to be cleared so the next Room's buttons can be built after the player chooses an option)
for(JButton j : optionButtons){
optionCopy.add(j);
}
optionButtons.clear();
//dd is a seperate drawingComponent I used for outputting room descriptions which may be totally unnecessary at this point :/
dd.repaint();
setVisible(true);
}
在动作侦听器(相同的类)中,这是我尝试摆动的方式:
for(JButton j : optionCopy){
if(e.getActionCommand().equals(j.getActionCommand())){
Main.saveRoom = Main.currentRoom;
Main.currentRoom = j.getActionCommand();
System.out.println(Main.currentRoom);
}
}}
然后在我的主班上打电话:narrator.narrate(currentRoom,saveRoom);它会处理其他有关上锁的门,遭遇等的逻辑。在主循环中,还有其他一些与自动保存和跟踪玩家访问过哪些房间有关的方法。我从这里的其他问答中知道,这都是非常糟糕的设计,现在我正努力了解,但是我的问题是:
游戏的第一个房间可以很好地加载,当我单击一个按钮时,它会输出到控制台(仅供测试),该按钮应该调用该房间的正确触发值,所以我已经走了很远,但是如何我现在再次调用相同的方法吗?
-如果我从actionListener调用narrate,它将再次调用自身并抱怨ConcurrentModification。
-如果我尝试在Main类中保持循环播放,它将保持循环播放,并且不允许播放器实际选择按钮。
我以前从未使用过线程,我想知道可能是答案,与我找到的相关答案最接近的东西是:Java: Method wait for ActionListener in another class但我不认为将actionListener移到Main类可以解决我的问题,即actionListener递归调用自身。至于观察者可观察的模式...我只是不明白它:(
我非常感谢您提供的所有帮助,我已经学到了很多尝试使此功能正常运行而又无需寻求帮助的方法,但这让我很沮丧。
您在actionPerformed
中的循环仅使用给定的actionCommand检查JButton
中是否存在optionList
。但是,可以在实际执行操作之前完成此操作:
boolean contained = false;
for (JButton j : optionButtons)
if (j.getActionCommand().equals(e.getActionCommand()))
contained = true;
if (contained) {
// change room
}
现在您可以调用narrate
,因为您已经完成了对集合的迭代,并且不会获得ConcurrentModificationException