Qt编程(二)-初步进阶

前言

  • 通过上篇文章我们对Qt有了初步的认识,Qt编程(一)-认识
  • 这里我们开始对Qt深入研究一下,通过之前我们知道,Qt中重要的是信号和槽,通过connect()函数连接。这里我们深入一下信号和槽

一,Qt自定义信号和槽

1,自定义信号和槽

  • 1,首先需要建两个类,一个信号类,一个槽函数类。右键项目->Add New,,新建类
    在这里插入图片描述
  • 2,设置类的属性:类名,父类,位置
    在这里插入图片描述
    在声明的槽函数里面,右键函数名,选择Refactor->在.cpp文件里面添加定义
    自定义信号类:
    在ZMSignals的头文件里面添加信号声明,不需要实现
    在这里插入图片描述
    自定义槽函数类:
    在ZMSlots类的头文件和源文件中添加自定义槽函数的定义和实现。
    在这里插入图片描述

在这里插入图片描述

  • 3,把信号和槽联系起来。
    信号和槽,需要依托一个窗口来联系,eg:widget,window 等
//emit是发送信号的标识,不写会报警告,版本问题,(非必须)
 emit zmSignal.zm_sig_start();

在这里插入图片描述

2,自定义信号带参数重载问题

  • 1,添加重载信号和槽函数
    在这里插入图片描述
    在这里插入图片描述
  • 2,发现connect的地方报错了,是因为connect时,上下文重载函数出现歧义
    在这里插入图片描述
  • 3,我们可以使用带参数的函数指针来指向我们要指向的函数,来消除歧义,下面两个方法,个人推荐第一个
#if 1 //两个方式一样,只是指针函数开放与不开放的问题
    //方法一:

    //设置两个带参数的函数指针
    void (ZMSignals::*str_sig_start)(QString) = &ZMSignals::zm_sig_start;
    void (ZMSlots::*str_slot_accept)(QString) = &ZMSlots::zm_slot_accept;

    //关联带参数的函数指针
    w.connect(&zmSignal, str_sig_start, &zmSlot, str_slot_accept);
#else
    //方法二:强制转换型,代码可读性低
    w.connect(&zmSignal, ( void (ZMSignals::*)(QString)) &ZMSignals::zm_sig_start, &zmSlot, (void (ZMSlots::*)(QString)) &ZMSlots::zm_slot_accept);
#endif

在这里插入图片描述

3,函数重载问题总结

  • 注意信号重载函数指针指向了哪一个函数,对重载函数的信号连接时,要指明到底连接的是哪一个槽函数

4,信号和槽的扩展

