Qt 从入门到入土

news2024/12/24 8:13:28

本文目录

  • 1. Qt 概述
    • 1.1 什么是 Qt
    • 1.2 Qt 的发展史
    • 1.3 支持的平台
    • 1.4 Qt 的版本
    • 1.5 Qt 的优点
    • 1.6 成功案例
  • 2. 创建 Qt 项目
    • 2.1 使用向导创建
    • 2.2 手动创建
    • 2.3 .pro文件
    • 2.4 一个最简单的 Qt 应用程序
    • 2.5 Qt 命名规范和常用快捷键
  • 3. 第一个 Qt 小程序
    • 3.1 按钮的创建
    • 3.2 对象模型(对象树)

1. Qt 概述

1.1 什么是 Qt

Qt 是一个跨平台的C++图形用户界面应用程序框架。它为应用程序开发者提供建立艺术级图形界面所需的所有功能。它是完全面向对象的,很容易扩展,并且允许真正的组件编程。

1.2 Qt 的发展史

  • 1991年 Qt最早由奇趣科技开发;
  • 1996年 进入商业领域,它也是目前流行的Linux桌面环境KDE的基础;
  • 2008年 奇趣科技被诺基亚公司收购,Qt称为诺基亚旗下的编程语言;
  • 2012年 Qt又被Digia公司收购;
  • 2014年 4月 跨平台的集成开发环境Qt Creator3.1.0发布,同年5月20日配发了Qt5.3正式版,至此Qt实现了对iOS、Android、WP等各平台的全面支持。

1.3 支持的平台

  • Windows – XP、Vista、Win7、Win8、Win2008、Win10等
  • Uinux/X11 – Linux、Sun Solaris、HP-UX、Compaq Tru64 UNIX、IBM AIX、SGI IRIX、FreeBSD、BSD/OS、和其他很多X11平台
  • Macintosh – Mac OS X
  • Embedded – 有帧缓冲支持的嵌入式Linux平台,Windows CE

1.4 Qt 的版本

Qt按照不同的版本发行,分为商业版和开源版:

  • 商业版:为商业软件提供开发,他们提供传统商业软件发行版,并且提供在商业有效期内的免费升级和技术支持服务。
  • 开源的LGPL版本:为了开发自有而设计的开放源码软件,它提供了和商业版本同样的功能,在GNU通用公共许可下,它是免费的。

1.5 Qt 的优点

  • 跨平台,几乎支持所有的平台;
  • 接口简单,容易上手,学习QT框架对学习其他框架有参考意义;
  • 一定程度上简化了内存回收机制;
  • 开发效率高,能够快速的构建应用程序;
  • 有很好的社区氛围,市场份额在缓慢上升;
  • 可以进行嵌入式开发。

1.6 成功案例

  • Linux桌面环境KDE
  • WPS Office 办公软件
  • Skype 网络电话
  • Google Earth 谷歌地图
  • VLC多媒体播放器
  • VirtualBox虚拟机软件

2. 创建 Qt 项目

2.1 使用向导创建

打开Qt Creator 界面选择 New Project或者选择菜单栏 【文件】-【新建文件或项目】菜单项
在这里插入图片描述

弹出New Project对话框,选择Qt Widgets Application
在这里插入图片描述

选择【Choose】按钮
在这里插入图片描述

设置项目名称和路径,按照向导进行下一步
在这里插入图片描述

选择编译套件
在这里插入图片描述

向导会默认添加一个继承自CMainWindow的类,可以在此修改类的名字和基类。默认的基类有QMainWindow、QWidget以及QDialog三个,我们可以选择QWidget(类似于空窗口),这里我们可以先创建一个不带UI的界面,继续下一步
在这里插入图片描述

系统会默认给我们添加main.cpp、mywidget.cpp、 mywidget.h和一个.pro项目文件,点击完成,即可创建出一个Qt桌面程序。

2.2 手动创建

添加一个空项目
在这里插入图片描述

选择【choose】进行下一步。设置项目名称和路径 —> 选择编译套件 --> 修改类信息 --> 完成(步骤同上),生成一个空项目。在空项目中添加文件:在项目名称上单击鼠标右键弹出右键菜单,选择【添加新文件】
在这里插入图片描述

弹出新建文件对话框
在这里插入图片描述

在此对话框中选择要添加的类或者文件,根据向导完成文件的添加。

2.3 .pro文件

在使用Qt向导生成的应用程序.pro文件格式如下:

QT       += core gui  //包含的模块

greaterThan(QT_MAJOR_VERSION, 4): QT += widgets //大于Qt4版本 才包含widget模块

