C++ Qt/C++;:可检查按钮和无限循环

C++ Qt/C++;:可检查按钮和无限循环,c++,qt,C++,Qt,我正在编写一个QtGUI,我正在尝试实现一个新功能,我现在想要得到一个精确的结果,但不是如何编写它。 我正在尝试添加一个可检查按钮,当选中该按钮时,该按钮将运行一个只在按钮未选中时才会停止的函数,但每秒钟窗口上的一个绘图区域都会更新一次(让我看到函数的多次执行如何改变我的数据)。看起来我需要使用一些QThread对象,但仅仅是处理按钮的部分对我来说已经是违反直觉的,我一直在尝试使用autoRepeatDelay和autoRepeatInterval,而没有掌握它们的功能以及它们对我的用处 我想我

我正在编写一个QtGUI,我正在尝试实现一个新功能,我现在想要得到一个精确的结果,但不是如何编写它。 我正在尝试添加一个可检查按钮,当选中该按钮时,该按钮将运行一个只在按钮未选中时才会停止的函数,但每秒钟窗口上的一个绘图区域都会更新一次(让我看到函数的多次执行如何改变我的数据)。看起来我需要使用一些QThread对象,但仅仅是处理按钮的部分对我来说已经是违反直觉的,我一直在尝试使用autoRepeatDelay和autoRepeatInterval,而没有掌握它们的功能以及它们对我的用处

我想我试图编写的代码并不是真正的原创,我应该知道实现它的步骤,或者是一个代码示例

编辑:
根据最初的回答(顺便说一下,谢谢你),我的问题可能不清楚。在线程方面,我想实现一个无限循环,只有当按下按钮进入按下位置(这是一个可检查的按钮)时才开始,离开时才停止。我尝试做的第一个版本(有一段时间(button->isChecked()循环)将完全冻结,因为应用程序将运行循环,gui将冻结,按钮无法关闭(因此在单独的线程中运行它的想法).瞧!我希望这是一个更清晰的表述。提前谢谢你。

我不知道我是否真的明白你想做什么,但我会尽力回答

首先,您需要一个发送开始和停止信息的按钮来控制线程。您可以使用复选框开始。此复选框在其状态更改时发送信号。将此信号连接到根据发送的布尔值执行开始线程和停止的插槽

其次,在你的线程中,你需要启动事件循环。之后,设置一个定时器,在每次超时后调用你重新绘制

希望有帮助


PS:注意线程和Qt对象的执行上下文。

这里有一些可能有效的简单框架。在不知道确切要求的情况下,它可能适合您的问题,也可能不适合您的问题。希望它能给您一些实际有帮助的提示

void Ui::buttonPressedSlot(bool checked){
    if (checked){
        Processor *processor = new Processor;
        connect(this, SIGNAL(abortCalculations()), processor, SLOT(abort()), Qt::QueuedConnection);
        connect(processor, SIGNAL(updateNeeded()), this, SLOT(updateGui()), Qt::QueuedConnection);
        QThreadPool::globalInstance()->start(processor);
    } else {
        emit abortCalculations(); // this is a signal in your UI class
    }
}
然后,您可以使用以下公式进行计算

class Processor : public QObject, public QRunnable{ // QObject must always be first in multiple inheritance
    Q_OBJECT
public:
    ~Processor();

    void run();

public slots:
    void abort();
    void doCalculations();

signals:
    void updateNeeded(); // connect this to the GUI to tell it to refresh

private:
    QScopedPointer<QEventLoop> loop;
};

Processor::~Processor(){
    abort();
}

void Processor::run() {

    loop.reset(new QEventLoop);

    QTimer timer;
    connect(&timer, SIGNAL(timeout()), this, SLOT(doCalculations()));
    timer.setInterval(1000);
    timer.start();

    loop->exec();
 }

 void Processor::abort(){
    if (!loop.isNull()){
        loop->quit();
    }
 }

 void Processor::doCalculations(){
     // do whatever needs to be done

     emit updateNeeded();
 }
类处理器:public QObject,public QRunnable{//QObject在多重继承中必须始终位于第一位
Q_对象
公众:
~Processor();
无效运行();
公众时段:
无效中止();
无效计算();
信号:
void updateNeeded();//将其连接到GUI以通知其刷新
私人:
QScopedPointer环;
};
处理器::~Processor(){
中止();
}
无效处理器::运行(){
复位(新的QEventLoop);
定时器;
连接(&计时器,信号(超时()),此,插槽(doCalculations());
定时器设置间隔(1000);
timer.start();
循环->执行();
}
无效处理器::中止(){
如果(!loop.isNull()){
循环->退出();
}
}
无效处理器::doCalculations(){
//做任何需要做的事
发出updateNeeded();
}

您需要在infinite循环中执行某些函数,直到选中复选框为止?如果是-请更新您的问题,使其易于理解。@DmitrySazonov刚刚记下您的评论并更新了问题,谢谢。另一种方法是创建一个计时器并在每个计时器事件上调用您的函数。因为任何无限循环,即使在其他情况下也是如此r线程,可能会导致很多“滞后”.的确,这真的很奇怪,我设法在另一个线程中运行了循环,但它仍然完全冻结了gui,我甚至放弃了可检查按钮,选择了一个只在单击时开始/停止的按钮,但一旦开始,整个事情就冻结了。谢谢,是的,这正是我想要的,只是我更喜欢一个可检查的按钮(可保持在按下位置)而不是一个复选框,只是一个风格的问题。对于其余部分,我看起来确实像是一个正确的实现方法。我将查看有关qt线程的文档,也许可以作为一个示例来说明方法。要使用按钮,您只需连接到单击的信号,检查并保护按钮的状态,并将其用作复选框state.Hi再次说明,我按照您给我的思路实现了一些东西,但在循环启动后仍然存在冻结整个GUI的问题(即使它在另一个线程中)。我也在一个4核CPU上运行它,所以这应该不是一个问题,但它是…你知道解决方案或计数器吗?我知道在使用线程w/Qt时存在一些问题。我可以建议你在运行线程时检查上下文ID。当发送超时时,可能你的计时器在主线程中。当我使用QThread时,我必须这是一个将信号重新发送到我的主线程的接口。首先,非常感谢您的建议(我将尝试实现这个soonish,此时此刻我手中还有其他东西)但是,在我看来,您的代码在每次执行循环时都会更新PaintArea,而我希望它只在计时器结束时完成,因此我想我必须将
emit updateNeeded()
移动到运行()的末尾声明。而且,我真的需要我的程序在一个循环执行过程中不中止,但是等待它完成并停止。我不熟悉这个QEntRoop,但它们本身支持吗?谢谢!<代码> qEngLoop < /Cord>是Qt中事件消息调度的底层控制器。如果您使用了<代码> QCoreApplication::exec()或
QDialog::exec()
,则您在不知不觉中使用了
QEventLoop
。如果将
emit updateNeeded()
移动到
run()
函数的末尾,则仅在中止后才会发出信号。此时,它将在
doCalculations()的末尾发出
函数,该函数本身每年调用一次