信号+槽——QT的核心特性

ops/2025/3/7 5:06:46/

在 QT里面实现控件与控件之间的联动关系(数据交互关系)

信号:

当一个组件发生任何改变(状态或者属性改变,人为主动操作/被动改变)
这些状态改变,称为 发生了事件

当任意一个组件,发生事件,该组件会发出一个与该事件关联的信号
    通过发出不同的信号,来告诉外部,自己发什么了什么改变

本质是一个函数,必须是一个控件/窗口的成员函数

槽函数:

接受并处理一个信号

    槽函数允许与一个信号关联
    如果槽函数发现与其关联的信号触发之后,就会自动调用槽函数

种类:

    1:槽函数可以是一个控件/窗口的成员函数
    2:槽函数可以是一个全局函数
    3:槽函数可以是一个匿名函数
    4:槽函数可以是一个信号函数

关联

1.当槽函数是控件/窗口的成员函数

QObject::connect(信号发送方控件地址,&信号发送方控件类型::信号名,信号接收方地址,&信号接收方控件类型::槽函数名)

le = new QLineEdit();
btn = new QPushButton();
QObject::connect(btn,&QPushButton::clicked,le,&QLineEdit::setText) 

槽函数如果带参数,实参来自于哪

信号和槽,不仅有简单的通知功能,还可传递数据

信号函数: signal(const QString& str = "hello world")
槽函数:slot(QString ptr);
signal 函数 和 slot 关联
那么,当信号函数触发, signal函数会将他的参数 str (默认为"hello world") 传递给 slot 的参数 ptr

所以注意:槽函数如果参数,说明要接受一个数据,那么信号就必须有一个相同的数据发过去,也就是信号函数必须有一个同样的参数
    反过来不一样,信号如果有参数,槽函数可以没有

 关联位置

在代码的任意处连接信号和槽
取决于,哪块位置访问需要连接的2个控件地址更为方便, 则就在哪里进行连接

2. 当槽函数是全局函数 

void func(){qDebug() << "hello world";
}Widget::Widget(QWidget *parent): QWidget(parent), ui(new Ui::Widget)
{ui->setupUi(this);QObject::connect(ui->pushButton_2,&QPushButton::clicked,func);
使用 connect 函数直接与全局函数连接
}

3.当槽函数是lambda表达式

Widget::Widget(QWidget *parent): QWidget(parent), ui(new Ui::Widget)
{ui->setupUi(this);QObject::connect(ui->pushButton_2,&QPushButton::clicked,[&]()mutable{qDebug() << "lambda";});
}
connect函数的第3个参数,直接写lambda表达式的定义就好了

4.当槽函数是信号 

Widget::Widget(QWidget *parent): QWidget(parent), ui(new Ui::Widget)
{ui->setupUi(this);QObject::connect(this,&Widget::mysignal,this,&Widget::myslot_2);QObject::connect(ui->pushButton_2,&QPushButton::clicked,this,&Widget::mysignal);
}
通过connect函数将 clicked 信号链接到 mysignal信号
由于mysignal信号连接到了 myslot_2,
所以,最终结果:clicked信号通过mysignal信号连接到了 myslot_2

自定义槽函数

目的

接受一个信号的槽函数,需要操作多个组件窗口,
拥有多个组件窗口地址的,一般就是一个父组件
so要为我们自己写的父组件,写一个自定义的槽函数,去操作多个组件

注意:

1:必须写在 public slots 访问权限里面

2:拥有自定义槽函数的类,必须在开头有一个宏:Q_OBJECT

        如果没有,虚表报错

        虚表报错了,再加上这个宏,编译还是报错,只能  重新构建 才能解决

3:有自定义槽函数的类,必须分文件编译

C++ 分文件的规则:一个类占一个头文件;

类里成员函数,定义在对应的.cpp 文件

练习:

编写2个聊天窗口,实现互相聊天功能