TARGET = QtFirst  //应用程序名  生成的.exe程序名称

TEMPLATE = app    //模板类型    应用程序模板

SOURCES += main.cpp\   //源文件

        mywidget.cpp

HEADERS  += mywidget.h   //头文件

.pro 就是工程文件(project),它是qmake自动生成的用于生产makefile的配置文件。.pro 文件的写法如下:

  • 注释:从“#”开始,到这一行结束。
  • 模板变量告诉qmake为这个应用程序生成哪种makefile。下面是可供使用的选择:TEMPLATE = app
    • app - 建立一个应用程序的makefile。这是默认值,所以如果模板没有被指定,这个将被使用。
    • lib - 建立一个库的makefile。
    • vcapp - 建立一个应用程序的VisualStudio项目文件。
    • vclib - 建立一个库的VisualStudio项目文件。
    • subdirs - 这是一个特殊的模板,它可以创建一个能够进入特定目录并且为一个项目文件生成makefile并且为它调用make的makefile。
  • #指定生成的应用程序名:TARGET = QtDemo
  • #工程中包含的头文件:HEADERS += include/painter.h
  • #工程中包含的.ui设计文件:FORMS += forms/painter.ui
  • #工程中包含的源文件:SOURCES += sources/main.cpp sources
  • #工程中包含的资源文件:RESOURCES += qrc/painter.qrc
  • greaterThan(QT_MAJOR_VERSION, 4): QT += widgets
    这条语句的含义是,如果QT_MAJOR_VERSION大于4(也就是当前使用的Qt5及更高版本)需要增加widgets模块。如果项目仅需支持Qt5,也可以直接添加“QT += widgets”一句。不过为了保持代码兼容,最好还是按照QtCreator生成的语句编写。
  • #配置信息
    CONFIG用来告诉qmake关于应用程序的配置信息。
    CONFIG += c++11 // 使用c++11的特性
    在这里使用“+=”,是因为我们添加我们的配置选项到任何一个已经存在中。这样做比使用“=”那样替换已经指定的所有选项更安全。

2.4 一个最简单的 Qt 应用程序

main入口函数中

#include "widget.h"
#include <QApplication>   //包含一个应用程序类的头文件
int main(int argc, char *argv[])   //argc:命令行变量的数量,argv:命令行变量的数组
{
    QApplication a(argc, argv); //a:应用程序对象,在Qt中,应用程序对象有且仅有一个
    Widget w;                   //窗口对象 myWidget父类->QWidget
    w.show();                   //窗口对象 默认不会显示,必须调用show方法显示窗口
    
    return a.exec();
    //让应用程序对象进入消息循环,也就是让代码阻塞到这行,类似于system("pause")
}

解释:

  • Qt系统提供的标准类名声明头文件没有.h后缀
  • Qt一个类对应一个头文件,类名就是头文件名
  • QApplication应用程序类
    • 管理图形用户界面应用程序的控制流和主要设置。
    • 是Qt的整个后台管理的命脉它 包含主事件循环,在其中来自窗口系统和其它资源的 所有事件处理和调度。它也处理 应用程序的初始化和结束,并且 提供对话管理。
    • 对于任何一个使用Qt的图形用户界面应用程序,都正好存在一个QApplication 对象,而不论这个应用程序在同一时间内是不是有0、1、2或更多个窗口。
  • a.exec()
    程序进入消息循环,等待对用户输入进行响应。这里main()把控制权转交给Qt,Qt完成事件处理工作,当应用程序退出的时候exec()的值就会返回。在exec()中,Qt接受并处理用户和系统的事件并且把它们传递给适当的窗口部件。

2.5 Qt 命名规范和常用快捷键

  1. 命名规范
  • 类名:首字母大写,单词和单词之间首字母大写。
  • 函数名和变量名称:首字母小写,单词和单词之间首字母大写。
  1. 快捷键
  • 注释 ctrl + /
  • 运行 ctrl + r
  • 编译 ctrl + b
  • 查找 ctrl + f
  • 帮助文档 F1
  • 自动对齐 ctrl + i
  • 同名的.h和.cpp切换 F4

3. 第一个 Qt 小程序

3.1 按钮的创建

在Qt程序中,最常用的控件之一就是按钮了,首先我们来看下如何创建一个按钮:

#include "mywidget.h"
#include <QPushButton>   //按钮控件的头文件

