• Qt5开发从入门到精通——第一篇(概述——(信号和槽机制)、(原对象系统)、(布局管理器))


    欢迎小伙伴的点评✨✨,相互学习、互关必回、全天在线🍳🍳🍳
    博主🧑🧑 本着开源的精神交流Qt开发的经验、将持续更新续章,为社区贡献博主自身的开源精神👩‍🚀


    前言

    本章节会探讨三个开发步骤、如下所示:

    • 信号和槽机制
    • 原对象系统
    • 布局管理器

    一、 信号和槽机制

    Qt 提供了信号和槽机制用于完成界面操作的响应,信号和槽机制是完成任意两个 Qt 对象之
    间的通信机制。其中,信号会在某个特定情况或动作下被触发,槽是等同于接收并处理信号的函
    数。例如,若要将一个窗口部件的变化情况通知给另 一个窗口部件,则一个窗口部件发送信号,
    另一个窗口部件的槽接收此信号并进行相应的操作,即可实现两个窗口部件之间的通信 。 每个 Qt
    对象都包含若干个预定义的信号和若干个预定义的槽 。 当某一个特定事件发生时,一个信号被发
    送,与信号相关联的槽则会响应信号并完成相应的处理 。 当 一个类被继承时,该类的信号和槽也
    同时被继承,也可以根据需要自定义信号和槽 。

    1.1信号与槽机制的连接方式

    (1)一个信号可以与另一个信号相连,代码如下:

    connect(Object1,SIGNAL(signal1),Object2,SIGNAL(signal1));
    
    • 1

    表示Object1的信号1发送可以触发Object2的信号1发送

    (2)同一个信号可以与多个槽相连,代码如下:

    connect(Object1,SIGNAL(signal2),Object2,SIGNAL(slot2));
    connect(Object1,SIGNAL(signal2),Object3,SIGNAL(slot1));
    
    • 1
    • 2

    (3)同一个槽可以相应多个信号,代码如下:

    connect(Object1,SIGNAL(signal2),Object2,SIGNAL(slot2));
    connect(Object3,SIGNAL(signal2),Object2,SIGNAL(slot2));
    
    • 1
    • 2

    但是,常用的连接方式为:

    connect(Object1,SIGNAL(signal),Object2,SLOT(slot));
    
    • 1

    其中, signal 为对象 Objectl 的信号, slot 为对象 Object2 的槽。

    (4)信号与槽机制的SIGNAL()和SLOT()解析:

    SIGNAL()和 SLOT()是 Qt 定义的两个宏,它们返回其参数的 C 语言风格的字符串 (const
    char*) 。因此,下面关联信号和槽的两个语句是等同的:

    connect(button,SIGNAL(clicked()), this, SLOT (showArea ()));
    connect (button, "clicked()",this, "showArea() ");
    
    • 1
    • 2

    1.2信号与槽机制的优点

    (1) 类型安全。
    需要关联的信号和槽的签名必须是等同的,即信号的参数类型和参数个数
    与接收该信号的槽的参数类型和参数个数相同。不过,一个槽的参数个数是可以少千信号的参
    数个数的,但缺少的参数必须是信号参数的最后一个或几个参数。如果信号和槽的签名不符,
    编译器就会报错。

    (2)松散耦合。

    信号和槽机制减弱了 Qt 对象的耦合度。激发信号的 Qt 对象无须知道是哪
    个对象的哪个槽需要接收它发出的信号,它只需做的是在适当的时间发送适当的信号就可以了,
    而不需要知道也不关心它的信号有没有被接收到,更不需要知道是哪个对象的哪个槽接收到了
    信号。同样,对象的槽也不知道是哪些信号关联了自己,而一旦关联信号和槽, Qt 就保证了适
    合的槽得到了调用。即使关联的对象在运行时被删除,应用程序也不会崩溃。
    一个类若要支待信号和槽,就必须从 QObject 或 QObject 的子类继承。注意, Qt 信号和槽
    机制不支持对模板的使用。

    1.3信号与槽机制的效率

    信号和槽机制增强了对象间通信的灵活性,然而,这也损失了一些性能。同回调函数相比,
    信号和槽机制运行速度有些慢。通常,通过传递一个信号来调用槽函数会比直接调用非虚函数
    的运行速度慢 10 倍。主要原因如下。

    (1) 需要定位接收信号的对象。
    (2)安全地遍历所有的关联(如一个信号关联多个槽的情况)。
    (3)编组(marshal)/解组(unmarshal)传递的参数。
    (4)在多线程时,信号可能需要排队等待。

    然而,与创建堆对象的 new 操作及删除堆对象的 delete 操作相比,信号和槽的运行代价
    很小。信号和槽机制导致的这点性能损失对实时应用程序是可以忽略的;同信号和槽提供的
    灵活性和简便性相比,这点性能损失也是值得的。

    二、原对象系统

    QtS 元对象系统提供了对象间的通信机制(信号和槽)、运行时类型信息和动态属性
    系统的支待,是标准 C++的一个扩展,它使 Qt 能够更好地实现 GUI 图形用户界面编程。
    QtS 的元对象系统不支持 C++模板,尽管该模板扩展了标准 C++ 的功能。但是,元对象
    系统提供了模板无法提供的一些特性。 QtS 元对象系统基千以下三个事实。

    (1)基类QObject:

    任何需要使用元对象系统功能的类必须继承自QObject

    (2)Q_OBJECT宏:

    Q_OBJECT 宏必须出现在类的私有声明区中,用千启动元对象的特性。

    (3)元对象编译器(Meta-Object Compiler,moc):

    为QObject 子类实现元对象特性提供必要的代码实现。

    三、布局管理器

    在设计较复杂的 GUI 用户界面时,仅通过指定窗口部件的父子关系以期达到加载和排列窗
    口部件的方法是行不通的,最好的办法是使用 Qt 提供的布局管理器。

    QGridLayout *mainLayout=new QGridLayout(this);     //(a)
    mainLayout->addWidget(label1,0,0); 				   //(b)
    mainLayout->addWidget(lineEdit,0,1);
    mainLayout->addWidget(label2,1,0);
    mainLayout->addWidget(button,1,1);
    setLayout(mainLayout);                             //(c)
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6

    其中,
    (a)QGridLayout *mainLayout=new QGridLayout(this): 创建一个网格布局管理器对象mainLayout, 并用 this 指出父窗口。

    (b) mainLayout->addWidget(…):分别将控件对象 labell 、 lineEdit 、 label2 和 button 放置在布局管理器中,还可以在创建布局管理器对象时不必指明父窗口。

    (c) QWidget:":setLayout(…):将布局管理器添加到对应的窗口部件对象中。因为这里的主窗口就是父窗口,所以直接调用 setLayout(mainLayout)即可。


    四、代码实例

    4.1、widget.h 原码分析

    #ifndef WIDGET_H
    #define WIDGET_H
    
    #include 
    #include 
    #include 
    #include 
    namespace Ui {
    class Widget;
    }
    
    class Widget : public QWidget
    {
        Q_OBJECT
    
    public:
        explicit Widget(QWidget *parent = nullptr);
        ~Widget();
              
    
    private:
        Ui::Widget *ui;
        QPushButton *button;        //声明一个QPushButton类型的指针
        QLineEdit *LineEdit;        //声明一个QLineEdit类型的指针
    private slots:
         void button_on();          //声明一个函数用于:button按钮触发连接用的槽
    };
    
    #endif // WIDGET_H
    
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30

    4.2、widget.h 原码分析

    #include "widget.h"
    #include "ui_widget.h"
    #include 
    Widget::Widget(QWidget *parent) :
        QWidget(parent),
        ui(new Ui::Widget)
    {
        ui->setupUi(this);
    
        button = new QPushButton("信号与槽");       //初始化button指针,分配空间
        LineEdit = new QLineEdit;                 //初始化LineEdit指针,分配空间
        connect(button,SIGNAL(clicked(bool)),this,SLOT(button_on()));  //用于连接按钮信号与槽的触发
        QGridLayout *mainLayout = new QGridLayout;    //声明一个QGridLayout类型,并分配空间,用于画图
    
        mainLayout->addWidget(button,2,0);        //用画图指针设计按钮在窗口中的位置
        mainLayout->addWidget(LineEdit,1,0);
    
    
    
        setLayout(mainLayout);
    }
    
    Widget::~Widget()
    {
        delete ui;
    }
    void Widget::button_on()
    {
        LineEdit->setText("信号与槽连接成功");
        qDebug()<<1;
    }
    
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32

    4.2、实际效果图

    在这里插入图片描述

  • 相关阅读:
    windows、ubuntu双系统安装教程
    有关BSP驱动该如何学习的个人看法
    day36
    2022杭电多校九 1007-Matryoshka Doll(动态规划)
    使用C语言实现并查集
    sequence启动的两种方式
    【Codeforces Round #805 (Div. 3)(A~C)】
    【直播预约】数据库OBCP认证全面升级公开课
    doris的单节点安装部署(详细)
    简单排序算法、二分法以及对数器
  • 原文地址:https://blog.csdn.net/weixin_44759598/article/details/126280571