通过 Signal/Slot 机制将 QString 传递给 QThread

Posted

技术标签:

【中文标题】通过 Signal/Slot 机制将 QString 传递给 QThread【英文标题】:Passing QString to QThread through Signal/Slot mechanism 【发布时间】:2015-04-16 08:57:59 【问题描述】:

我无法让我的 MainWindow 与 Worker 线程通信。我正在使用通常的 SIGNAL/SLOT 机制传递 QString 对象。我的程序应该将 QString "Alice" 从 MainWindow 传输到在 QThread 中处理的类 Worker 的工作对象,然后再返回。代码编译没有错误,并且在我的 MacBook Pro 上使用 Qt 4.8 和 Clang 运行顺利。这是显示我的问题的最少代码。

ma​​inwindow.h

#ifndef MAINWINDOW_H
#define MAINWINDOW_H

#include <QMainWindow>
#include <worker.h>

namespace Ui 
class MainWindow;


class MainWindow : public QMainWindow

    Q_OBJECT

public:
    explicit MainWindow(QWidget *parent = 0);
    void ThreadedWork();
    ~MainWindow();

private:
    Ui::MainWindow *ui;
    QString name;
private slots:
    void errorString(QString);

public slots:
    void getFromWorker(QString);

signals:
    void sendToWorker(QString);
;

#endif // MAINWINDOW_H

ma​​inwindow.cpp

#include "mainwindow.h"
#include "ui_mainwindow.h"
#include <QThread>
#include <QDebug>

MainWindow::MainWindow(QWidget *parent) : QMainWindow(parent), ui(new Ui::MainWindow)

    ui->setupUi(this);

    name = "Alice";
    qDebug() << "The name in MainWindow is: " << name << " from ThreadID = " << QThread::currentThreadId();
    ThreadedWork();
    qDebug() << "Name sent from the Worker Thread is: " << name;


MainWindow::~MainWindow()

    delete ui;


void MainWindow::errorString(QString string)

    qDebug() << "The error from the threaded process is: " << string;


void MainWindow::ThreadedWork()

    Worker* worker = new Worker;
    emit sendToWorker(name);
    connect(this,SIGNAL(sendToWorker(QString)),worker,SLOT(getFromMain(QString)));
    connect(worker,SIGNAL(sendToMain(QString)),this,SLOT(getFromWorker(QString)));

    QThread *thread = new QThread;
    worker->moveToThread(thread);

    connect(worker, SIGNAL(error(QString)), this, SLOT(errorString(QString)));
    connect(thread, SIGNAL(started()), worker, SLOT(process()));
    connect(worker, SIGNAL(finished()), thread, SLOT(quit()));
    connect(worker, SIGNAL(finished()), worker, SLOT(deleteLater()));
    connect(thread, SIGNAL(finished()), thread, SLOT(deleteLater()));

    thread->start();


void MainWindow::getFromWorker(QString someName) //slot implementation

    name = someName;

worker.h

#ifndef WORKER_H
#define WORKER_H

#include <QObject>

class Worker : public QObject

    Q_OBJECT
public:
    explicit Worker(Worker * parent = 0);
    ~Worker();

signals:
    void sendToMain(QString);
    void error(QString err);
    void finished();

public slots:
    void getFromMain(QString);
    void process();

private:
    QString name;
;

#endif // WORKER_H

worker.cpp

#include "worker.h"
#include <QDebug>
#include <QThread>

Worker::Worker(Worker * parent)




Worker::~Worker()




void Worker::process() 
    // allocate resources using new here
    qDebug() << "name recieved from Main is: " << name;
    qDebug() << "name passed to Worker Thread is: " << name << " having ThreadID = " << QThread::currentThreadId();
    emit sendToMain(name);
    emit finished();


void Worker::getFromMain(QString someName) // slot implementation

    name = someName;

我的输出是:

The name in MainWindow is:  "Alice"  from ThreadID =  0x7fff7de7a300 
Name sent from the Worker Thread is:  "Alice" 
name recieved from Main is:  "" 
name passed to Worker Thread is:  ""  having ThreadID =  0x1107a9000

如上所述,我无法将 QString "Alice" 传递给工作人员。我在这里错过了什么?

【问题讨论】:

尝试添加Qt::QueuedConnection 作为连接到worker的第5个参数。 一个问题是在将插槽连接到它之前发出信号:emit sendToWorker(name);连接(这个,信号(sendToWorker(QString))... 我是否可以推断(也有点明显)信号只有在连接后才能在代码中发出? @marital_weeping 当然,否则disconnect() 技术将毫无用处。文档说:“Qt 的信号和槽机制确保如果将信号连接到槽,则将在正确的时间使用信号的参数调用槽。” @marital_weeping 您好,我对您的代码有疑问。是否可以使用finished() 信号将“名称”变量发送给父级并避免使用sendToMain() 信号? 【参考方案1】:

ThreadedWork() 方法的问题:

您首先发出信号emit sendToWorker(name);,然后只有他们将这个信号连接到插槽-这是您失败的根源。

像这样换行:

void MainWindow::ThreadedWork()

    Worker* worker = new Worker;

    connect(this,SIGNAL(sendToWorker(QString)),worker,SLOT(getFromMain(QString)));
    connect(worker,SIGNAL(sendToMain(QString)),this,SLOT(getFromWorker(QString)));

    emit sendToWorker(name);

    QThread *thread = new QThread;
    worker->moveToThread(thread);
...

我可能会得到预期的结果:

The name in MainWindow is:  "Alice"  from ThreadID =  0xcbc
Name sent from the Worker Thread is:  "Alice"
name recieved from Main is:  "Alice"
name passed to Worker Thread is:  "Alice"  having ThreadID =  0xff8

【讨论】:

以上是关于通过 Signal/Slot 机制将 QString 传递给 QThread的主要内容,如果未能解决你的问题,请参考以下文章

QT 中 关键字讲解(emit,signal,slot)

详解 Qt 线程间共享数据(使用signal/slot传递数据,线程间传递信号会立刻返回,但也可通过connect改变)

为啥我的数据不能在带有 SIGNAl/SLOT 的表格之间传输?

PySide2 使用 QProgressBar 作为信号参数

QT中的小细节

Qt for Qt:如何连接到具有新信号/插槽风格的信号?