myWidget::myWidget(QWidget *parent)
    : QWidget(parent)
{
    //创建第一个按钮
    QPushButton * btn = new QPushButton;
    //btn->show();//show以顶层方式弹出窗口控件,也就是单独显示一个窗口
    btn->setParent(this);//设置父亲,让btn对象依赖在myWidget窗口中

    btn->setText("第一个按钮");   //显示文本
    
    //创建第二个按钮 按照控件的大小创建窗口
    QPushButton * btn2 = new QPushButton("第二个按钮",this);

    btn2->move(100,100);    //移动btn2按钮

    btn2->resize(100,50);   //重新指定按钮的大小

    this->resize(600,400);  //重置窗口大小,用户可以拖拽修改窗口大小

    //设置固定窗口大小,用户不能拖拽修改窗口大小
    this->setFixedSize(600,400);

    //设置窗口标题,在这里可以像上面一样加this,也可以不加
    setWindowTitle("第一个窗口");
}

在上面的代码中,一个按钮其实就是一个QPushButton类下的对象,如果只是创建出对象,是无法显示到窗口中的,所以我们需要依赖一个父窗口,也就是指定一个父亲利用setParent函数即可,如果想设置按钮上显示的文字利用setText,移动按钮位置用move。

对于窗口而言,我们可以修改左上角窗口的标题setWindowTitle,重新指定窗口大小:resize,或者设置固定的窗口大小setFixedSize。

按钮常用API总结:

  1. show() // 以顶层方式弹出窗口控件
  2. setParent() // 选择依赖方式
  3. setText() // 设置文本
  4. resize() // 重置窗口大小
  5. move() // 移动
  6. setWindowTitle() // 设置窗口标题
  7. setFixedSize() // 设置固定窗口大小

3.2 对象模型(对象树)

在Qt中创建对象的时候会提供一个Parent对象指针,下面来解释这个 parent 到底是干什么的。

  • QObject是以对象树的形式组织起来的。

    • 当你创建一个QObject对象时,会看到QObject的构造函数接收一个QObject指针作为参数,这个参数就是 parent,也就是父对象指针。
      这相当于,在创建QObject对象时,可以提供一个其父对象,我们创建的这个QObject对象会自动添加到其父对象的children()列表。
    • 当父对象析构的时候,这个列表中的所有对象也会被析构。(注意,这里的父对象并不是继承意义上的父类!)
      这种机制在 GUI 程序设计中相当有用。例如,一个按钮有一个QShortcut(快捷键)对象作为其子对象。当我们删除按钮的时候,这个快捷键理应被删除。这是合理的。
  • QWidget是能够在屏幕上显示的一切组件的父类。

    • QWidget继承自QObject,因此也继承了这种对象树关系。一个孩子自动地成为父组件的一个子组件**。因此,它会显示在父组件的坐标系统中,被父组件的边界剪裁。例如,当用户关闭一个对话框的时候,应用程序将其删除,那么,我们希望属于这个对话框的按钮、图标等应该一起被删除。事实就是如此,因为这些都是对话框的子组件。
    • 当然,我们也可以自己删除子对象,它们会自动从其父对象列表中删除。比如,当我们删除了一个工具栏时,其所在的主窗口会自动将该工具栏从其子对象列表中删除,并且自动调整屏幕显示。

Qt 引入对象树的概念,在一定程度上解决了内存问题。

  • 当一个QObject对象在堆上创建的时候,Qt 会同时为其创建一个对象树。不过,对象树中对象的顺序是没有定义的。这意味着,销毁这些对象的顺序也是未定义的。
  • 任何对象树中的 QObject对象 delete 的时候,如果这个对象有 parent,则自动将其从 parent 的children()列表中删除;如果有孩子,则自动 delete 每一个孩子。Qt 保证没有QObject会被 delete 两次,这是由析构顺序决定的。

如果QObject在栈上创建,Qt 保持同样的行为。正常情况下,这也不会发生什么问题。来看下面的代码片段:

{
    QWidget window;
    QPushButton quit("Quit", &window);
}

作为父组件的 window 和作为子组件的 quit 都是QObject的子类(事实上,它们都是QWidget的子类,而QWidget是QObject的子类)。这段代码是正确的,quit 的析构函数不会被调用两次,因为标准 C++要求,局部对象的析构顺序应该按照其创建顺序的相反过程。因此,这段代码在超出作用域时,会先调用 quit 的析构函数,将其从父对象 window 的子对象列表中删除,然后才会再调用 window 的析构函数。

但是,如果我们使用下面的代码:

{
    QPushButton quit("Quit");
    QWidget window;
    quit.setParent(&window);
}

