【QT-百日筑基篇】打完完怪,开始学炼丹, 前往藏书阁寻找对应材料的信息,并前往去寻找对应材料-QT信号和槽

|----------------------------------------------------------------------------|----------------------------------------------------------------------------------|
| 作者简介 | |
| Linux | QT-百日筑基篇 |
| 数据结构篇 | |

目录/索引:

目录

QT信号的三要素:

触发信号的一般条件:

关于槽的理解:信号的处理方式:槽(slot)=>函数。

connect的使用方式:

QT到底提供了哪些的信号和槽让我们使用呢?

那我们就看一下文档:

控件的方式使用槽:

查看系统生成:

图解:

自定义信号

信号和槽带参数:

为啥这里要求信号的参数要>=槽的参数呢???

深度理解Q_OBJECT在信号和槽里的作用:

但是我如果注释这行代码会发生什么?程序还能不能运行了。

那么我在创建一个没有信号与槽的项目并作出相同的操作这样还能报错吗???

综上所述:

槽链接断开(disconnect的使用):

在QT中使用lambda表达式:

下篇QT预告:



QT信号的三要素:

信号源: 由那个信号源发出的信号。

信号类型: 发出的信号是哪种的信号。

信号处理对象: 这个信号要交给谁来进行处理。

信号的处理方式: 注册信号处理函数,在信号被触发时自动调用执行。

这些依次对应着connect的四个参数。

触发信号的一般条件:

比如我们点击按钮,触发点击信号。

在输入框移动光标, 触发点击信号。

勾选一个复选框。

选择一个下拉框, 都会触发不同的信号。

关于槽的理解:

信号的处理方式:槽(slot)=>函数。

QT中可以使用connect来将槽和信号进行关联起来, 后续只要信号触发了就会执行对应的槽函数。所谓的槽本质上也是一种"回调函数"(我们c++的仿函数,lambad其实也是一种回调函数)。

connect的使用方式:

我们在上一篇文章写了一个按钮的信号我们现在在这里来进行一个详细的介绍。

cpp 复制代码
    button= new QPushButton(this);
    button->setText("请点击");
    connect(button, &QPushButton::clicked, this , &Widget::handleclick);

要解释这块的内容我们要将这块的内容进行拆解的进行逐个进行细致的讲解:

connect的第一个参数时谁发出的信号,这里的button是定义了一个按钮。在这里这个信号由按钮来进行发送。具体怎么进行发送呢,还要看下一个参数。

我们的变量:

&QPushButton::clicked:第二个参数, 指的是如和进行发送这个信号我们这时使用了QPushButton内部的一个信号。这里选择的clicked点击来进行触发这个信号。 我们的QPushButton内部还有一个click他是运行时自动点击。 我们这想要手动的进行点击所以使用clicked。

this: 这个参数时这个信号交给谁来进行处理, 我们这里是交给this;来进行处理。 这里的this是什么呢?

我们可以看到他是Widget的构造, 所以这个this是Widget的属性(变量), 所以将这个信号交给Widget来进行对应的处理。

&Widget::handleclick: 这个是我们对应的信号处理者(第三个参数)实现一个方法来进行对于这个信号的处理。

我们通过上面的可以简单的了解一点对应的一些使用方法。

那我们来进行对应的了解。

我们可以先查下文档来进行对应的处理:

我们再次的练习一下: 来一个按钮点击一下将运行窗口进行关闭。

cpp 复制代码
connect(button, &QPushButton::clicked, this , &Widget::handleclick);

void Widget::handleclick()
{
    this->close();
}

connect要求参数是匹配的。button的类型如果是QPushButton*, 此时,第二个参数的信号必须是QPushButton内置的信号(父类的信号), 不能是一个其他的。当然第三个参数和第四个参数也是匹配的。

close是QWidget内置的槽函数,Widget是继承自QWidget的也就是继承了父类的槽函数。

人家已经实现好了不需要我们在进行实现了。 所以这样也能将窗口进行关闭。

cpp 复制代码
connect(button, &QPushButton::clicked, this , &Widget::close);