//widget.h
class Widget : public QWidget
{   Q_OBJECTQLineEdit* le;QTextEdit* te;QPushButton* btn;QWidget* sw;QHBoxLayout* hlay;QVBoxLayout* vlay;Widget*that;//public:Widget(QWidget *parent = nullptr);void setThat(Widget*w);///
public slots:void myslot();
signals:void mysignal(QString text);
};//widget.cpp
Widget::Widget(QWidget *parent) : QWidget(parent)
{sw = new QWidget(this);  // 创建一个子窗口te = new QTextEdit(this);  // 创建文本编辑器vlay = new QVBoxLayout(this);  // 创建垂直布局(主布局)// 将子窗口和文本编辑器添加到主布局vlay->addWidget(sw);vlay->addWidget(te);le = new QLineEdit(sw);  // 创建单行文本输入框btn = new QPushButton("Click Me", sw);  // 创建按钮hlay = new QHBoxLayout(sw);  // 创建水平布局(子窗口布局)// 将单行文本输入框和按钮添加到子窗口布局hlay->addWidget(le);hlay->addWidget(btn);// 连接按钮点击信号到槽函数connect(btn, &QPushButton::clicked, this, &Widget::myslot);}
void Widget::myslot(){QString text = le->text();  // 获取单行文本输入框的内容te->setPlainText(text);    // 将内容显示在文本编辑器中te->append(text);le->clear();that->te->append(text);
}
void Widget::setThat(Widget*w){//that=w;
}//main.cpp
int main(int argc, char *argv[])
{QApplication app(argc, argv);Widget w1,w2;w1.setWindowTitle("Window 1");w2.setWindowTitle("Window 2");w1.setThat(&w2);w2.setThat(&w1);w1.show();w2.show();return app.exec();  // 启动事件循环
}
//widget.h
class Widget : public QWidget
{   Q_OBJECTQLineEdit* le;QTextEdit* te;QPushButton* btn;QWidget* sw;QHBoxLayout* hlay;QVBoxLayout* vlay;//Widget*that;
public:Widget(QWidget *parent = nullptr);//    void setThat(Widget*w);void receiveText(const QString& text);
public slots:void myslot();
signals:void mysignal(QString text);
};//widget.cpp
Widget::Widget(QWidget *parent) : QWidget(parent)
{sw = new QWidget(this);  // 创建一个子窗口te = new QTextEdit(this);  // 创建文本编辑器vlay = new QVBoxLayout(this);  // 创建垂直布局(主布局)// 将子窗口和文本编辑器添加到主布局vlay->addWidget(sw);vlay->addWidget(te);le = new QLineEdit(sw);  // 创建单行文本输入框btn = new QPushButton("Click Me", sw);  // 创建按钮hlay = new QHBoxLayout(sw);  // 创建水平布局(子窗口布局)// 将单行文本输入框和按钮添加到子窗口布局hlay->addWidget(le);hlay->addWidget(btn);// 连接按钮点击信号到槽函数connect(btn, &QPushButton::clicked, this, &Widget::myslot);}
void Widget::myslot(){QString text = le->text();  // 获取单行文本输入框的内容//te->setPlainText(text);    // 将内容显示在文本编辑器中te->append(text);le->clear();//that->te->append(text);emit mysignal(text);
}
//void Widget::setThat(Widget*w){
//    that=w;
//}
void Widget::receiveText(const QString& text)
{te->setPlainText(text);  // 将接收到的内容显示在文本编辑器中
}//main.cpp
int main(int argc, char *argv[])
{QApplication app(argc, argv);Widget w1,w2;w1.setWindowTitle("Window 1");w2.setWindowTitle("Window 2");//    w1.setThat(&w2);//    w2.setThat(&w1);// 连接窗口2的textSent信号到窗口1的receiveText槽函数QObject::connect(&w1, &Widget::mysignal, &w2, &Widget::receiveText);QObject::connect(&w2, &Widget::mysignal, &w1, &Widget::receiveText);w1.show();w2.show();return app.exec();  // 启动事件循环
}

自定义信号

目的:

省写一个接口
接口和信号做的是一件事情

怎么写

1:写在signals访问权限里面
2:参数,也可向槽函数发送数据,所以槽函数要什么数据,自定义信号写什么数据就好了
3:信号函数无需定义
4:发送信号时,直接调用信号函数,函数前加 emit

转到槽 功能

依赖于ui界面,ui界面中的子组件,通过ui->去访问
只适用于能够在ui界面上显示的组件
一些组件无法在ui界面上布局,只能用 connect

connect 最后一个参数的意义

Qt::AutoConnection自动连接:
如果信号和槽所在的组件,处于同一个线程,则使用Qt::DirectConnection模式,如果不处于同一个线程,则使用Qt::QueuedConnection

Qt::DirectConnection 直接连接:
当信号和槽所在的组件,处于同一个线程的时候,信号一旦发送,则立刻调用槽函数

Qt::QueuedConnection队列连接:
当信号和槽所在的组件,不处于同一个线程的时候,信号触发后,需要等待程序运行到槽函数所在的组件所处的线程运行的时候,才会触发槽函数

Qt::BlockingQueuedConnection    阻塞队列连接:
当信号和槽所在的组件,不处于同一个线程的时候,信号触发后,需要等待程序运行到槽函数所在的组件所处的线程运行的时候,才会触发槽函数
        但是 信号所在的线程会阻塞,直到槽函数运行完才接触阻塞


http://www.ppmy.cn/ops/163395.html

相关文章

【Laplacian边缘检测详解】

Laplacian边缘检测详解 目录 Laplacian边缘检测详解一. 定义二. 原理三. 特点四. 使用技巧五. MATLAB示例代码示例1&#xff1a;基本Laplacian边缘检测示例2&#xff1a;扩展Laplacian核的使用示例3&#xff1a;与Sobel边缘检测的比较示例4&#xff1a;检测图像中的文字边缘示例…

JavaScript 变量命名规范

在编写JavaScript代码时&#xff0c;选择合适的变量名对于代码的清晰度、可读性和可维护性至关重要。一个良好的变量命名规范不仅能帮助团队成员更好地理解代码意图&#xff0c;还能减少错误发生的可能性。本文将介绍一些广泛接受的JavaScript变量命名规则和最佳实践。 命名的…

剧本杀门店预约小程序:市场发展下的刚需

在剧本杀爆发式增长下&#xff0c;门店数字化运营的模式正在市场中逐渐展开&#xff0c;线下门店的竞争方向已发生了全新转变&#xff01; 目前&#xff0c;数字化发展已经成为了消费市场的刚需&#xff0c;利用网络的便捷性提高服务&#xff0c;优化运营&#xff0c;提高自身…

另辟蹊径:多维度解析 STM32 微控制器

开篇&#xff1a;STM32 的广泛影响力 在嵌入式系统的广阔天地中&#xff0c;STM32 系列微控制器宛如一颗璀璨的明星&#xff0c;散发着耀眼的光芒。它凭借出色的性能、丰富的资源以及高性价比&#xff0c;在工业、医疗、消费电子等众多领域广泛应用&#xff0c;成为无数开发者…

兼容移动端ios,安卓,web端底部软键盘弹出,输入框被遮挡问题

思路&#xff1a; 1.监听键盘高度的变化 要监听键盘高度的变化&#xff0c;我们得先看看在键盘展开或收起的时候&#xff0c;分别会触发哪些浏览器事件&#xff1a; iOS 和部分 Android 浏览器 展开&#xff1a;键盘展示时会依次触发 visualViewport resize -> focusin -&g…

JavaWeb基础专项复习6(2)——AJAX补充

目录 1、load(url, [data], [callback]) 1.1 语法 1.2概述 1.3参数 url,[data,[callback]]String,Map/String,CallbackV1.0 1.4示例 HTML 代码: jQuery 代码: 2、get(url, [data], [callback], [type]) 2.1 语法 2.2 概述 2.3 参数 url,[data],[callback],[type]St…

【JavaScript—前端快速入门】JavaScript 综合案例 — 猜数字

JavaScript 综合案例—猜数字 预期效果 需求 完成基本的页面布局在文本框输入数字后&#xff0c;点击"猜"按钮&#xff0c;结果那一行会显示"猜大了"或者"猜小了"每猜一次&#xff0c;就会增加一次猜的次数猜到数字后&#xff0c;结果显示要猜的…

3d投影到2d python opencv

目录 cv2.projectPoints 投影 矩阵计算投影 cv2.projectPoints 投影 cv2.projectPoints() 是 OpenCV 中的一个函数&#xff0c;用于将三维空间中的点&#xff08;3D points&#xff09;投影到二维图像平面上。这在计算机视觉中经常用于相机标定、物体姿态估计、3D物体与2D图…