情况又有所不同,析构顺序就有了问题。我们看到,在上面的代码中,作为父对象的 window 会首先被析构,因为它是最后一个创建的对象。在析构过程中,它会调用子对象列表中每一个对象的析构函数,也就是说, quit 此时就被析构了。然后,代码继续执行,在 window 析构之后,quit 也会被析构,因为 quit 也是一个局部变量,在超出作用域的时候当然也需要析构。但是,这时候已经是第二次调用 quit 的析构函数了,C++ 不允许调用两次析构函数,因此,程序崩溃了。

由此我们看到,Qt 的对象树机制虽然帮助我们在一定程度上解决了内存问题,但是也引入了一些值得注意的事情。这些细节在今后的开发过程中很可能时不时跳出来烦扰一下,所以,我们最好从开始就养成良好习惯,在 Qt 中,尽量在构造的时候就指定 parent 对象,并且大胆在堆上创建。
在这里插入图片描述

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/493230.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

基于springboot的学生成绩管理系统

摘 要 随着信息技术和网络技术的飞速发展&#xff0c;人类已进入全新信息化时代&#xff0c;传统管理技术已无法高效&#xff0c;便捷地管理信息。为了迎合时代需求&#xff0c;优化管理效率&#xff0c;各种各样的管理系统应运而生&#xff0c;各行各业相继进入信息管理时代&…

LeetCode第2题——两数相加(Java)

题目描述&#xff1a; ​ 给你两个 非空 的链表&#xff0c;表示两个非负的整数。它们每位数字都是按照 逆序 的方式存储的&#xff0c;并且每个节点只能存储 一位 数字。 ​ 请你将两个数相加&#xff0c;并以相同形式返回一个表示和的链表。 ​ 你可以假设除了数字 0 之外…

考研数据结构--数组与广义表

数组与广义表 文章目录 数组与广义表数组数组的基本概念性质数组的存储结构一维数组的存储结构二维数组的存储结构 特殊矩阵的压缩存储对称矩阵上三角矩阵下三角矩阵对角矩阵 稀疏矩阵定义稀疏矩阵的三元组表示稀疏矩阵的存储结构及其基本运算算法定义存入三元组三元组元素赋值…

ChatGPT in Drug Discovery

ChatGPT是OpenAI开发的一种语言模型。这是一个在大型人类语言数据集上训练的机器学习模型&#xff0c;能够生成类似人类语言文本。它可以用于各种自然语言处理任务&#xff0c;如语言翻译、文本摘要和问题回答。在目前的工作中&#xff0c;我们讨论了ChatGPT在药物发现中的应用…

矩阵乘法之叉乘和点乘

矩阵的乘法包含两种&#xff1a;点乘和叉乘。 矩阵点乘的含义是对应元素相乘&#xff0c;例如矩阵&#xff0c;同样存在矩阵, 那么. 矩阵叉乘含义与我们平时理解矩阵相乘一致&#xff0c;即一个矩阵A&#xff0c;若要与另外一个矩阵相乘&#xff0c;另另外一个矩阵的行数必须…

【iOS】NSOperation,NSOperationQueue

文章目录 前言概念使用NSOperation&#xff0c;NSoperationQueue的好处操作和操作队列操作&#xff08;Operation&#xff09;操作队列&#xff08;Operation Queues&#xff09; NSOperation&#xff0c;NSOperationQueue常用属性和方法归纳NSOperation常用属性和方法NSOperat…

阶乘求和,求 1 + 2 + 3 + ... + 202320232023 ,阶乘总和的末尾九位数字

求 1! 2! 3! … 202320232023! &#xff0c;总和的末尾九位数字。 【学习的细节是欢悦的历程】 Python 官网&#xff1a;https://www.python.org/ Free&#xff1a;大咖免费“圣经”教程《 python 完全自学教程》&#xff0c;不仅仅是基础那么简单…… 地址&#xff1a;ht…

learn_C_deep_8 (循环语法的理解、void的用法以及理解)

目录 循环语法的理解 break关键字 continue关键字 continue跳转的位置 goto关键字 void的用法以及理解 void是否可以定义变量 为何 void 不能定义变量 void的应用场景 void 指针 循环语法的理解 for循环是一种常用的循环结构&#xff0c;它适合于在已知循环次数的情况…

ChatGPT prompt engineering (中文版)笔记 |吴恩达ChatGPT 提示工程

目录 一、资料二、 指南环境配置两个基本原则&#xff08;最重要!!!!&#xff09;原则一&#xff1a;编写清晰、具体的指令**策略一&#xff1a;使用分隔符清晰地表示输入的不同部分**&#xff0c;**分隔符可以是&#xff1a;&#xff0c;""&#xff0c;<>&…

