首页 > 其他分享 >QT学习笔记2(QPushButton类、对象树、信号与槽,Lambdabiao表达式)

QT学习笔记2(QPushButton类、对象树、信号与槽,Lambdabiao表达式)

时间:2024-08-27 17:23:30浏览次数:5  
标签:Lambdabiao QT parent public QPushButton include MainWindow QObject

那些难过的日子,都一起陪伴,也不说些什么大道理。

难过的时候,所有人都给你讲一堆大道理。

只有你的好朋友,懂你的沉默,陪你一起在墙角蹲着。


对象树

QT中创建QObject对象会时,构造函数会接收一个Parent父对象指针作为参数。

这就于相当于创建QObject对象时,可以提供一个父类,创建的QObject对象会自动添加到父对象的children()列表中。

当父对象析构时,这个列表中的所有对象都会被析构。例:一个按钮有一个QShortcut(快捷键)作为子对象,删除按钮类时,快捷键也被删除。

这种机制被称为对象树,QObject是以对象树的形式组织起来的,从QObject类向下(子对象)构造,析构时自下(子对象)往上(父对象)析构。

当创建的对象在在堆区时(指定父对象为QObject子类或者其派生类---setParent()),可以不用管理释放操作,一定程度上简化了内存回收机制。

信号和槽

connect(信号发送者,发送具体的信号(信号函数的地址),信号接收者,信号处理函数(槽函数的地址))

信号槽的优点,松散耦合,接收与发送之间没有关联,通过connect连接。

mainwindow.h文件

#ifndef MAINWINDOW_H
#define MAINWINDOW_H

#include <QMainWindow>//包含头文件MainWindow窗口类

class MainWindow : public QMainWindow
{
    Q_OBJECT//Q_OBJECT类,允许使用信号和槽机制

public:
    MainWindow(QWidget *parent = nullptr);//Mainwindow的有参构造函数,参数默认值为0,空指针,在声明和构造中只有一个有参数的默认值
    ~MainWindow();
};
#endif // MAINWINDOW_H

mypushbutton.h文件

#ifndef MYPUSHBUTTON_H
#define MYPUSHBUTTON_H

#include <QPushButton>

class MyPushButton : public QPushButton
{
    Q_OBJECT
public:
    explicit MyPushButton(QWidget *parent = nullptr);//系统提供的析构函数
    ~MyPushButton();
signals:   
};

#endif // MYPUSHBUTTON_H

main.cpp文件

#include "mainwindow.h"
#include <QApplication>//包含一个应用程序的头文件
int main(int argc, char *argv[])//argc 命令行变量的数量,argv命令行变量的数组
{
    QApplication a(argc, argv);//应用程序的对象,有且只有一个
    MainWindow w;//主窗口程序对象
    w.show();//窗口对象不会默认显示,需要调用Show方法显示窗口
    return a.exec();//让应用对象进入消息循环,代码会阻塞的这一行,不会执行接下来的代码
}

MainWindow.cpp文件

#include "mainwindow.h"
#include <QPushButton>//按钮类头文件
#include "mypushbutton.h"
MainWindow::MainWindow(QWidget *parent)
    : QMainWindow(parent)//初始化列表
{
    resize(200,200);//重置窗口大小
    setWindowTitle("第一个窗口");//设置主窗口标题
    setFixedSize(200,200);//设置窗口为固定大小
    QPushButton *btn =new QPushButton;
    btn->setParent(this);//让创建的按钮依赖于MainWindow窗口
     btn->resize(100,25);//重置按钮大小
    btn->setText("第一个按钮");//显示文本
     //创建第二个按钮,按照控件大小创建窗口
    QPushButton *btn2=new QPushButton("第二个按钮",this);
    btn2->move(50,50);//移动btn2按钮
    btn->move(50,0);
    //创建自定义按钮
    MyPushButton *mbtn=new MyPushButton;
    mbtn->setText("我的按钮");
    mbtn->setParent(this);
    mbtn->resize(100,25);
    mbtn->move(50,100);
    //两种书写方式,由于信号是继承父类的,信号与槽可以用父类的函数地址,也可以使用自己的函数地址
    connect(btn,&QPushButton::clicked,this,&QWidget::close);//点击“第一个按钮”,关闭窗口
    connect(mbtn,&MyPushButton::clicked,this,&MainWindow::close);
    qDebug()<<"调用MainWIndow构造函数";//打印顺序相反,原因是程序运行到这一行,会先确认该类是否存在子类,如果有会暂停析构,跳转到子类的析构函数,执行子类的析构,子类析构完继续析构该类
}
MainWindow::~MainWindow() {
    qDebug()<<"调用MainWIndow析构函数";
}

mypushbutton.cpp文件

#include "mypushbutton.h"
#include <QDebug>//打印调试信息

MyPushButton::MyPushButton(QWidget *parent)
    : QPushButton{parent}
{
    qDebug()<<"调用我的按钮构造函数";

}
MyPushButton::~MyPushButton()
{

     qDebug()<<"调用我的按钮析构函数";
}

