您的位置:首页 > 编程语言 > Qt开发

qt线程间信号与槽

2018-03-28 09:23 369 查看
qt线程的用法,其实我们在官网上看到的用法比较简单,很多时候会出现奇怪的现象。下面我们来看看,

1,qt信号与槽方式进行通信

QT就是把这个signal包装成一个 QEvent,放到消息队列里。线程的QThread::exec()会从消息队列里取消息,然后调用 signal关联的几个slot。这种方式既可以在线程内传递消息,也可以跨线程传递消息。

先看界面:



我用代码来测试:

mainwindow.h

#ifndef MAINWINDOW_H
#define MAINWINDOW_H

#include <QMainWindow>
#include <QThread>
#include "testthread.h"
namespace Ui {
class MainWindow;
}

class MainWindow : public QMainWindow
{
Q_OBJECT

public:
explicit MainWindow(QWidget *parent = 0);
~MainWindow();
public slots:
void handleResults(const QString &);
signals:
void start(const QString &);
void stop(const QString &);
void sendData1(const QString &);
void sendData2(const testString &);
private slots:
void on_pushButton_clicked();

void on_pushButton_2_clicked();

void on_pushButton_3_clicked();

void on_pushButton_4_clicked();

private:
Ui::MainWindow *ui;
QThread workerThread;
};

#endif // MAINWINDOW_H


mainwindow.cpp
#include "mainwindow.h"
#include "ui_mainwindow.h"

#include <QDebug>
MainWindow::MainWindow(QWidget *parent) :
QMainWindow(parent),
ui(new Ui::MainWindow)
{
ui->setupUi(this);
testthread *worker = new testthread;
qRegisterMetaType<testString>("testString");
qRegisterMetaType<testString>("testString&");
worker->moveToThread(&workerThread);
// connect(&workerThread, &QThread::finished, worker, &QObject::deleteLater);
// connect(this, &MainWindow::operate, worker, &testthread::doWork);
// connect(this, &MainWindow::operate2, worker, &testthread::doWork);
// connect(worker, &testthread::resultReady, this, &MainWindow::handleResults);
connect (this,SIGNAL(start(const QString &)),worker,SLOT(startWork(const QString &)));
connect (this,SIGNAL(stop(const QString &)),worker,SLOT(stopWork(const QString &)));
connect (this,SIGNAL(sendData1(const QString &)),worker,SLOT(acceptData1(const QString &)));
connect (this,SIGNAL(sendData2(const testString &)),worker,SLOT(acceptData2(const testString &)));
connect (worker,SIGNAL(resultReady(const QString &)),this,SLOT(handleResults(const QString &)));
workerThread.start();
}

MainWindow::~MainWindow()
{
delete ui;
workerThread.quit();
workerThread.wait();
}

void MainWindow::handleResults(const QString &str)
{
qDebug()<<str;
}

void MainWindow::on_pushButton_clicked()
{
emit start("start");
}

void MainWindow::on_pushButton_2_clicked()
{
emit stop("stop");
}

void MainWindow::on_pushButton_3_clicked()
{
emit sendData1("niubi");
}

void MainWindow::on_pushButton_4_clicked()
{
testString str;
str.a = "shabi";
emit sendData2(str);
}


testthread.h
#ifndef TESTTHREAD_H
#define TESTTHREAD_H

#include <QObject>

class testString
{
public:
QString a;
};

class testthread : public QObject
{
Q_OBJECT
public:
explicit testthread(QObject *parent = 0);
public slots:
void startWork(const QString ¶meter) ;
void stopWork(const QString ¶meter) ;
void acceptData1(const QString ¶meter) ;
void acceptData2(const testString ¶meter) ;
signals:
void resultReady(const QString &result);
private:
bool state;
};

#endif // TESTTHREAD_H

testthread.cpp

#include "testthread.h"

#include <QDebug>

#include <QThread>

testthread::testthread(QObject *parent) : QObject(parent)

{

state = false;

}


void testthread::startWork(const QString ¶meter)

{

if(parameter == "start")

{

QString result= "我槽你吗!";

while(1)

{

emit resultReady(result);//这里发送

QThread::sleep (1);

if(state==true)

{

break;

}

}

}

}


void testthread::stopWork(const QString ¶meter)

{

if(parameter == "stop")

{

state = true;

}

}


void testthread::acceptData1(const QString ¶meter)

{

qDebug()<<parameter;

}


void testthread::acceptData2(const testString ¶meter)

{

qDebug()<<parameter.a;

}



我们就用上面的四个文件来测试:
1,信号与槽线程间连接的数据类型问题,qt自带的元数据类型,想没有问题的,但是我们自己建立了一个testString,

如果在mainwindow的构造函数里面,没有注册到元数据属性里面,

qRegisterMetaType<testString>("testString");

qRegisterMetaType<testString>("testString&");


就会提示:

QObject::connect: Cannot queue arguments of type 'testString'
(Make sure 'testString' is registered using qRegisterMetaType().)
所以,自定义数据类型必须注册到元对象里面才可以使用。
2,当我们点击界面开始后界面,会打印出曹尼玛,但是点击停止就是停止不了,信号和槽也是连接了的,数据类型也是qt自己的,那么为什么就是停不下来曹尼玛呢。

在很多编程中都会用到在线程中去循环一个事件,让他一直执行,但是如果这样听不下来,那么在退出程序的时候,就会崩溃掉。

原因:

1,信号与槽的连接是没有问题的,信号也是发送了的。

2,问题在于,while死循环中,因为线程是一个一个的执行,但是线程也有一个QThread::exec();需要去处理其他事件,

线程一直在循环中单步执行,造成QThread::exec();并没有处理,也就是说,信号其实是过来了,但是你线程没有去处理,

因为你在while一直循环。所以我们在使用线程的时候,就要注意了。.

 
3,处理方式,在线程的while中加一条

QCoreApplication::processEvents(QEventLoop::AllEvents);

注意添加头文件
#include <QCoreApplication>


这样我们点击停止按钮,曹尼玛才会停止。
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: