运行 连续输入代码,直到按下 "Stop"
Run the code continuously until "Stop" is pressed
我想在按下 "Start" 按钮时执行一些代码,它会继续执行 运行 直到我按下 "Stop"。
但是,使用下面的代码,一旦我按下 "Start",我就不能再按下 "Stop":
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();
}
}
Qt 的 GUI 运行s 在一个线程中,如果您的代码阻塞了该线程,鼠标点击之类的事情将永远不会得到处理(因为线程正忙于计算您的数据),所以你的 GUI 冻结了。
至于如何更改您的程序以免发生这种情况,您有以下几种选择:
您可以直接调用 qApp->processEvents() 到您的计算循环中。这样 Qt 将有机会在您计算时处理诸如鼠标点击之类的事情。这是最简单的方法,但如果你不小心,它可能会伤害你——例如,如果你设置了一些其他代码,鼠标点击导致你的 MainWindow 被删除,那么你很可能会崩溃因为在 processEvents() returns 之后,它发现自己在现在已删除的 MainWindow 对象 (!) 的 on_pushButton_clicked() 方法中执行。
您可以生成一个单独的线程(使用 QThread 对象)和 运行 您的计算循环。这可能是最有效的方法,因为在多核 CPU 上,它会让 GUI 事件循环 运行 在一个内核上,同时计算循环在另一个内核上同时 运行s,等等两个循环都不会减慢另一个循环的速度。请注意,此方法仅在您的计算循环不涉及任何 Qt GUI 内容时才有效——Qt 的 GUI 小部件只能由 GUI 线程访问,并且如果您尝试从不同的线程检查或修改它们,就会有不好的事情发生。
你可以"unwrap"你的循环,这样它就不再是一个同步循环,而是更像一个状态机:也就是说,移动你的计算状态变量的声明(spectrum_sensed, Sn, sigma, alpha, 和 ydata) 退出方法,因此它们现在是 MainWindow class 的成员变量。然后编写一个 Slot 方法,它只执行 while 循环的一次迭代(或者可能是少量迭代,具体取决于每次迭代需要多长时间),然后(在几十毫秒内)调用 QTimer::singleShot(0,这个,SLOT(TheCalculationSlotMethodName()) 和 returns。那个 QTimer::singleShot() 调用将导致你的计算槽方法在 Qt 事件循环的下一次迭代中被再次调用,于是它可以做多一点计算。当用户单击 "Stop" 按钮时,只需让您的 on_stopButton_Pushed() 插槽设置一个布尔值或其他内容,以便您的计算方法知道不调用 QTimer::singleShot () 了。我喜欢这种方法,因为竞争条件或重入问题的风险很小。
我想在按下 "Start" 按钮时执行一些代码,它会继续执行 运行 直到我按下 "Stop"。
但是,使用下面的代码,一旦我按下 "Start",我就不能再按下 "Stop":
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();
}
}
Qt 的 GUI 运行s 在一个线程中,如果您的代码阻塞了该线程,鼠标点击之类的事情将永远不会得到处理(因为线程正忙于计算您的数据),所以你的 GUI 冻结了。
至于如何更改您的程序以免发生这种情况,您有以下几种选择:
您可以直接调用 qApp->processEvents() 到您的计算循环中。这样 Qt 将有机会在您计算时处理诸如鼠标点击之类的事情。这是最简单的方法,但如果你不小心,它可能会伤害你——例如,如果你设置了一些其他代码,鼠标点击导致你的 MainWindow 被删除,那么你很可能会崩溃因为在 processEvents() returns 之后,它发现自己在现在已删除的 MainWindow 对象 (!) 的 on_pushButton_clicked() 方法中执行。
您可以生成一个单独的线程(使用 QThread 对象)和 运行 您的计算循环。这可能是最有效的方法,因为在多核 CPU 上,它会让 GUI 事件循环 运行 在一个内核上,同时计算循环在另一个内核上同时 运行s,等等两个循环都不会减慢另一个循环的速度。请注意,此方法仅在您的计算循环不涉及任何 Qt GUI 内容时才有效——Qt 的 GUI 小部件只能由 GUI 线程访问,并且如果您尝试从不同的线程检查或修改它们,就会有不好的事情发生。
你可以"unwrap"你的循环,这样它就不再是一个同步循环,而是更像一个状态机:也就是说,移动你的计算状态变量的声明(spectrum_sensed, Sn, sigma, alpha, 和 ydata) 退出方法,因此它们现在是 MainWindow class 的成员变量。然后编写一个 Slot 方法,它只执行 while 循环的一次迭代(或者可能是少量迭代,具体取决于每次迭代需要多长时间),然后(在几十毫秒内)调用 QTimer::singleShot(0,这个,SLOT(TheCalculationSlotMethodName()) 和 returns。那个 QTimer::singleShot() 调用将导致你的计算槽方法在 Qt 事件循环的下一次迭代中被再次调用,于是它可以做多一点计算。当用户单击 "Stop" 按钮时,只需让您的 on_stopButton_Pushed() 插槽设置一个布尔值或其他内容,以便您的计算方法知道不调用 QTimer::singleShot () 了。我喜欢这种方法,因为竞争条件或重入问题的风险很小。