Java contentpane.removeAll不删除JPanel

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();

我有一个带有启动按钮的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();
        } 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中。如果是这样,您只需要并且只应该添加一次


请查看要回答的编辑。您的程序结构已损坏,需要修复。thx供您回复,但我仍不清楚如何使用操作侦听器和回调函数使通过问题的for循环等待,而不是立即跳转到下一个问题,这是因为您不使用for循环。这就是线性控制台程序的实现方式,但这里并不是这样。相反,你有一个非线性事件驱动的GUI程序,在这种情况下,当一个事件发生时,比如说按下一个按钮,你改变一个变量的状态,比如说问题编号,然后获取下一个问题。它需要以事件驱动的方式思考问题。如果仍然坚持,然后考虑创建一个非常简单的程序版本,一个,我们可以运行,并张贴在这里的代码与您的问题。好,我实际上设法修复它几个小时前与您的帮助感谢ALOT!非常好,祝贺你!很高兴听到这个消息,因为这需要解决一个重要的范式转换。如果你不介意的话,请看一下。