一尘不染

从后台工作线程修改Qt GUI

linux

我在Qt工作,当我按下GO按钮时,我需要不断将软件包发送到网络并使用收到的信息修改界面。

问题是我while(1)在按钮中有一个,所以按钮永不结束,所以界面永不更新。我想在按钮中创建一个线程并将while(){}代码放在那里。

我的问题是如何从线程修改接口?(例如,如何从线程修改textBox?


阅读 623

收藏
2020-06-02

共1个答案

一尘不染

关于Qt的重要一点是, 必须 仅从GUI线程(即主线程)使用Qt GUI。

这就是为什么执行此操作的正确方法是从worker 通知 主线程,并且主线程中的代码实际上将更新文本框,进度栏或其他内容。

我认为,做到这一点的最佳方法是使用QThread而不是posix线程,并使用Qt 信号
在线程之间进行通信。这将是您的工作人员,是以下人员的替代者thread_func

class WorkerThread : public QThread {
    void run() {
        while(1) {
             // ... hard work
             // Now want to notify main thread:
             emit progressChanged("Some info");
        }
    }
    // Define signal:
    signals:
    void progressChanged(QString info);
};

在窗口小部件中,定义一个与.h中的信号具有相同原型的 插槽

class MyWidget : public QWidget {
    // Your gui code

    // Define slot:
    public slots:
    void onProgressChanged(QString info);
};

在.cpp中实现此功能:

void MyWidget::onProgressChanged(QString info) {
    // Processing code
    textBox->setText("Latest info: " + info);
}

现在在您要生成线程的位置(单击按钮):

void MyWidget::startWorkInAThread() {
    // Create an instance of your woker
    WorkerThread *workerThread = new WorkerThread;
    // Connect our signal and slot
    connect(workerThread, SIGNAL(progressChanged(QString)),
                          SLOT(onProgressChanged(QString)));
    // Setup callback for cleanup when it finishes
    connect(workerThread, SIGNAL(finished()),
            workerThread, SLOT(deleteLater()));
    // Run, Forest, run!
    workerThread->start(); // This invokes WorkerThread::run in a new thread
}

将信号和插槽连接后,emit progressChanged(...)在工作线程中发出带有插槽的插槽将向主线程发送消息,并且主线程将在onProgressChanged此处调用与该信号连接的插槽。

附言:我尚未测试代码,所以如果我在某处输入错误,请随时提出修改建议

2020-06-02