网站首页设计思路,深圳市宝安区网站建设,网站建设的域名是什么,展示型网站的特点往期回顾#xff1a; 【QT入门】 lambda表达式(函数)详解-CSDN博客 【QT入门】 Qt槽函数五种常用写法介绍-CSDN博客 【QT入门】 Qt实现自定义信号-CSDN博客 【QT入门】 Qt自定义信号后跨线程发送信号
由于Qt的子线程是无法直接修改ui#xff0c;需要发送信号到ui线程进行修改…往期回顾 【QT入门】 lambda表达式(函数)详解-CSDN博客 【QT入门】 Qt槽函数五种常用写法介绍-CSDN博客 【QT入门】 Qt实现自定义信号-CSDN博客 【QT入门】 Qt自定义信号后跨线程发送信号
由于Qt的子线程是无法直接修改ui需要发送信号到ui线程进行修改所以会跨线程发送信号。
一、思路
思路基本一致子线程发送一个信号父线程接收信号并执行槽函数把子线程传递的数据展示在父线程ui上。
二、步骤
1.如何创建子线程
右键单击项目选择Add New-CC Class即可 ChildThread是我们自己取的子线程名字 下面的基类因为没有合适的基类我们选择Custom继承QThread类
这里注意创建以后由于是自己填的继承自QThread类它不一定包含了相应的头文件需要我们自己补上。
2、添加Q_OBJECT宏
自己创建的子线程是不包含Q_OBJECT宏的如果需要用到信号槽需要自己补上Q_OBJECT 一般建议大家不管用不用创建后就都补上。
3、子线程重写run方法
子线程继承父线程之后需要重写父线程的run方法关于线程这一块知识点后续会有更加详细的讲解比如子线程重写的run方法在子线程里但是其构造函数却是在父线程里等
void ChildThread::run()
{//打印当前线程的线程号qDebug()child thread id QThread::currentThreadId();Score s;s.namezhangsan;s.age18;s.id001;emit sig_sendScore(s);}
注
当我们分不清代码运行在哪个线程的时候可以用QThread::currentThreadId();方法打印当前线程的线程号来判断。
这里数据方面用了一个结构体来写数据
struct Score
{string name;int age;int id;
};
4、启动子线程 父线程按钮点击的槽函数里创建子线程接受子线程的信号并启动子线程
void Widget::on_btnOpen_clicked()
{ChildThread *ch new ChildThread();connect(ch,ChildThread::sig_sendScore,[](Score s){string infonames.name ageto_string(s.age) idto_string(s.id);ui-lineEdit-setText(QString::fromStdString(info));});qDebug()widget thread id QThread::currentThreadId();ch-start();
}
针对代码看几个注意点
1、要在Qt用c的string类型一个加头文件二个加命名空间2、age和id这种int类型要转成string用一个to_string()复习int转Qstring用QString::number()3、setText放的是QString类型的这里info是string类型所以需要转QString用QString::fromStdString()
但是由于ChildThread的ch对象的槽函数sig_sendScore连接到了lambda表达式中lambda表达式可能在ChildThread的线程中执行。这导致槽函数执行时在ChildThread的线程中运行而不是在主线程中。
为了让槽函数在父线程执行要么不用lambda表达式改用槽函数要么改写lambda表达式
4.1 改用槽函数
void Widget::on_btnOpen_clicked()
{ChildThread *ch new ChildThread();connect(ch,ChildThread::sig_sendScore,this,Widget::showIofo);qDebug()ui01 thread id QThread::currentThreadId();ch-start();
}
4.2 改写lambda表达式
void Widget::on_btnOpen_clicked()
{ChildThread *ch new ChildThread();connect(ch, ChildThread::sig_sendScore, this, [](Score s){string info name s.name age to_string(s.age) id to_string(s.id);ui-lineEdit-setText(QString::fromStdString(info));qDebug()slots thread id QThread::currentThreadId();}, Qt::QueuedConnection);qDebug()ui01 thread id QThread::currentThreadId();ch-start();
}
使用Qt::QueuedConnection连接信号和槽这样信号会被投递到接收者所在的线程中执行。可以确保槽函数在接收者所在的线程中执行从而解决可能的线程问题。
三、报错
当成功在父线程执行后报了一个错误 QObject::connect: Cannot queue arguments of type Score (Make sure Score is registered using qRegisterMetaType().) 这是告诉我们Score是一个非基础类型参数需要进行注册在子线程的构造函数实现里注册即可
ChildThread::ChildThread()
{//非基础类型参数注册qRegisterMetaTypeScore(Score);
}
四、最终代码 最后附上最终代码以便供大家参考
1、widget.h
#ifndef WIDGET_H
#define WIDGET_H
#include childthread.h
#include QWidgetQT_BEGIN_NAMESPACE
namespace Ui { class Widget; }
QT_END_NAMESPACEclass Widget : public QWidget
{Q_OBJECTpublic:Widget(QWidget *parent nullptr);~Widget();private slots:void on_btnOpen_clicked();void showIofo(Score s);private:Ui::Widget *ui;
};
#endif // WIDGET_H2、widget.cpp
#include widget.h
#include ui_widget.h
#include QDebugWidget::Widget(QWidget *parent): QWidget(parent), ui(new Ui::Widget)
{ui-setupUi(this);
}Widget::~Widget()
{delete ui;
}void Widget::on_btnOpen_clicked()
{ChildThread *ch new ChildThread();//ch对象的槽函数sig_sendScore连接到了lambda表达式中lambda表达式可能在ChildThread的线程中执行。//这可能导致槽函数执行时在ChildThread的线程中运行而不是在主线程中。
// connect(ch,ChildThread::sig_sendScore,[](Score s){
// string infonames.name ageto_string(s.age) idto_string(s.id);
// ui-lineEdit-setText(QString::fromStdString(info));
// qDebug()slots thread id QThread::currentThreadId();
// });// connect(ch, ChildThread::sig_sendScore, this, [](Score s){
// string info name s.name age to_string(s.age) id to_string(s.id);
// ui-lineEdit-setText(QString::fromStdString(info));
// qDebug()slots thread id QThread::currentThreadId();
// }, Qt::QueuedConnection);//connect(ch,ChildThread::sig_sendScore,this,Widget::showIofo);qDebug()ui01 thread id QThread::currentThreadId();ch-start();
}void Widget::showIofo(Score s)
{qDebug()ui02 thread id QThread::currentThreadId();string infonames.name ageto_string(s.age) idto_string(s.id);//setText放的是QString类型的这里info是string类型所以需要转QStringui-lineEdit-setText(QString::fromStdString(info));
}3、childthread.h
#ifndef CHILDTHREAD_H
#define CHILDTHREAD_H
#include QThread
#include stringusing namespace std;//定义一个结构体函数
struct Score
{string name;int age;int id;
};class ChildThread : public QThread
{Q_OBJECTpublic:ChildThread();protected:void run() override ;signals:void sig_sendScore(Score s);};#endif // CHILDTHREAD_H4、childthread.cpp
#include childthread.h
#include QDebug
ChildThread::ChildThread()
{//非基础类型参数注册qRegisterMetaTypeScore(Score);
}void ChildThread::run()
{//打印当前线程的线程号qDebug()child thread id QThread::currentThreadId();Score s;s.namezhangsan;s.age18;s.id001;emit sig_sendScore(s);} 都看到这里了点个赞再走呗朋友~
加油吧预祝大家变得更强