拓展:

1.信号可以与连接信号

2.信号可以连接多个槽函数

3.多个信号可以连接一个槽函数

4.槽函数跟信号的参数类型必须一一对应,参数个数可以不一致,信号的参数个数可以多于槽函数的参数个数。

需求:使用QPushButton类实现下课了,老师布置作业,学生写作业

mainwindow.h文件

#ifndef MAINWINDOW_H
#define MAINWINDOW_H

#include <QMainWindow>
#include <QDebug>
#include "student.h"
#include "teacher.h"
QT_BEGIN_NAMESPACE
namespace Ui {
class MainWindow;
}
QT_END_NAMESPACE

class MainWindow : public QMainWindow
{
    Q_OBJECT

public:
    MainWindow(QWidget *parent = nullptr);
    ~MainWindow();
    void classOver();

private:
    Ui::MainWindow *ui;
    Student *st;
    Teacher *te;
};
#endif // MAINWINDOW_H

student.h文件

#ifndef STUDENT_H
#define STUDENT_H

#include <QObject>

class Student : public QObject
{
    Q_OBJECT
public:
    explicit Student(QObject *parent = nullptr);

signals:
public slots:
        void writeHW();//早期Qt版本槽函数必须写道public slots下,高级版本可以写到public或者全局下。
        void writeHW(QString homework);//槽函数重载
};

#endif // STUDENT_H

teacher.h文件

#ifndef TEACHER_H
#define TEACHER_H

#include <QObject>
class Teacher : public QObject
{
    Q_OBJECT
public:
    explicit Teacher(QObject *parent = nullptr);

signals:
    void assignHW();//信号需要声明,不需要实现(重点),有参数可以重载。需要声明不需要实现,可以有参数可以重载
    void assignHW(QString string);//信号重载
public slots:
};

#endif // TEACHER_H

main.cpp文件

#include "mainwindow.h"

#include <QApplication>

int main(int argc, char *argv[])
{
    QApplication a(argc, argv);
    MainWindow w;
    w.show();
    return a.exec();
}

mainwindow.cpp文件

#include "mainwindow.h"
#include "./ui_mainwindow.h"
#include <QPushButton>
#include <QDebug>
//放学了,老师布置作业,学生写作业
MainWindow::MainWindow(QWidget *parent)
    : QMainWindow(parent)
    , ui(new Ui::MainWindow)
{
    ui->setupUi(this);
     st=new Student(this);//指定父对象为MainWindow
     te=new Teacher(this);
    // resize(200,200);
    // QPushButton *btn=new QPushButton("按钮一",this);
    // btn->resize(80,30);
    // btn->move(60,85);
    //connect(te,Teacher::assignHW,st,Student::writeHW)
    // void (Teacher::*TeHomeworkS)(QString)=&Teacher::assignHW;重载后使用上述方式,编译器无法识别函数出来的版本和重载版本使用函数指针指向函数地址
    // void (Student::*StHomeworkW)(QString)=&Student::writeHW;
    // connect(te,TeHomeworkS,st,StHomeworkW);//连接带参数的信号与槽
    // classOver();
    // void (Teacher::*TeHomeworkS1)(void)=&Teacher::assignHW;//无参信号函数指针
    // void (Student::*StHomeworkW1)(void)=&Student::writeHW;
    // connect(te,TeHomeworkS1,st,StHomeworkW1);
    // connect(btn,&QPushButton::clicked,te,TeHomeworkS1); //信号与信号连接
    // disconnect(btn,&QPushButton::clicked,te,TeHomeworkS1);//断开连接
    //
    // connect(te,SIGNAL(assignHW()),st,SLOT(writeHW()));//QT4以前的信号和槽的连接方式,参数直观,但是不做类型检测,  connect(te,SIGNAL(assignHW()),st,SLOT(writeHW(QString)));编译器不报错
    // connect(btn,SIGNAL(clicked()),te,SIGNAL(assignHW()));//底层逻辑是将函数名转换为字符串去匹配函数
    
    QPushButton *btn4=new QPushButton("吃饭",this);
    connect(btn4,&QPushButton::clicked,[=](){
        emit st->writeHW("数学");
    });//使用lambda表达式实现连接,第三个参数是this,可以省略。可以在表达式内调用任何想调用的函数





    // [=](){
    //     btn->setText("aaa");
    // }();//最后这个小括号是使函数函数声明改编为函数调用,表达式内部调用了函数
    //Lambda表达式[](){}分别为标识符(匿名函数)、参数、实现体,=可以使用表达式所在的作用范围内所有的局部变量,通过值传递的形式,推荐值传递;&是引用传递
    //表达式返回值,[]()->int{return int类型的值;}();
    
    // QPushButton *btn2=new QPushButton(this);
    // QPushButton *btn3=new QPushButton(this);
    // btn3->move(100,100);
    // int m=10;
    // connect(btn2,&QPushButton::clicked,this,[m]()mutable{m=100+10;qDebug()<<m;});//[]()mutable{},mutable关键字用于修饰值传递的变量,修改的是拷贝不是本体
    // connect(btn3,&QPushButton::clicked,this,[=](){qDebug()<<m;});
    // qDebug()<<m;

}
void MainWindow::classOver()
{
    emit te->assignHW("语文");
}
MainWindow::~MainWindow()
{
    delete ui;
}

