• Qt学习笔记详解(1)- 对象树与信号与槽


    对象树

    qt使用对象树进行对象管理,方便内存管理

    作为树状图,那就会存在分岔(父对象和子对象)。

     1.当创建一个QObject对象的时候,创建一个父对象指针给构构造函数,会自动添加到该对象的父对象的children()列表下面,当父对象析构的时候,父对象的所有子对象都会析构(当用户关闭以一个对话框的时候,会将对话框的所有内容全部删除)

    2.当析构子对象的时候,会从父对象的子对象列表中删除。(优点:自动销毁子类对象,不需要管控内存情况)(在对话框删除一个工具栏,但自动调整屏幕显示)

    3.只要对象定义于QObject或者继承于QObject,就不用delete对象,因为QObject是这一切的基类。

    4.QWidget是能够在屏幕上显示的一切组件的父类,继承于QObject。

    5.堆区对象树的构造和析构:构造顺序是:父对象->子对象,而析构顺序是:子对象->父对象,但在运行程序发现,构造和理论推算一样,但是析构却和理论相反,原因是:析构是从父对象开始打印Qdebug()的相关信息,直到枝叶尽头,然后从最后创建的子对象开始,往回开始析构。这个时候才开始释放内存

     千万注意:析构 ≠ 释放!!!!!!

    6.子对象只能对应一个父对象,父对象可以对应对各子对象。 

    7.对象树的相关疑惑问题:

    (a).在堆区:如果子对象在父对象的前面创建,就会析构两次子对象(父对象一次,子对象一次),从而出现程序的报错。       栈区不允许顺序出错,否则会crash。

    (b).当顺序正常的时候,栈区先析构子对象同时释放内存,然后是父对象同时释放内存。

    信号与槽(Signal and Slot)

    我用的是Qt5版本,所以connect函数已经将信号与槽连接在了一起,不需要使用SIGNAL()和SLOT()。

     

     QT  与 槽 的连接机制

    (1)信号与槽式QT对象之间的通信,可以通过某种触发或者代码触发。

    (2)信号和槽的连接式动态的,对象释放后会自动断开所有的信号和槽,所以基本不会使disconnect()。

    (3)QObject::connect(发送信号对象的地址,信号,接收信号的对象,槽函数)

    (4)存在一对一,多对一,一对多情况

    my_widget.cpp

    1. #include "my_widget.h"
    2. #include"QPushButton"
    3. my_Widget::my_Widget(QWidget *parent)
    4. : QWidget(parent)
    5. {
    6. QPushButton *btn = new QPushButton;
    7. btn->show(); //show以顶层方式弹出窗口
    8. //让 my_widget 依赖在窗口
    9. btn->setParent(this);
    10. //显示文本
    11. //btn->resize(200,200);
    12. btn->setText("第一个按钮");
    13. //;创建第二个文本
    14. QPushButton *btn2 = new QPushButton("第二个按钮",this);
    15. btn2->move(100,200);
    16. resize(600,400);
    17. //设置窗口的大小和标题
    18. setFixedSize(600,400);
    19. setWindowTitle("text");
    20. //需求 按钮关闭窗口 参数1 信号的发送者 参数2 发送的信号(函数的地址) 参数3 信号的接受者 参数4 处理的曹函数
    21. connect(btn,&QPushButton::clicked,this,&my_Widget::close);
    22. }

    my_widget.h

    1. t : public QWidget
    2. {
    3. Q_OBJECT
    4. public:
    5. my_Widget(QWidget *parent = nullptr);
    6. ~my_Widget();
    7. };
    8. #endif // MY_WIDGET_H
    1. signals:
    2. //自定义信号 写到signals下
    3. //返回值 为 void ,只需要声明,不需要实现
    4. //可以有参数,可以重载
    5. void hungry();
    6. void hungry(QString namefood);
    7. public slots:
    8. //返回为void , 需要声明和实现
    9. void treat();
    10. void treat(QString namefood);

    当出现同名的析构函数的时候,需要用函数指针进行传址。然后用connect进行连接

    1. void (Teacher:: *teacherSignal)(QString) = &Teacher::hungry;
    2. void (Student:: *studentSlot)(QString) = &Student::treat;
    3. connect(btn,&QPushButton::clicked,this,&Widget::classIsOver);

    Lambda表达式

    使用Lambda表达式可以简化代码操作,可以直接对槽函数进行值传递。

    1. QPushButton *but1 = new QPushButton(this);
    2. QPushButton *but2 = new QPushButton(this);
    3. but1->move(100,100);
    4. int n = 10;
    5. connect(but1,&QPushButton::clicked,this,[n]()mutable{n = 100+10;qDebug()<
    6. connect(but2,&QPushButton::clicked,this,[=](){qDebug()<

     思考:当按键but1按下时打印110,当按键but2按下的时候,n竟然还是10?

    原因:因为mutable传进去的只是n的一个拷贝对象,而不是本尊,所以不会影响到别的地方调用。

  • 相关阅读:
    局域网MongoDB的数据库访问不了
    Python中setdefault()通过键查找字典中对应的值
    基于Python实现的手写数字图像识别
    Rust基础入门之(基本类型)
    Roreg复现
    Socks5代理IP:网络安全的重要组成部分
    JAVA计算机毕业设计-物流管理系统-(附源码、数据库)
    react源码分析:babel如何解析jsx
    代码改造:设计模式之责任链
    树模型(2)随机森林
  • 原文地址:https://blog.csdn.net/weixin_63032791/article/details/127569028