连续运行代码,直到"停止"被压了

时间:2015-05-28 22:26:49

标签: c++ qt-creator

当我按下"开始"我想要执行一些代码。按钮,它继续运行,直到我按下"停止"。

但是,在按下"开始"后,使用以下代码,我无法按"停止"了:

void MainWindow::on_pushButton_clicked()
{
    if (ui->pushButton->text()=="Start") {
        ui->pushButton->setText("Stop");

        vec spectrum_sensed,Sn,sigma,alpha;
        mat ydata;
        condition=true;
        while (condition) {
            cvec uhd_samples = to_cvec(randn(Nsamples),randn(Nsamples));
            ydata=spectrum->dft(uhd_samples,Ndft,Nband);

            myplot->Plot_data(spectrum_sensed,Ndft);
        }
     }
     else {
         ui->pushButton->setText("Start");
         condition=false;
         myplot->clear_plot();
     }
}

1 个答案:

答案 0 :(得分:2)

Qt的GUI在一个线程中运行,如果你的代码阻塞了那个线程,鼠标点击之类的东西就不会得到处理(因为线程忙着什么都不做,除了计算你的数据),以及所以你的GUI冻结了。

至于如何改变你的计划以便不会发生,你有几个选择:

  1. 您可以将qApp-> processEvents()调用到您的计算循环中。这样,Qt将有机会在计算时处理鼠标点击等事情。这是最简单的方法,但如果您不小心,它可能会咬你 - 例如,如果您设置了其他代码以便鼠标单击导致您的MainWindow被删除那么你很可能会崩溃,因为在processEvents()返回后它发现自己在现在删除的MainWindow对象(!)的on_pushButton_clicked()方法中执行。

  2. 您可以生成一个单独的线程(使用QThread对象)并在那里运行您的计算循环。这可能是最有效的方法,因为在多核CPU上它会让GUI事件循环在一个核心上运行,而计算循环同时在另一个核心上运行,因此两个循环都不会减慢另一个核心。请注意,这种方法仅在您的计算循环不触及任何Qt GUI内容时才有效 - Qt的GUI小部件只能由GUI线程访问,如果您尝试检查它们或从不同的线程修改它们,会发生不好的事情。

  3. 你可以"展开"你的循环使它不再是一个同步循环,而更像是一个状态机:也就是说,将计算的状态变量(spectrum_sensed,Sn,sigma,alpha和ydata)的声明移出该方法,现在它们现在是MainWindow类的成员变量。然后编写一个Slot方法,它只执行while循环的一次迭代(或者可能是少量迭代,具体取决于每次迭代需要多长时间),然后(在几十毫秒内)调用QTimer :: singleShot(0,this ,SLOT(TheCalculationSlotMethodName())并返回。那个QTimer :: singleShot()调用将导致你的计算槽方法在Qt事件循环的下一次迭代中再次被调用,于是它可以做更多的计算。当用户单击"停止"按钮时,只需让你的on_stopButton_Pushed()槽设置一个布尔值或类似的东西,以便你的计算方法知道不再调用QTimer :: singleShot()。我喜欢这种方法因为竞争条件或再入境问题的风险很小。