QT-如何在 QThread 中使用 QWidget?

Posted

技术标签:

【中文标题】QT-如何在 QThread 中使用 QWidget?【英文标题】:QT-How to utilize QWidget with QThread? 【发布时间】:2020-07-15 07:42:07 【问题描述】:

我正在通过 QT 制作一些 GUI。 我几乎完成了我的工作,但我很难处理 Qthread。 我的目标是测量电机的位置(它移动)并将其显示在 Qtextbrowser 上,同时在主线程中运行另一个函数。当我写下面这样的代码时,人们说我不能直接在线程中使用 QTextBrowser(Qwidget),所以我正在寻找如何将位置值返回给主线程。能帮我一下吗? MDCE 是另一个标题中的一个类,我附加的代码是我的第一个代码的一些部分。

void MotorPort::StartThread(MDCE* com, QTextBrowser* browser)


    thread1 = QThread::create(std::bind(&MotorPort::MeasureLocation,this,com,browser));
    thread1 -> start();


void MotorPort::MeasureLocation(MDCE* com, QTextBrowser* browser)

    double location;
    while(1)
    
        location = CurrentLocation(com); \\return current position value
        browser->setText(QString::number(location));
        if (QThread::currentThread()->isInterruptionRequested()) return ;
    


void MotorPort::stopMeasure()

    thread1->requestInterruption();
    if (!thread1->wait(3000))
    
        thread1->terminate();
        thread1->wait();
    
    thread1 = nullptr;

【问题讨论】:

您可能无法从其他线程访问 GUI 内容。 Qt 小部件不是线程安全的。我在对SO: How to alter Qt Widgets in WINAPI threads? 的回答中写了一些关于这个主题的内容(忽略了问题的 Windows 特定方面)。 【参考方案1】:

您应该使用 Qt 信号/槽机制来进行迭代线程通知,例如。首先改变你的MotorPort类定义来声明一个信号location_changed...

class MotorPort: public QObject 
    Q_OBJECT;
signals:
    void location_changed(QString location);
    ...

现在,与其直接调用QTextBrowser::setText 不如直接调用MotorPort::MeasureLocation 应该发出location_changed 信号...

void MotorPort::MeasureLocation (MDCE *com, QTextBrowser *browser)

    while (true) 
        double location = CurrentLocation(com);

        /*
         * Emit signal to notify of location update.
         */
        emit location_changed(QString::number(location));
        if (QThread::currentThread()->isInterruptionRequested())
            return ;
    

最后,更新MotorPort::StartThread,将信号连接到浏览器的setText槽...

void MotorPort::StartThread (MDCE *com, QTextBrowser *browser)

    connect(this, &MotorPort::location_changed, browser, &QTextBrowser::setText);
    thread1 = QThread::create(std::bind(&MotorPort::MeasureLocation, this, com, browser));
    thread1->start();

【讨论】:

真的真的非常感谢!问题已经解决了!你能向我解释一下连接功能中的“这个”吗?因为我刚学C++一个月就做了QT程序,我不知道'this'。 this 只是一个 c++ keyword 用于引用当前对象实例——与 Qt 无关。关于connect 调用,您应该阅读definitive documentation 关于信号和插槽的内容——这是Qt 的一个关键特性,因此彻底理解很重要。 非常感谢您的回答!谢谢你的帮助:)

以上是关于QT-如何在 QThread 中使用 QWidget?的主要内容,如果未能解决你的问题,请参考以下文章

帮助 QT 编程与 QThread 类,如何使用它

如何在 QT 中停止 qThread [重复]

如何在 Qt 中正确终止 QThread?

如何终止 QThread

Qt on Python 中的 QThread

如何向 Qt 中 QThread 类的特定对象发出信号?