首先我怎么知道QPushButton是怎么有个clicked信号? 或者QWidget有一个close槽??

QT到底提供了哪些的信号和槽让我们使用呢?

那我们就看一下文档:

下面的那个是他的子类。

QT会提供好几种按钮,这些按钮存在一些共性的内容,我们就把这些共性提取放到了QAbstractButton类里面。

在这里我们除啦使用我们手动的connect将信号和槽连接起来以外, 我们还能在控件的方面将这两者进行关联起来。

当然这里还有一个问题:

当然我们这里的第二个和第四个我们connect要的是char*类型的指针, 而我们传的是函数指针, 我们在c语言阶段知道不同类型的指针不能相互的进行传递的。 那么这里为什么能进行这样的传递呢?

控件的方式使用槽:

我们现在控件的屏幕上创建一个按钮, 然后右键他会出现一个转到槽的地方, 我们点击它。

当然这里会出现两种click第一个click是点击按钮发出的信号, 而第二个有一个bool的形参, 它主要作用于像我们同意一些要求所要勾选的一些下拉框, 也就是一个"对号" ,勾选就变成了true, 否则为false。在这里我们选泽第一个来进行后续方法的实现。

我们点击后就会在widget.cpp中自动的生成一个槽函数。

我们试着写一段代码来进行验证这一块的内容:

代码块:

cpp 复制代码
    if(ui->pushButton->text()==QString("请点击"))
    {
        ui->pushButton->setText("已点击");
    }
    else
    {
        ui->pushButton->setText("请点击");
    }

我们发现我们没有进行connect就能将信号和槽链接起来, 这是因为我们点击后系统给我们自动的就生成了这样的一段代码。我们可以在系统进行查看的。

查看系统生成:

右击.pro, 点击在explorer中显示, 退到上一级,找到一个名字类似于"build-signal-Desktop_Qt_5_14_0_MinGW_64_bit-Debug"的文件点进去,点击"ui_widget"拖到QT中打开。

图解:

我们能看到这里有许多的代码, 我们主要是要寻找connect, 我们没有发现connect的影子,但是我们发现了一个和它类似的东西

那我们查下文档看看它究竟是个什么。

发现果然与connect有关, 译文:"递归搜索给定对象的所有子对象,并将来自这些子对象的匹配信号连接到遵循特定命名规则的槽函数。"

在这里我们介绍一个可以修改窗口命令的控件:

setWindowTitle控件能修改窗口的名字。

以前老版本的QT必须这么些否则编译报错:

自定义信号

当然QT也允许自定义信号

自定义槽函数非常关键, 我们也经常使用它, 槽是触发某种信号我们要执行的对应逻辑。非常常用。

自定义信号就非常少的进行使用了, 因为常用的我们QT官方就已经帮我们实现好了,不需要我们在进行额外的操作进行实现了。当然一些特定的情况我们也是需要对应信号的书写的。 自定义信号的书写也是很简单的。

信号是一类非常特殊的函数, 程序员只要写出和函数的声明,并告诉QT这是一个信号即可,这个函数的定义在QT编译过程中自动生成,我们无法进行干预。

首先作为信号函数这个返回值必须是void有无参数都可以,也可以进行重载。信号的前面需要加上signals来进行说明这是一个信号。这也是QT扩展出的一个关键字

这里只是建立了链接不代表信号发出来了。那么如何才能触发信号呢? QT内置的信号不要手动的通过代码来触发,用户在GUI 进行某些操作时, 就会自动的触发对应的信号,我们能通过这些间接的方式将这个信号进行发出 。

这样也是可以的。已经将这个信号进行了发出。然后执行对应的槽函数。

信号和槽带参数:

信号和槽也是可以进行携带参数的,当信号有参数时, 槽的参数要与信号的参数一致或者要小于 信号的参数,信号的参数一定的>= 槽的参数的个数

这个信号的参数传给了槽的text然年经过文本的设置对按钮的操作进一步的补充了。

声明:

cpp 复制代码
    void headclick(const QString& text);//槽

signals:
    void mysignal(const QString& text);

