user-interface - 跨线程的Qt信号,一个是GUI线程?

标签 user-interface qt signals-slots qthread

在 Qt 中使用 moveToThread 将对象从一个线程移动到另一个线程是什么意思?甚至在使用 moveToThread 之前,一切似乎都在工作,它将对象从一个线程(GUI 线程)移动到另一个线程(工作)并且 Qt:connect 调用对象上的适当插槽。

对象所在的位置、GUI 线程或工作线程有什么区别吗?

编辑:
我做了一个小程序,但我不明白 QThread 是如何与 Signal 和 slot 函数一起工作的,如果您能通过示例解释 moveToThread 的用途,我将不胜感激

#include <QtGui/QApplication>
#include <QPushButton>
#include <QHBoxLayout>
#include <QLineEdit>
#include <QString>
#include "mythread.h"
//GUI calls a thread to do some job and sub update the text box once it is done
int main(int argc, char *argv[])
{
    QApplication a(argc, argv);
    QWidget w;
    QHBoxLayout * pH = new QHBoxLayout(&w);
    QPushButton * pushButton = new QPushButton("asdad");
    QLineEdit * lineEdit = new QLineEdit("AAA");
    pH->addWidget(pushButton);
    pH->addWidget(lineEdit);
    w.setLayout(pH);
    w.show();
    MyThread thread;
    qDebug("Thread id %d",(int)QThread::currentThreadId());
    QObject::connect(pushButton,SIGNAL(clicked()),&thread,SLOT(callRun())) ;
    QObject::connect(&thread,SIGNAL(signalGUI(QString)),lineEdit,SLOT(setText(QString)));
    return a.exec();
}

#ifndef MYTHREAD_H
#define MYTHREAD_H

#include <QThread>
#include <QMutex>

class MyThread : public QThread
{
    Q_OBJECT
public:
    MyThread();
public slots:
    void callRun();
    void run();
 signals:
    void signalGUI(QString);
private:
    QMutex mutex;

};

#endif // MYTHREAD_H


#include "mythread.h"
#include <QDebug>
#include <QString>
#include <QMutexLocker>

MyThread::MyThread()
{
}
 void MyThread::callRun()
 {

     qDebug("in thread");
    if(!isRunning())
     {
        this->start(LowestPriority);
        exec();
    }
    else
    {
        run();
    }

 }
 void MyThread::run()
 {
     QMutexLocker fn_scope(&mutex);
     static int a = 0;
    ++a;
     qDebug("Thread id inside run %d",(int)QThread::currentThreadId());
     this->sleep(3);
     static QString number;
     QString temp;
     number += temp.setNum(a);
     emit signalGUI(number);
 }

最佳答案

看看Signals and slots across threads .如果您总是使用信号和槽来与工作线程通信,Qt 会在需要时为您处理 moveToThread 并且您使用了正确的连接。

编辑:我猜这篇文章的作者看到了他的问题,因为他在实际创建线程之前在构造函数中调用了 start 。换句话说,不要盲目相信第三方代码。

编辑:为了回应您的评论,请查看 Mandelbrot例如,在 MandelbrotWidget Class Implementation 下标题:

With queued connections, Qt must store a copy of the arguments that were passed to the signal so that it can pass them to the slot later on. Qt knows how to take of copy of many C++ and Qt types, but QImage isn't one of them. We must therefore call the template function qRegisterMetaType() before we can use QImage as parameter in queued connections.



我相信这有点过时了,这里是 valid meta types .由于跨线程的信号和槽使用排队连接,因此在大多数情况下您不必执行 moveToThread 调用。

编辑:
我将尝试用一个类似的例子来解释事情:

我的线程.h:
#ifndef MYTHREAD_H
#define MYTHREAD_H

#include <QThread>
#include <QMutex>

class MyThread : public QThread
{
   Q_OBJECT

protected:
   virtual void run();

signals:
   void signalGUI(QString);
};

#endif // MYTHREAD_H

我的线程.cpp:
#include "mythread.h"
#include <QString>

void MyThread::run()
{
   qDebug("Thread id inside run %d",(int)QThread::currentThreadId());
   static int run = 0;
   QString temp = QString("Run: %1").arg(run++);
   qDebug("String address inside run %p", &temp);
   emit signalGUI(temp);
}

mylineedit.h
#ifndef MYLINEEDIT_H
#define MYLINEEDIT_H

#include <QLineEdit>

class MyLineEdit : public QLineEdit
{
Q_OBJECT
public:
    explicit MyLineEdit(QWidget *parent = 0);

public slots:
    void setText(const QString &string);

};

#endif // MYLINEEDIT_H

mylineedit.cpp
#include "mylineedit.h"
#include <QThread>

MyLineEdit::MyLineEdit(QWidget *parent) :
    QLineEdit(parent)
{
}

void MyLineEdit::setText(const QString &string)
{
   qDebug("Thread id inside setText %d",(int)QThread::currentThreadId());
   qDebug("String address inside setText %p\n", &string);
   QLineEdit::setText(string);
}

主.cpp:
#include <QApplication>
#include <QPushButton>
#include <QHBoxLayout>
#include "mythread.h"
#include "mylineedit.h"

//GUI calls a thread to do some job and sub update the text box once it is done
int main(int argc, char *argv[])
{
   QApplication a(argc, argv);
   QWidget w;
   QHBoxLayout * pH = new QHBoxLayout(&w);
   QPushButton * pushButton = new QPushButton("Run Thread", &w);
   MyLineEdit * lineEdit = new MyLineEdit(&w);

   pH->addWidget(pushButton);
   pH->addWidget(lineEdit);
   w.show();

   MyThread thread;
   qDebug("Thread id %d",(int)QThread::currentThreadId());
   QObject::connect(pushButton,SIGNAL(clicked()),&thread,SLOT(start())) ;
   QObject::connect(&thread,SIGNAL(signalGUI(const QString&)),lineEdit,SLOT(setText(const QString&)));
   return a.exec();
}

单击按钮后的示例输出:

线程 ID 1088110320
线程 id 内运行 1093176208
运行中的字符串地址 0x41288350
setText 内的线程 ID 1088110320
setText 0x974af58 内的字符串地址

如您所见,运行线程与主 GUI 线程不同。此外,即使您传递了对 QString 的 const 引用,由于它跨越了线程边界,因此它会复制它。
强烈鼓励您阅读 Threads and QObject .

关于user-interface - 跨线程的Qt信号,一个是GUI线程?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/2086142/

相关文章:

ios - Swift 如何将 View 转换为横向、内部纵向设备方向?有可能的?

qt - 如何使用样式表更改 QPushButton 图标/文本间距?

java - 用于 Java 的 Qt Web 引擎?

c++ - itemChanged 信号在应用程序启动时没有更改项目时起作用

java - 什么是最好的 GUI builder for swing

ios - 使用 iOS 8 在 iPad 上正确呈现 UIAlertController

iphone - 如何制作一个漂亮的 UITextView 并根据需要扩展(就像 SMS 应用程序中使用的那样)?

c++ - Shared_Ptr 影响了我的应用程序的性能

c++ - 仅当 QCheckBox 被选中时才发出信号

c++ - 是否可以将宏函数作为 QMetaMethod 标记?