从后台工作线程修改 Qt GUI [英] Modify Qt GUI from background worker thread

查看:38
本文介绍了从后台工作线程修改 Qt GUI的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

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

I work in Qt and when I press the button GO I need to continuously send packages to the network and modify the interface with the information I receive.

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

The problem is that I have a while(1) in the button so the button never finishes so the interface is never updated. I thought to create a thread in the button and put the while(){} code there.

我的问题是如何从线程修改界面?(例如,如何从线程修改文本框?

My question is how can I modify the interface from the thread? (For example how can I modify a textBox from the thread ?

推荐答案

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

Important thing about Qt is that you must work with Qt GUI only from GUI thread, that is main thread.

这就是为什么正确的做法是从worker通知主线程,而主线程中的代码实际上会更新文本框、进度条或其他东西.

That's why the proper way to do this is to notify main thread from worker, and the code in main thread will actually update text box, progress bar or something else.

我认为最好的方法是使用 QThread 而不是 posix 线程,并使用 Qt 信号 在线程之间进行通信.这将是你的工人,thread_func 的替代者:

The best way to do this, I think, is use QThread instead of posix thread, and use Qt signals for communicating between threads. This will be your worker, a replacer of 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 中的信号具有相同原型的:

In your widget, define a slot with same prototype as signal in .h:

class MyWidget : public QWidget {
    // Your gui code

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

在.cpp中实现这个功能:

In .cpp implement this function:

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

现在在你想要生成线程的地方(点击按钮):

Now in that place where you want to spawn a thread (on button click):

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 在这里.

After you connect signal and slot, emiting slot with emit progressChanged(...) in worker thread will send message to main thread and main thread will call the slot that is connected to that signal, onProgressChanged here.

P.s.我还没有测试代码,所以如果我在某处错了,请随时提出修改建议

这篇关于从后台工作线程修改 Qt GUI的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