1,信号连接(connect):

  • 我们通过一个按钮button的clicked,触发一个信号,进而通过信号与槽的connect连接,去触发信号对应的槽函数。即:信号连接信号,一个消息信号可以绑定多个槽,同样的,一个槽函数也可以绑定多个消息信号。(多对多关系
    eg:触发按钮点击,同时触发ZMSlots对应的槽函数执行,和触发MainWindow对应的关闭槽函数
    在这里插入图片描述

2,信号的断开(disconnect):

  • 可以通过disconnect函数来断开连接,使用方式与信号连接connect一样
  • disconnect(信号发送者,信号,信号接收者,槽函数);
    在这里插入图片描述

3,信号和槽的参数

  • 信号发送的是什么,槽函数接收的就是什么,类型必须一致。
  • 信号的参数个数可以多于槽函数的参数个数,但前面相同数量的参数,其参数类型必须一一对应。反之则不可以。

二,Lambda函数

  • 为解决项目中各种信号的传递和连接,在大型项目中,信号连接和传递过度使用会使工程可阅读性降低,增加熟悉成本。

1,Lambda函数认识

  • Lambda函数也叫Lambda表达式,是匿名函数(没有名字的函数),和传统函数不一样。
  • Lambda表达式是C++11之后引入的概念,用于定义并创建匿名函数对象。

2, Lambda表达式结构:

[捕捉列表](参数)mutable-> 返回类型{函数体},
eg:

[](){
	qDebug("Hello Qt");
}
  • [],标识一个Lambda匿名函数的开始,这个必须有,不能省略,函数对象参数是 传递给 编译器自动生成的函数对象类的构造函数的。函数对象参数只能使用到Lambda定义所在的作用域范围内可见的局部变量,包括Lambda所在类的this。
  • []中括号函数对象里面对应参数有以下形式:
    • ,没有使用任何函数对象参数
    • =,函数体内使用Lambda所在范围内的可见局部变量,包括所在类的this的传值方式,相当于编译器给Lambda所在范围的所有局部变量**赋值**一份给Lambda函数
    • &,函数体内使用Lambda所在范围内的可见局部变量,包括所在类的this的引用方式,相当于编译器给Lambda所在范围的所有局部变量**引用**一份给Lambda函数
    • this,函数体内可以使用Lambda所在内的成员变量
    • a,不是字母,而是指具体一个变量a,Lambda内拷贝一个变量a使用
    • &a,Lambda内引用变量a
    • a, &b,拷贝a,引用b
    • =,&a,&b,除a,b引用外,其他变量做拷贝操作
    • &,a,b,除a,b拷贝外,其他变量做引用操作
  • mutable:标记可更改

3,为什么使用Lambda函数

  • 有些函数只是临时使用,而且它的业务逻辑也很简单,就没必要非给它取名字。在Qt中也可简化一些操作。

4,Lambda实例

在这里插入图片描述
在这里插入图片描述

三,Lambda函数扩展

1,Lambda的返回值

在这里插入图片描述

程序能正常输出结果:40;

  • 注意点:
    • -> 是有返回值的标志,int是返回值类型,在函数中直接返回,
    • 最后的()是调用函数,没有()不是函数调用,这里的函数可以定义后直接调用。

Lambda表达式,实现 斐波那契数

    //斐波那契数:Fibonacci数
    int a=0, b=1;
    [](int& a,int& b, int count){
        int ret = 0;
        for (int i =0; i<count; i++) {
            ret = a+b;
            a=b,b=ret;
            qDebug()<<ret;
        }
    }(a, b, 10);//函数调用时,传a,b进到Lambda表达式里

运行结果:
在这里插入图片描述

2,Lambda的应用

  • 无参数的信号,调用有参数的槽函数,这时候使用Lambda
    在这里插入图片描述
    实现原理解析:因为按钮点击无参数,匿名函数也没有参数,但匿名函数中调用了一个有参数的信号。

3,QString转char*

  • 由于QDebug打印时会把QString的双引号一并带上
    在这里插入图片描述
  • QString类中的一些public方法中,有一个toUtf8方法,返回为QByteArray,先转成一个字节数组。然后还有一个data方法,调用data方法,再将这个数组转成char*
    在这里插入图片描述

4,Lambda意义

  • 1,使代码更简洁高效
  • 2,如果connect,信号的接收者是this的话,this可以省略不写
  connect(btn, &QPushButton::clicked,[=](){ //信号接收者为this,可以省略不写
        this->close();
    });//发送信号

在这里插入图片描述

四,常用控件

1,QTextEdit控件

  • QTextEdit:文本编辑框,
    在这里插入图片描述
  • 实例:
    在这里插入图片描述

2,QMainWindow

  • QMainWindow是为用户提供界面的主窗口类,包含菜单栏(menubar),多个工具栏(toobar),多个铆接部件(dockwidgets浮动窗口),一个状态栏(status),及一个中心部件(centralwidget),是app的基础,eg:文本编辑器,图片编辑器等。
    在这里插入图片描述

3,菜单栏(QMenuBar)

  • 菜单栏有且仅有一个,设置方法是:setMenuBar
    在这里插入图片描述

4,添加工具栏(QToolbar)

  • 工具栏可以随意拖动的,可以放在软件左侧,上侧,下侧,右侧,甚至可以浮动在app的界面中。
  • 工具栏与菜单栏区别:菜单栏只能有一个,且在最上方;而工具栏可以有多个,并且位置多样。因此设置方式为addToolBar
    在这里插入图片描述

5,添加状态栏(QStatusBar)

  • 状态栏有且仅能添加一个,因此,设置方式为setStatusBar
    在这里插入图片描述

  • 添加状态栏,由于系统的不同,以及中文和中文符号的数量为奇数个的时候易出现乱码

    • 解决方式一,编辑里面重新设置编码规则, 并且有中文的地方前面全部加上u8,即可
      在这里插入图片描述
      在这里插入图片描述

    • 解决方式二:使用QStringLiteral(),方法,因为内部是Lambda表达式实现,高频次调用影响性能
      在这里插入图片描述

6,铆接部件、中心部件(QDockWidget、centralWidget)

1,铆接部件(dockWidget)

-铆接部件、中心部件、浮动窗口是同一个意思,通过查Qt助手文档,我们看到QDockWidget基于QWidget,浮动窗口可以有多个,因此 addDockWidget
在这里插入图片描述

  • 有一个铆接部件时,拖到中间会变成浮动,默认停靠的地方有些奇怪。这是因为,在QMainWindow中,我们还没有添加中心部件,默认中心部件是空的,因此它就直接在顶部了
    在这里插入图片描述
  • 铆接部件的设置,通过查询Qt助手文档,其跟工具栏一样

2,中心部件(centralWidget)

  • 在QMainWindow中,有个中心部件,但这个中心部件不是具体的中心部件,而是我们可以将一个具体的部件设置为中心部件。中心部件只能有一个,因此 setCentralWidget
    在这里插入图片描述
    在这里插入图片描述

五,工程及界面UI

1,UI设计器

  • 每个项目中都会有个:.ui的文件,其实就是Qt界面文件,打开文件时自动启动Qt ui设计器,在这个设计器中编辑控件,会方便直观很多,大大提高开发效率
    在这里插入图片描述
    在这里插入图片描述
  • 添加一个tableview
    在这里插入图片描述
    在这里插入图片描述
    设置完新的action后,直接拖动action到相应位置
  • 多注意 属性设置的使用,信号和槽的使用,以及右键属性设置的使用

2,Qt资源文件添加

  • 资源添加分两种方式:源码添加,和使用UI设计器添加,比如:一个QAction对象,对它添加图标,还是设置图标,添加代表可以多个,一般来说,一个工具,一个选项卡就是一个图标,因此,我们应该是设置图标,也就是设置icon,那么方法就是set开头,setIcon

1,源码添加方式

  • 源码添加图片,局限在路径,使用相对路径需要一些设置,而且路径一旦修改,图片可能又加载不出来了
    在这里插入图片描述

2,UI设计器添加方式

  • 添加前提需要创建好Resource File,右键工程->add New->Qt->Qt Resource File,新建好工程资源文件,然后把图片资源放入其中
    在这里插入图片描述
  • 创建好资源文件后,设置前置和添加图片资源,添加完资源后记得保存
    在这里插入图片描述
    在这里插入图片描述
  • 保存好,上步添加的资源后,打开UI设计器,我们往 “保存” 这个选项里面添加个icon
    在这里插入图片描述
    在这里插入图片描述
  • 选择好icon后,在UI设计器里面直接就能看到了
    在这里插入图片描述
  • 如果添加完资源文件后,我们也可以用代码去访问资源文件
    在这里插入图片描述
    在构造QIcon的时候,需要“ : + 前缀名 + 资源路径 ”

3,对话框–模态&非模态

  • 在图形用户界面,对话框是比较特色的视图,用来向用户显示信息,或者在需要的时候获得用户输入响应。构成了人机交互。
  • 标准对话框是Qt内置的一些列对话框的工具,用于简化开发,
  • Qt内置的对话框包括:
    • QColorDialog 选择颜色对话框
    • QFileDialog 选择文件或目录
    • QFontDialog 选择字体
    • QInputDialog 允许用户输入值,并将其返回
    • MessageBoxDialog 模态对话框,用于显示信息、咨询或警告等。
    • 等等
  • 模态:用户交互阻塞在当前对话框
  • 非模态:用户可以跳开当前对话框,在别的对话框交互

1,QDialog

在这里插入图片描述

  • Qt的入口main函数里面返回了一个exec,保持了Qt的主窗口一直显示,其时exec里面是个死循环,在里面一直等待控制消息,直到收到关闭信息,就会退出窗口,否则,一直循环阻塞在消息里,让原来的窗口不能继续执行。
  • 注意,lambda表达式作用域的问题,(堆栈)
    在这里插入图片描述
  • 注意内存泄漏的隐患,添加删除部件的方法
    在这里插入图片描述

2,QMessageBox

  • 1,认识
    • QMessageBox是模态对话框,在app中主要用来提供显示信息,弹出询问,警告等等。例如:我们在记事本中编辑文本,没有保存的时候,就点击关闭,那么app会弹出个QMessageBox对话框,来询问是否保存文本。
    • QMessageBox基于QDialog类的对话框
      在这里插入图片描述
  • 2,使用
    在这里插入图片描述
    • 实例:
      QMessageBox::information(this, “询问”,“你在干嘛?”);,information,question,warn,cerical,都为静态函数,有自己的内存控件,因此可以直接使用类去调用。不用再去 堆中创建
      在这里插入图片描述
    • 注意静态成员函数的返回类型,和调用方式
    • 参数的意义
      在这里插入图片描述
    • 部分源码:
 connect(ui->pb02, &QPushButton::clicked, [=](){
        //在堆中创建msg,需要控制释放,但对于模态来说,会阻塞函数不能结束,如果用户触发结束后,自动跟随函数释放内存。因此不建议这么写
//        QMessageBox* msg = new QMessageBox(this);
//        msg->information(this, "询问","你在干嘛?");

        //比较合理的编写方式,information为静态函数,因此可以直接使用类调用
        int ret = QMessageBox::information(this, "提示","你上班摸鱼5分钟了,请合理安排时间!", QMessageBox::Yes|QMessageBox::No);
        if (ret == QMessageBox::Yes) {
            qDebug()<<"好的,知道了!";
        } else {
            qDebug()<<"就是为了让老板知道!";
        }
    });

    connect(ui->pb03, &QPushButton::clicked, [=](){

        //比较合理的编写方式,question为静态函数,因此可以直接使用类调用
        QMessageBox::question(this, "询问","你在干嘛?");

    });
    connect(ui->pb04, &QPushButton::clicked, [=](){

        //比较合理的编写方式,warning为静态函数,因此可以直接使用类调用
        QMessageBox::warning(this, "警告","注意:你上班摸鱼10分钟了,可能要被老板发现了");
        critical_func(this);
    });

void critical_func(QWidget* widget)
{

//    QMessageBox::critical(widget, "致命","不好,你摸鱼被老板发现了!");

    QMessageBox* msg = new QMessageBox(widget);
    msg->resize(200,100);

    QPushButton* btn = new QPushButton();
    btn = msg->addButton("确定", QMessageBox::AcceptRole);
    msg->show();

    widget->connect(btn,&QPushButton::clicked,widget, [=](){
        msg->critical(widget, "致命","不好,你摸鱼被老板发现了!");
    });
}

3,QColorDialog

  • 在QColorDialog中的静态函数区:
    在这里插入图片描述
  • 四个参数:颜色,父类,标题名称,ColorDialogOptions 颜色选项,如果只调用getColor(),分别都添加了默认。返回值为QColor。
static QColor getColor(const QColor &initial = Qt::white,
                           QWidget *parent = nullptr,
                           const QString &title = QString(),
                           ColorDialogOptions options = ColorDialogOptions());

在这里插入图片描述

4,QFileDialog

  • 在Qt助手里面搜索QFileDialog,静态函数区,getOpenFileNamegetOpenFileNames这个就是我们获取文件路径+文件名的两个方法,对文件进行操作,我们只需要获取到路径+文件名即可,:
    在这里插入图片描述
  • 两个函数,一个不加s返回QString,另一个加s的函数返回一个QStringList,即,一个返回具体文件,一个返回文件列表。
static QString getOpenFileName(QWidget *parent = nullptr,
                                   const QString &caption = QString(),
                                   const QString &dir = QString(),
                                   const QString &filter = QString(),
                                   QString *selectedFilter = nullptr,
                                   Options options = Options());

对应五个参数:
父类:一般为this
caption:标题
dir:默认路径
selectedFilter:文件筛选,筛选显示后缀符合条件的文件
opthons:文件器,默认即可

  • 简单示例:
    在这里插入图片描述

六,总结

  • 1,通过对Qt的初步认识,我们了解到Qt界面开发的一些常用控件,知道了控件的继承关系和控件里面开放的方法。
  • 2,工程开发中有两种方式,我们在编程时,使用代码或使用UI设计器,根据不同的需求场景去做设计(性能和开发速度的博弈)
  • 3,Qt助手文档很实用,建议多多使用。
  • 4,这里我们只是对Qt的一些认识,涉及编程设计模式的地方以及更多优化性能的地方,在本内容中还没体现,后续账号会不断更新,感兴趣的同学还请关注。
  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
【项目资源】: 包含前端、后端、移动开发、操作系统、人工智能、物联网、信息化管理、数据库、硬件开发、大数据、课程资源、音视频、网站开发等各种技术项目的源码。 包括STM32、ESP8266、PHP、QT、Linux、iOS、C++、Java、python、web、C#、EDA、proteus、RTOS等项目的源码。 【项目质量】: 所有源码都经过严格测试,可以直接运行。 功能在确认正常工作后才上传。 【适用人群】: 适用于希望学习不同技术领域的小白或进阶学习者。 可作为毕设项目、课程设计、大作业、工程实训或初期项目立项。 【附加价值】: 项目具有较高的学习借鉴价值,也可直接拿来修改复刻。 对于有一定基础或热衷于研究的人来说,可以在这些基础代码上进行修改和扩展,实现其他功能。 【沟通交流】: 有任何使用上的问题,欢迎随时与博主沟通,博主会及时解答。 鼓励下载和使用,并欢迎大家互相学习,共同进步。 ————————————————————————————————————— 竞赛资料源码- 【目标受众】: 本项目适合IT相关专业各种计算机技术的源代码和项目资料,如计科、人工智能、通信工程、自动化和电子信息等的在校学生、老师或者企业员工下载使用。 也适合小白学习进阶,可以用作比赛项目、可以进行项目复刻去参加同赛道比赛。 【资源内容】: 源码与竞赛资料:教育部认可的大学生竞赛备赛资料代码、源码、竞赛总结。 功能与质量保证:这个资源库是一个宝贵的学习平台,有助于他们深入了解计算机技术的原理和应用。这些源码经过测试和验证,可以直接运行,方便学生快速上手并开始实践。 【应用场景】: 竞赛准备:适用于各种教育部认可的竞赛,如全国电子设计大赛、全国大学生智能汽车竞赛等,他们可以借助这些资料了解竞赛的规则、要求和技巧。 学习与项目开发:可以用作毕设、课设、作业和竞赛项目的开发基础,可以使用这些源码作为项目开发的基础,快速构建出具有竞争力的作品。 【互动与交流】: 资料鼓励下载和使用这些资源,并欢迎学习者进行沟通交流、互相学习、共同进步。这种互动式的学习方式有助于形成良好的学习氛围,促进知识的共享和传播,为计算机相关专业的学习者提供了一个全面的学习和发展平台。
竞赛资料源码-(全国物联网大赛一等奖,挑战杯铜奖)基于QT的人脸识别,定位导航,脑电心率测算,用GPRS传到服务端的疲劳驾驶检测系统 【目标受众】: 本项目适合IT相关专业各种计算机技术的源代码和项目资料,如计科、人工智能、通信工程、自动化和电子信息等的在校学生、老师或者企业员工下载使用。 也适合小白学习进阶,可以用作比赛项目、可以进行项目复刻去参加同赛道比赛。 【资源内容】: 源码与竞赛资料:教育部认可的大学生竞赛备赛资料代码、源码、竞赛总结。 功能与质量保证:这个资源库是一个宝贵的学习平台,有助于他们深入了解计算机技术的原理和应用。这些源码经过测试和验证,可以直接运行,方便学生快速上手并开始实践。 【应用场景】: 竞赛准备:适用于各种教育部认可的竞赛,如全国电子设计大赛、全国大学生智能汽车竞赛等,他们可以借助这些资料了解竞赛的规则、要求和技巧。 学习与项目开发:可以用作毕设、课设、作业和竞赛项目的开发基础,可以使用这些源码作为项目开发的基础,快速构建出具有竞争力的作品。 【互动与交流】: 资料鼓励下载和使用这些资源,并欢迎学习者进行沟通交流、互相学习、共同进步。这种互动式的学习方式有助于形成良好的学习氛围,促进知识的共享和传播,为计算机相关专业的学习者提供了一个全面的学习和发展平台。
【项目资源】: 包含前端、后端、移动开发、操作系统、人工智能、物联网、信息化管理、数据库、硬件开发、大数据、课程资源、音视频、网站开发等各种技术项目的源码。 包括STM32、ESP8266、PHP、QT、Linux、iOS、C++、Java、python、web、C#、EDA、proteus、RTOS等项目的源码。 【项目质量】: 所有源码都经过严格测试,可以直接运行。 功能在确认正常工作后才上传。 【适用人群】: 适用于希望学习不同技术领域的小白或进阶学习者。 可作为毕设项目、课程设计、大作业、工程实训或初期项目立项。 【附加价值】: 项目具有较高的学习借鉴价值,也可直接拿来修改复刻。 对于有一定基础或热衷于研究的人来说,可以在这些基础代码上进行修改和扩展,实现其他功能。 【沟通交流】: 有任何使用上的问题,欢迎随时与博主沟通,博主会及时解答。 鼓励下载和使用,并欢迎大家互相学习,共同进步。 ————————————————————————————————————— 竞赛资料源码- 【目标受众】: 本项目适合IT相关专业各种计算机技术的源代码和项目资料,如计科、人工智能、通信工程、自动化和电子信息等的在校学生、老师或者企业员工下载使用。 也适合小白学习进阶,可以用作比赛项目、可以进行项目复刻去参加同赛道比赛。 【资源内容】: 源码与竞赛资料:教育部认可的大学生竞赛备赛资料代码、源码、竞赛总结。 功能与质量保证:这个资源库是一个宝贵的学习平台,有助于他们深入了解计算机技术的原理和应用。这些源码经过测试和验证,可以直接运行,方便学生快速上手并开始实践。 【应用场景】: 竞赛准备:适用于各种教育部认可的竞赛,如全国电子设计大赛、全国大学生智能汽车竞赛等,他们可以借助这些资料了解竞赛的规则、要求和技巧。 学习与项目开发:可以用作毕设、课设、作业和竞赛项目的开发基础,可以使用这些源码作为项目开发的基础,快速构建出具有竞争力的作品。 【互动与交流】: 资料鼓励下载和使用这些资源,并欢迎学习者进行沟通交流、互相学习、共同进步。这种互动式的学习方式有助于形成良好的学习氛围,促进知识的共享和传播,为计算机相关专业的学习者提供了一个全面的学习和发展平台。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

☆MOON

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值