Java contentpane.removeAll不删除JPanel
我有一个带有启动按钮的JPanel,当按下该按钮时,它通过主机调用控制器中的start()函数Java contentpane.removeAll不删除JPanel,java,swing,concurrency,jframe,jpanel,Java,Swing,Concurrency,Jframe,Jpanel,我有一个带有启动按钮的JPanel,当按下该按钮时,它通过主机调用控制器中的start()函数 public void actionPerformed(ActionEvent e) { // TODO Auto-generated method stub if (e.getSource().equals(start)) { System.out.println("hi"); try { f.c.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;");
}
这是大型机中的一个函数,它是一个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,让它直接进入问题,它就可以正常工作。但我还是不想直接问问题。出于某种原因,它可以在问题面板之间切换,但不能在开始面板和问题面板之间切换 您遇到了并发问题,正在调用Swing事件线程上的长时间运行的代码,该问题将阻止该线程执行重要的任务,例如绘制GUI和与用户交互。解决方案是在后台线程中执行长时间运行的代码,如SwingWorker提供的代码。然后阅读Swing并发性:
好的,我现在确信我最初的建议——使用后台线程——是错误的,相反,你已经用while循环、synchronized块和wait把代码复杂化了。是的,这些线程会阻止事件线程,是的,这会使应用程序停止运行,使其冻结并变得完全无响应,但解决方案不是使用后台线程,而是您希望摆脱
while(true)
循环、同步块和wait()
调用并在其位置使用事件侦听器和回调方法。这一点的精确连接将取决于我们还不了解的代码,但这就是这个问题的解决方案。例如,问题面板可以通知控制类某个问题已被回答,以更改模型的状态,使其转到下一个问题。然后模型会改变,这会通知视图它必须更新自己,现在显示下一个问题
旁注:
- 最好使用CardLayout交换视图,然后直接交换视图。可以在以下位置找到教程:
- 关于:
main.setPanel(qp)代码>
您似乎正在将QuestionPanel重新添加到for循环中的main中。如果是这样,您只需要并且只应该添加一次