浅谈几个通信概念-如何理解卷积,负频率,傅里叶变换,奈奎斯特采样定理?

1.如何理解卷积&#xff1f; t时刻的输出信号是t时刻之前的无数小的脉冲序列冲击引起的。 2. 如何理解欧拉公式&#xff0c;复指数信号呢&#xff1f; 可以看成一个点在复平面上以角速度w进行逆时针的旋转。 傅里叶分析&#xff1a; 整体到部分&#xff0c;把一个信号分解成无…

【网络】socket套接字基础知识

文章目录 IP与端口号TCP/UDP协议网络字节流socket套接字接口总结 IP与端口号 IP 每台主机都有自己的IP地址&#xff0c;所以当数据从一台主机传输到另一台主机就需要IP地址。报头中就会包含源IP和目的IP 源IP地址&#xff1a;发送数据报那个主机的IP地址&#xff0c;目的IP地…

JMeter开发web及手机APP自动化脚本练习

一、打开浏览器代理服务器设置 我这里用的是360浏览器&#xff0c;打开浏览器代理服务器设置&#xff0c;端口要与jmeter中的端口设置保持一致哦。 二、JMeter设置代理 JMeter设置代理&#xff08;jmeter中的端口要与360浏览器端口设置保持一致哦。&#xff09; 三、启动代理运…

BM17 二分查找-I

二分查找-I_牛客题霸_牛客网 (nowcoder.com) 设置中间值mid 每次判断目标值和中间值的大小 缩短区间 直到区间全被搜索完成 class Solution { public: /** * 代码中的类名、方法名、参数名已经指定&#xff0c;请勿修改&#xff0c;直接返回方法规定的值即可 * * * param nums …

因子挖掘框架cs优缺点介绍和使用说明

cs框架的优点和缺点 优点和ts一样,就是速度非常快缺点有好几个:必须使用根据过去一定天数计算因子值,持有一定天数之后再平衡的模式;必须使用连续的数据,如果是期货期权等需要合成连续数据。资金不足的时候不会拒单。cs框架使用方法 设计理念 计算因子由用户进行计算,因…

Yolov7论文详解

论文地址&#xff1a;https://arxiv.org/pdf/2207.02696.pdfhttps://arxiv.org/pdf/2207.02696.pdf 项目地址&#xff1a; WongKinYiu/yolov7: Implementation of paper - YOLOv7: Trainable bag-of-freebies sets new state-of-the-art for real-time object detectors (gith…

多进程多线程并发服务器代码实现

欢迎关注博主 Mindtechnist 或加入【Linux C/C/Python社区】一起学习和分享Linux、C、C、Python、Matlab&#xff0c;机器人运动控制、多机器人协作&#xff0c;智能优化算法&#xff0c;滤波估计、多传感器信息融合&#xff0c;机器学习&#xff0c;人工智能等相关领域的知识和…

R语言:鉴于计算10亿以内训练模型记录for循环的加速

文章目录 1 前言2 几个循环2.1 100以内的和2.2 100以内奇数和/偶数和 3 多重循环3.1 向量化3.2 合并循环3.3 apply函数3.4 矩阵运算3.5 foreach分解任务 4 讨论 1 前言 笔者主力机是MBAM1芯片&#xff08;8256&#xff09;&#xff0c;某个下午巩固循环突然思考到个问题&#…

【Luenberger Observer】龙贝格观测器及示例Matlab仿真

目录 龙贝格观测器 龙贝格观测器示例和仿真 Matlab仿真 龙贝格观测器 观测器&#xff1a;根据系统的输入u和输出y估计系统的状态x。 SISO系统的状态空间方程如下 龙贝格观测器&#xff0c;通过在原系统添加基于输出误差校正项&#xff0c;构造状态空间方程&#xff0c;设x_h…

如何用Jmeter压测Netty的Echo服务之自定义Jmeter的Java Sampler

前言 如果想要压测一些三方组件&#xff0c;比如MQ&#xff0c;redis什么的&#xff0c;jmeter本身是不支持的。 本文以开发一个压测netty的echo示例&#xff0c;说明如何自定义jmeter的sampler。 开发 本文以idea示例&#xff0c; 新建工程 打开idea新建一个空的maven工程…

yolov8 ONNX Runtime C++ 部署

其实个人偏爱用OpenCV DNN 部署&#xff0c;但是在前面一篇博客发现还要升级OpenCV。 笔记本的CPU 是AMD 牌子的&#xff0c;就只能用 ONNX Runtime 部署了。 目录 Pre: cv::dnn::blobFromImages() gettimeofday() rand() template 代码 utils.h utils.cpp detect.h…