传参可以起到复用代码的效果,有多个逻辑, 整体一致, 但涉及到的数据不同, 就可以通过函数,参数来复用代码,并且在不同场景传入不同的参数即可~。

cpp 复制代码
   connect(this, &Widget::mysignal, this,&Widget::headclick);

通过这样的方式可以进行不同的文本的设置。

这样可以设置两个不一样的文本了。

cpp 复制代码
void Widget::on_pushButton_clicked()
{
    emit mysignal("已点击按钮一");
}

void Widget::on_pushButton_2_clicked()
{
     emit mysignal("已点击按钮二");
}

这时信号有两个参数,而槽只有一个参数, 那么我们这时候的编译是不会报错的。

我们的槽如果要是两个参数而信号是一个参数是,那么编译就会报错。

所以我们的信号的参数要>=槽的参数。

但是我们直观的感受,应该要求信号和槽的参数个数一致,

为啥这里要求信号的参数要>=槽的参数呢???

一个槽可能绑定多个信号, 如果我们要求参数个数一致就意味着绑定槽的要求变高了, 换言之现在这种情况我们信号和槽的要求就变高了,就会有更多的信号绑定到这个槽上了。

这样也能确保每个参数都能有参数, 确保每个参数都是有值的。

我们带参数的信号和槽要求:

类型要一致且信号的参数>=槽的参数。

深度理解Q_OBJECT在信号和槽里的作用:

F2进入这个宏我们能看到许多东西

但是我如果注释这行代码会发生什么?程序还能不能运行了。

我们能发现他是缺少了一个Q_OBJECT的宏。

那么我在创建一个没有信号与槽的项目并作出相同的操作这样还能报错吗???

能正常的运行。

综上所述:

Q_OBJECT在信号和槽中的作用还是挺明显的, 没有它就会编译报错。

QT信号槽connect设想是美好的,

1) 解耦合: 把用户操作的控件和处理对用户的操作逻辑解耦合。

2) 多对多效果(数据库也是多对多的形式):

一个信号,可以connect到多个槽函数上。

一个槽函数,也可以被多个connect进行链接。


槽链接断开(disconnect的使用):

disconnect主要是断开对应的信号和槽的链接。

主动断开往往把信号重新绑定到另一个槽函数上。

我们可以发现解除后再次点击按钮一,是不会有任何的变化的。


在QT中使用lambda表达式:

在C++11时我们c++标准给出了一个lambda表达试。当然在我们QT5以后也支持了Lambda表达式本质上还是函数调用。

这样我们也能看到它被执行了。

这里要注意的是:

像我们有些局部变量我们是在lambda中用不了的我们要在[]中进行对外面变量进行捕获,也找注意变量的生命周期, 在合适的时机进行值捕获或者引用捕获。

当然我们QT5以后才支持C++11,要像之前的要在pro中进行更换标准才能进行使用lambda表达式。


完结


下篇QT预告:

QT中常用的控件。

相关推荐
csbysj20201 小时前
Bootstrap5 Jumbotron 深入解析
开发语言
小短腿的代码世界1 小时前
QtitanRibbon深度解析:从微软Office UI到Qt跨平台Ribbon框架的完整架构实现
qt·microsoft·ui
郝学胜-神的一滴1 小时前
CMake 010 :一步到位链接静态库
开发语言·c++·qt·程序人生·系统架构·cmake
小则又沐风a1 小时前
C++继承
开发语言·c++
测试员周周1 小时前
【Appium 系列】第10节-手势操作实战 — 滑动、拖拽、缩放与轻拂
linux·服务器·开发语言·人工智能·python·appium·pytest
雪度娃娃1 小时前
转向现代C++——在创建对象时注意区分()和{}
开发语言·c++
铅笔小新z1 小时前
【C语言】数组详解
c语言·开发语言
摇滚侠1 小时前
Java 饿汉式 单例模式
java·开发语言·单例模式
lbb 小魔仙1 小时前
工业数据困局的破局者:DolphinDB 如何让海量时序数据真正“跑“出价值
开发语言·人工智能·python·langchain