1 跨进程发送信号
项目代码下载:提取码:ikun
其实与跨界面发送信号是一致的,只不过是发送信号的一方变成了进程
1.1 添加子进程类
- 选择C++ class
- 选择其父类为QThread(也可以自行在代码中继承QThread)
- 点击完成即可。
非基础类型数据的注册
此处我们要使用一个score结构体,要是没有注册,则会报错:
QObject::connect: Cannot queue arguments of type 'score' (Make sure 'score' is registered using qRegisterMetaType().)
注册如下:
将score结构体注册,用score使用即可。注册的位置不固定,只需要在项目中即可。
qRegisterMetaType<score>("score");
TIP:string也属于非基础类型数据
string相关的问题
由于string是std中的,因此就算包含了#incude头文件,在使用时也要加上std,例如:
std::string std::to_string(int index)
否则会报错:
代码
child_name.h
#include <QThread>] #include<string> struct score{ int age; std::string name; int rate; }; class child_name : public QThread { Q_OBJECT //Q_OBJECT宏,使该类可以发送Qt信号 public: child_name(); signals: void send_index(score sc); //信号 protected: void run () override; //需要重写run方法 };
child_name.cpp
#include "child_name.h" #include<stdlib.h> #include<QDebug> #include<string> child_name::child_name() {} void child_name::run(){ while(1){ //不间断的发送index,同时使index++ score sc; sc.age = 13; sc.name="Tom"; sc.rate = 100; emit this->send_index(sc); sleep(1); //每隔一秒发送 } }
Widget.h
#include <QWidget> #include "child_name.h" class Widget : public QWidget { Q_OBJECT public: Widget(QWidget *parent = nullptr); ~Widget(); void handle_send_index(score score); //处理信号的槽函数 void connectFunc();//专门绑定各槽函数 child_name *child; //让子进程成为自己的成员,便于操作 public slots: void on_start_btn_clicked(); //按钮按下的槽函数 private: Ui::Widget *ui; };
Widget.cpp
#include "widget.h" #include "ui_widget.h" #include "child_name.h" #include<QString> #include<string> Widget::Widget(QWidget *parent) : QWidget(parent) , ui(new Ui::Widget) { qRegisterMetaType<score>("score"); ui->setupUi(this); connectFunc(); } Widget::~Widget() { delete ui; } void Widget::connectFunc(){ //专门绑定各槽函数 this->child = new child_name(); connect(child,&child_name::send_index,this,&Widget::handle_send_index); } void Widget::handle_send_index(score sc){ std::string str = "name: "+sc.name+"age: "+std::to_string(sc.age)+"rate: "+std::to_string(sc.rate); QString info = "index: "+QString::number(this->index++)+QString::fromStdString(str); //将int型转化为QString类型 this->ui->dispInfo->clear(); //清除原有内容 this->ui->dispInfo->setText(info); } void Widget::on_start_btn_clicked(){ this->child->start(); //开始运行子进程 }
1.2 槽函数参数和信号参数的关系
Qt槽函数的参数需要和信号的参数保持一致,可以比信号的参数少,但是不能顺序不同,也不能比信号的参数多。
否则就会报错:
1.3 重名信号的处理
例如,QCOmboBox里面的currentIndexChanged有两个重载的版本,而我们在使用QT5的connect时是只写函数名的,因此此时编译器会报错。
若要处理,则使用Qt4的版本,因为它必须要指明参数的类型。例如
connect(this->ui->comboBox,SIGNAL(currentIndexChanged(int)),this,SLOT(handle_index_change(int));
此外,还可以采用泛型编程的思想:
connect(ui->comboBox, Q0verload<int>::of(&0comboBox::currentIndexchanged),this,&Widget::onIndex);
此时,QOverload的数据类型为int,则此时currentIndexChanged函数中参数列表就是int型的。反之,为QOverload<const QString&>时则函数参数列表为const QString&类型
1.4 connect函数
connect(const typename QtPrivate::FunctionPointer<Func1>::Object *sender //发送者的指针 Func1 signal, //信号 const QObject *contexct //接收者的指针 Func2 slot, //槽函数 Qt::ConnectionType type = Qt::AutoConnection) //连接的类型默认为AutoConection
连接方式是枚举型,有以下几种连接方式:
enum ConnectionType { AutoConnection, DirectConnection, QueuedConnection, BlockingQueuedConnection, UniqueConnection = 0x80 };
AutoConnection:默认的连接方式,如果接收方在发出信号的线程中,使用Qt::DirectConnection;否则使用Qt::Queuedconnection。使用这种方式,Qt在发出信号时确定连接类型。在Qt中默认是用的AutoConnection,所以平时写信号槽时都是4个参数。
DirectConnection:当发出信号时,插槽立即被调果难槽在发送信易的线程中执行。
QueuedConnection:当控制返回到接收方线程的事件循环时调用槽,槽在接收方的线程中执行。
BlockingQueuedConnection:与Qt::QueuedConnection相同,只是发送信号的线程会阻,直到返回如果接收方存在于发送信号的线程中,则不能使用此连接,否则应用程序将死锁。
UniqueConnection:这是一个可以使用按位OR与上述任何一种连接类型组合的标志,当Qt::UniqueConnection被设置时,如果连接已经存在,QObject::connect()将失败(例如,如果相同的信号已经连接到相同的对象对的插槽)。
2 总结
在代码的舞台上翩翩起舞, Qt,如诗如画,编织梦的彩虹。
跨越平台的轻盈舞姿, 文档的琴音,灵感的涟漪。
模块的花瓣,细腻而丰满, 开发者的心灵,在那里盛开。
清新而深邃,如林中明月, Qt,用优雅的笔触,谱写未来的篇章。
渴望挑战Qt的学习路径和掌握进阶技术?不妨点击下方链接,一同探讨更多Qt的奇迹吧。我们推出了引领趋势的💻QT专栏:《QT从基础到进阶》 ,旨在深度探索Qt的实际应用和创新。🌐🔍