当按下该按钮时,我有一个带开始按钮的JPanel,它通过mainFrame调用控制器中的start()函数
public void actionPerformed(ActionEvent e) {
// TODO Auto-generated method stub
if (e.getSource().equals(start)) {
System.out.println("hi");
try {
f.c.start();
} catch (KludgeException e1) {
// TODO Auto-generated catch block
e1.printStackTrace();
}
}
}
start()函数调用askQuesions()函数,循环问题为它们创建一个问题面板并存储答案。
public void start() throws KludgeException{
System.out.println("start");
askQuestions();
ConductInference();
}
public void askQuestions() throws KludgeException {
QuestionsPanel qp = new QuestionsPanel(main);
for(data.containers.Question q : kludge.getQuestions()){
qp.addQuestion(q.getQuestion(), q.getType());
main.setPanel(qp);
synchronized(this){
while(!next){
try {
wait();
kludge.setSystemValue(q.getValueName(), v);
//System.out.println("waitOver");
} catch (InterruptedException e) {}
}
}
next = false;
//System.out.println("next question");
}
System.out.println("questions over;");
}
这是mainFrame中的一个函数,它是一个JFrame,它设置了必要的面板。
public void setPanel(JPanel p){
main.getContentPane().removeAll();
main.getContentPane().add(p);
main.validate();
System.out.println("all removed, added and validated");
}
我的问题是这个...当按下stat按钮时程序卡在startPanel上它会冻结。如果我跳过整个startPanel并告诉它直接回答问题它可以正常工作。但我仍然不希望它直接回答问题。由于某种原因,它在问题面板之间切换正常,但不在startPanel和questionPanels之间切换..
答案 0 :(得分:1)
您遇到了并发问题,并且正在Swing事件线程上调用长时间运行的代码,这个问题将阻止此线程执行其重要的工作,例如绘制GUI并与用户交互。解决方案是在后台线程中执行长时间运行的代码,例如SwingWorker提供的代码。那并阅读Swing并发:Lesson: Concurrency in Swing
好的,我现在确定我的原始建议 - 使用后台线程 - 是错误的,相反,您使用while循环,同步块和等待。是的,这些都阻止了事件线程,是的,这会阻碍你的应用程序,使其冻结并变得完全没有响应,但解决方案不是使用后台线程,而是你想要摆脱while (true)
循环,同步块和wait()
调用,并在其位置使用事件侦听器和回调方法。确切的接线将取决于我们尚未知道的代码,但这是该问题的解决方案。例如,问题面板可以通知控件类已经回答了问题,以更改模型的状态,以便它继续进行下一个问题。然后模型会更改,这可以通知视图它必须自行更新,现在显示下一个问题。
附注:
您最好使用CardLayout交换视图,然后直接交换它们。可以在此处找到该教程:CardLayout tutorial。
关于:main.setPanel(qp);
您似乎在for循环中将QuestionPanel重新添加到main。如果是这样,您只需要添加一次即可。