student.cpp

#include "student.h"
#include <QDebug>
Student::Student(QObject *parent)
    : QObject{parent}
{
}

void Student::writeHW()
{
    qDebug()<<"学生写作业";
}
void Student::writeHW(QString homework)
{
    //QString 转换为char * 先转成QByteArray(.toUtf8()),再转换为char*(.data()))
    qDebug()<<"学生写"<<homework.toUtf8().data()<<"作业";
}

teacher.cpp文件

#include "teacher.h"
#include <QDebug>
Teacher::Teacher(QObject *parent)
    : QObject{parent}
{
}

C++之前的早期版本使用Lambda表达式需要在project文件中添加

CONDIG +=C++11

标签:Lambdabiao,QT,parent,public,QPushButton,include,MainWindow,QObject
From: https://blog.csdn.net/qq_64083803/article/details/141562782

相关文章

  • qt 串口学习笔记
    qt6.7串口通信在Qt6.7中进行串口通信,主要依赖于QtSerialPort模块。QtSerialPort模块提供了一套方便的API,用于访问串口。下面是如何在Qt6.7项目中使用串口通信的基本步骤:1. 添加 QtSerialPort 模块首先,确保在你的Qt项目中包含了QtSerialPort模块......
  • C++/Qt 多媒体(续二)
    一、前言        前边讲述到了Qt的两项独特的模块编程支持的另一项内容——多媒体编程,上篇文章具体讲述的包括一个QMediaPlayer类的示例代码和一个QSoundEffect类的讲解,而本章将会提供一篇示例代码——《基于QMediaRecorder类的音频录制》。    对于上篇内......
  • qt代理QItemDelegate使用
    *-----------------------------------File.h-------------------------------------------------------*#include<QTableView>#include<QItemDelegate>#include<QStandardItemModel>#include<QComboBox>#include<QCheckBox>#include<......
  • VScode+QT 无法自动补全代码的解决方法
    问题:没有添加包含的头文件路径,即include文件夹所在位置第一步找到库路径并复制(在qt安装路径中)第二步打开vscode环境配置文件,添加库路径最终效果头文件红色波浪线消失了,并且代码可以完美补全!注意事项请根据自己的来修改。记得把路径的\更换成\\或者用/表示记得在incl......
  • 【编程规范具体案例(基于Qt、微软、谷歌和AUTOSAR C++14 参考)】 C++ 编码规范 之并发篇
    目录标题并发目录12.并发编程规范12.1线程创建与管理规则12.1.1\[必须]明确定义线程的生命周期管理策略12.1.2\[必须]为关键线程设置明确的标识符12.1.3\[必须]在多线程环境中安全地处理异常12.2线程同步规则12.2.1\[必须]使用线程安......
  • Qt5.14.2 操作PostgreSQL 记录
    在Qt5.14.2中操作PostgreSQL数据库.#include<QSqlDatabase>#include<QSqlQuery>#include<QSqlError>#include<QDebug>//初始化数据库连接QSqlDatabasedb=QSqlDatabase::addDatabase("QPSQL");//qDebug()<<"aaaa"......
  • [QT]QSharedMemory读写cv::Mat
    1.写入共享内存voidWriteMat(constchar*section,constcv::Mat&img){QSharedMemory*mem=newQSharedMemory();mem->setKey(section);intsize=img.cols*img.rows*img.channels();//cols+rows+channels+data//ifexistreturn......
  • 搭建多协议的串口服务器流程:RS-232、RS-485和TCP/IP、MQTT网络协议(代码示例)
    一、项目概述在物联网(IoT)和自动化控制的快速发展中,串口通信作为一种经典的通信方式,依然发挥着重要作用。本项目旨在构建一个支持多种协议的串口服务器,能够通过串口接收和发送数据,并通过网络协议(如TCP/IP、MQTT等)与其他设备和系统进行交互。项目的目标和用途本项目的目标......
  • QT概述---详细
    目录一、QT简介二、QT核心特性  1.跨平台性  2.组件化  3.信号与槽机制  4.元对象系统(MOC)  5.国际化支持三、QT模块组成四、QT应用领域  1.桌面应用程序  2.嵌入式领域  3.移动开发  4.Web开发五、总结        本文将为大......
  • Qt+OpenCascade开发笔记(二):Qt引入occ库,搭建工程模板发布Demo
    前言  OpenCASCADE是由OpenCascadeSAS公司开发和支持的开源软件开发平台,旨在为特定领域快速开发程序而设计。它是一个面向对象的C++类库,提供了丰富的几何造型、数据交换和可视化等功能,成为许多CAD软件的核心组件。  本篇描述搭建Qt开发occ环境过程。Demo  注意......