跨UI发送信号
基本框架
新建窗口
自定义信号
跨线程发送信号
新建线程
查看线程号
完整代码
跨UI发送信号
setdialog.h
#ifndef SETDIALOG_H
#define SETDIALOG_H
#include <QDialog>
namespace Ui {
class setdialog;
}
class setdialog : public QDialog
{
Q_OBJECT
public:
explicit setdialog(QWidget *parent = nullptr);
~setdialog();
private slots:
void on_btnAdd_clicked();
signals:
void sig_addOne(int value);
private:
Ui::setdialog *ui;
};
#endif // SETDIALOG_H
widget.h
#ifndef WIDGET_H
#define WIDGET_H
#include <QWidget>
QT_BEGIN_NAMESPACE
namespace Ui {
class Widget;
}
QT_END_NAMESPACE
class Widget : public QWidget
{
Q_OBJECT
public:
Widget(QWidget *parent = nullptr);
~Widget();
private slots:
void on_btnOpen_clicked();
private:
Ui::Widget *ui;
};
#endif // WIDGET_H
setdialog.cpp
#include "setdialog.h"
#include "ui_setdialog.h"
setdialog::setdialog(QWidget *parent)
: QDialog(parent)
, ui(new Ui::setdialog)
{
ui->setupUi(this);
}
setdialog::~setdialog()
{
delete ui;
}
void setdialog::on_btnAdd_clicked(){
static int score=100;
emit sig_addOne(score++);
}
widget.cpp
#include "widget.h"
#include "ui_widget.h"
#include <setdialog.h>
Widget::Widget(QWidget *parent)
: QWidget(parent)
, ui(new Ui::Widget)
{
ui->setupUi(this);
}
Widget::~Widget()
{
delete ui;
}
void Widget::on_btnOpen_clicked(){
setdialog dlg;
connect(&dlg ,&setdialog::sig_addOne,[=](int value){
ui->lineEdit_score->setText(QString::number(value));
});
dlg.exec();
}
跨线程发送信号
childthread.h
#ifndef CHILDTHREAD_H
#define CHILDTHREAD_H
#include <QThread>
using namespace std;
#include <string>
struct Score{
string name;
int id;
int age;
};
class ChildThread : public QThread
{
Q_OBJECT
public:
ChildThread();
signals:
void sig_SendToUI(Score score);
protected:
void run() override;
};
#endif // CHILDTHREAD_H
widget.h
#ifndef WIDGET_H
#define WIDGET_H
#include <QWidget>
#include <childthread.h>
QT_BEGIN_NAMESPACE
namespace Ui {
class Widget;
}
QT_END_NAMESPACE
class Widget : public QWidget
{
Q_OBJECT
public:
Widget(QWidget *parent = nullptr);
~Widget();
private slots:
void on_btnUpdate_clicked();
void showInfo(Score s);
private:
Ui::Widget *ui;
};
#endif // WIDGET_H
childthread.cpp
#include "childthread.h"
#include <QDebug>
ChildThread::ChildThread() {}
void ChildThread::run(){
Score s;
s.name="Jack";
s.age=18;
s.id=10086;
emit sig_SendToUI(s);
qDebug()<<"ui thread id4_run = "<<QThread:: currentThreadId();
}
widget.cpp
#include "widget.h"
#include "ui_widget.h"
#include <QDebug>
#include <childthread.h>
Widget::Widget(QWidget *parent)
: QWidget(parent)
, ui(new Ui::Widget)
{
ui->setupUi(this);
}
Widget::~Widget()
{
delete ui;
}
void Widget::on_btnUpdate_clicked(){
qDebug()<<"正常运行";
ChildThread* ch=new ChildThread;
connect(ch,&ChildThread::sig_SendToUI,this,&Widget::showInfo);
ch->start();
qDebug()<<"ui thread id2_btnUpdate = "<<QThread:: currentThreadId();
}
void Widget::showInfo(Score s){
string info="name="+s.name+" id="+to_string(s.id)+" age="+to_string(s.age);
ui->lineEdit->setText(QString::fromStdString(info));
qDebug()<<"ui thread id3_showInfo = "<<QThread:: currentThreadId();
}
复盘
跨UI发送信号
跨UI发送信号是指在不同用户界面组件之间传递信息,以实现交互和数据共享。
Qt的信号和槽机制是跨UI组件通信的经典方法。信号和槽允许对象之间进行松耦合的通信:
信号:由对象发出,表示某个事件发生。
槽:可以是任何可调用对象,当信号发出时,槽会被调用。
连接:通过QObject::connect方法将信号和槽连接起来。
void Widget::on_btnOpen_clicked(){
setdialog dlg;
connect(&dlg ,&setdialog::sig_addOne,[=](int value){
ui->lineEdit_score->setText(QString::number(value));
});
dlg.exec();
}
- void Widget::on_btnOpen_clicked()
这是一个槽函数,用于响应名为 btnOpen 的按钮点击事件。Widget 是一个自定义的类,包含这个槽函数。
- setdialog dlg;
这里创建了一个 setdialog 类型的对象 dlg。
- connect(&dlg, &setdialog::sig_addOne, [=](int value){ ui->lineEdit_score->setText(QString::number(value)); });
这行代码使用了 Qt 的信号和槽机制,建立了一个连接:
&dlg 是信号发送者,即 setdialog 对象。
&setdialog::sig_addOne 是 setdialog 类中的一个信号。
[=](int value){ … } 是一个Lambda表达式,作为槽函数。当信号 sig_addOne 发出时,这个Lambda函数会被调用,接收一个整数参数 value。
ui->lineEdit_score->setText(QString::number(value)); 将接收到的 value 转换为字符串,并设置到 lineEdit_score 控件中显示。
- dlg.exec();
这行代码以模态方式运行对话框 dlg。exec() 函数会阻塞,直到对话框关闭。
执行事件循环.
void setdialog::on_btnAdd_clicked(){
static int score=100;
emit sig_addOne(score++);
}
代码解析
- void setdialog::on_btnAdd_clicked()
这是一个槽函数,用于响应 setdialog 类中名为 btnAdd 的按钮点击事件。
- static int score = 100;
声明并初始化一个静态局部变量 score,初始值为 100。
静态局部变量在函数调用之间保持其值不变。也就是说,每次调用这个函数时,score 的值都会在上一次调用的基础上增加,而不会每次重新初始化为 100。
- emit sig_addOne(score++);
emit 关键字用于发出信号。这里发出的是 sig_addOne 信号。
score++ 是后置递增运算符,意味着在发出信号时,score 的当前值将被使用,然后 score 自增 1。
例如,第一次点击按钮时,score 的值是 100,信号 sig_addOne 发出时传递的值是 100,然后 score 增加到 101。
下一次点击按钮时,score 的值是 101,信号 sig_addOne 发出时传递的值是 101,然后 score 增加到 102。
信号和槽的工作流程
当用户点击 btnAdd 按钮时,on_btnAdd_clicked() 函数会被调用。
该函数发出 sig_addOne 信号,并传递当前的 score 值。
score 值会在每次按钮点击后递增,因此每次发出的信号都会传递一个增加后的 score 值。
在主窗口的槽函数中(如之前提到的 on_btnOpen_clicked()),连接到 sig_addOne 信号的槽函数会接收到这个 score 值,并在界面上更新显示。
跨线程发送信号
void ChildThread::run(){
Score s;
s.name="Jack";
s.age=18;
s.id=10086;
emit sig_SendToUI(s);
qDebug()<<"ui thread id4_run = "<<QThread:: currentThreadId();
}
- void ChildThread::run()
这是 ChildThread 类的 run 方法,是线程的入口点。在 QThread 中,run 方法会在调用 start 后在子线程中执行。
- Score s;
创建一个 Score 类型的对象 s。Score 可能是一个自定义的数据结构或类。
- s.name=“Jack”;
设置 Score 对象 s 的 name 属性为 “Jack”。
- s.age=18;
设置 Score 对象 s 的 age 属性为 18。
- s.id=10086;
设置 Score 对象 s 的 id 属性为 10086。
- emit sig_SendToUI(s);
发出信号 sig_SendToUI,并传递 Score 对象 s。
sig_SendToUI 是 ChildThread 类中的一个自定义信号,用于将数据传递到主线程的UI组件中进行显示或处理。
- qDebug()<<"ui thread id4_run = "<<QThread:: currentThreadId();
输出当前线程的线程ID,使用 qDebug() 进行调试打印。
QThread::currentThreadId() 返回当前线程的ID,可以用来验证代码是在子线程中执行的。
通过这种方式,子线程可以安全地将数据传递到主线程,并在UI中进行显示或处理。
void Widget::on_btnUpdate_clicked(){
qDebug()<<"正常运行";
ChildThread* ch=new ChildThread;
connect(ch, &ChildThread::sig_SendToUI, this, &Widget::showInfo);
ch->start();
qDebug()<<"ui thread id2_btnUpdate = "<<QThread::currentThreadId();
}
- void Widget::on_btnUpdate_clicked()
这是一个槽函数,用于响应 btnUpdate 按钮的点击事件。
- qDebug()<<“正常运行”;
使用 qDebug() 输出调试信息,表示槽函数已被正确调用。
- ChildThread* ch = new ChildThread
动态创建一个 ChildThread 对象 ch。ChildThread 类继承自 QThread,它代表一个独立的执行线程。
- connect(ch, &ChildThread::sig_SendToUI, this, &Widget::showInfo);
使用 Qt 的信号和槽机制,将子线程 ch 的 sig_SendToUI 信号连接到当前对象(Widget 类实例)的 showInfo 槽函数。
sig_SendToUI 是 ChildThread 类中定义的一个信号。
showInfo 是 Widget 类中的一个槽函数,用于处理来自子线程的数据并更新UI。
- ch->start();
调用 ch 的 start() 方法启动子线程。start() 方法会调用 ChildThread 类中的 run() 方法,在子线程中执行其中的代码。
- qDebug()<<"ui thread id2_btnUpdate = "<<QThread::currentThreadId();
使用 qDebug() 输出当前线程的线程ID,帮助开发者确认代码在主线程中执行。
**创建并启动子线程:**当用户点击 btnUpdate 按钮时,程序会动态创建一个 ChildThread 对象并启动子线程。
**连接信号和槽:**将子线程的信号 sig_SendToUI 连接到主线程的槽函数 showInfo。这样,当子线程发出信号时,主线程的槽函数会被调用,以更新UI。
**调试输出:**输出调试信息,确认槽函数被调用和线程ID。
结尾
最后,感谢您阅读我的文章,希望这些内容能够对您有所启发和帮助。如果您有任何问题或想要分享您的观点,请随时在评论区留言。
同时,不要忘记订阅我的博客以获取更多有趣的内容。在未来的文章中,我将继续探讨这个话题的不同方面,为您呈现更多深度和见解。
谢谢您的支持,期待与您在下一篇文章中再次相遇!