qt线程间信号与槽
2018-03-28 09:23
369 查看
qt线程的用法,其实我们在官网上看到的用法比较简单,很多时候会出现奇怪的现象。下面我们来看看,
1,qt信号与槽方式进行通信
QT就是把这个signal包装成一个 QEvent,放到消息队列里。线程的QThread::exec()会从消息队列里取消息,然后调用 signal关联的几个slot。这种方式既可以在线程内传递消息,也可以跨线程传递消息。
先看界面:
![](https://img-blog.csdn.net/20180328091214326?watermark/2/text/aHR0cDovL2Jsb2cuY3Nkbi5uZXQvY3FsdGJlMTMxNDIx/font/5a6L5L2T/fontsize/400/fill/I0JBQkFCMA==/dissolve/70/gravity/Center)
我用代码来测试:
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
我们就用上面的四个文件来测试:
1,信号与槽线程间连接的数据类型问题,qt自带的元数据类型,想没有问题的,但是我们自己建立了一个testString,
如果在mainwindow的构造函数里面,没有注册到元数据属性里面,
就会提示:
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中加一条
注意添加头文件
这样我们点击停止按钮,曹尼玛才会停止。
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>
这样我们点击停止按钮,曹尼玛才会停止。
相关文章推荐
- Qt中同一个线程里,QTimer的timeout()信号相关的槽未执行完,会发生什么?
- Qt4.7中,线程,信号,事件的一点理解
- 在非UI线程中更改UI(Delphi使用隐藏窗口来处理,QT使用信号槽)
- qt线程调用QAXObject(Excel,word)并传信号
- Qt多线程程序设计中,可使用信号和槽进行线程通信
- Qt事件循环 跨线程信号和槽
- QT 信号与槽在不同线程不能连接的问题
- Qt跨线程发送信号与元数据
- qt不同线程emit信号需要使用qMetaType
- Qt线程在sleep时能否处理信号
- Qt多线程间信号槽传递非QObject类型对象的参数
- Qt学习:线程间共享数据(使用信号槽传递数据,必须提前使用qRegisterMetaType来注册参数的类型)
- 基于Qt的函数对象(泛化仿函数)设计,可在线程中运行并通过信号返回QVariant
- 详解 Qt 线程间共享数据(用信号槽方式)
- QT 发射信号,接收槽,双线程演示(QtSDK演示程序)
- pyqt4 利用信号槽在子线程里面操作Qt界面
- Qt跨线程发送信号与元数据
- QT下信号与槽不在同一个线程中如何connect
- Qt线程间的信号与槽 以及 QThread
- 详解 Qt 线程间共享数据(使用signal/slot传递数据,线程间传递信号会立刻返回,但也可通过connect改变)