大家好,欢迎来到IT知识分享网。
一、QT
1、什么是QT
是一个跨平台的C++应用程序开发框架
具有短平快的优秀特质: 投资少、周期短、见效快、效益高
几乎支持所有的平台, 可用于桌面程序开发以及嵌入式开发
有属于自己的事件处理机制
可以高效率的开发基于窗口的应用程序。
Qt是标准 C++ 的扩展, C++的语法在Qt中都是支持的
良好封装机制使得 Qt 的模块化程度非常高,可重用性较好,可以快速上手。
Qt 提供了一种称为 signals/slots 的安全类型来替代 callback(回调函数),这使得各个元件 之间的协同工作变得十分简单。
2、QT的特点
广泛用于开发GUI程序,也可用于开发非GUI程序。
GUI = Graphical User Interface —-> 也就是基于窗口的应用程序开发。
有丰富的 API
Qt 包括多达 250 个以上的 C++ 类
可以处理正则表达式。
支持 2D/3D 图形渲染,支持 OpenGL
Qt给程序猿提供了非常详细的官方文档
支持XML,Json
框架底层模块化, 使用者可以根据需求选择相应的模块来使用
可以轻松跨平台 —> 和Java的跨平台方式不同
在不同的平台使用的是相同的上层接口,但是在底层封装了不同平台对应的API(暗度陈仓)。
3、QT的模块
Qt类库里大量的类根据功能分为各种模块,这些模块又分为以下几大类:
Qt 基本模块(Qt Essentials):提供了 Qt 在所有平台上的基本功能。
Qt 附加模块(Qt Add-Ons):实现一些特定功能的提供附加价值的模块。
增值模块(Value-AddModules):单独发布的提供额外价值的模块或工具。
技术预览模块(Technology Preview Modules):一些处于开发阶段,但是可以作为技术预览使用的模块。
Qt 工具(Qt Tools):帮助应用程序开发的一些工具。
Qt官网或者帮助文档的“All Modules”页面可以查看所有这些模块的信息。以下是官方对Qt基本模块的描述。关于其他模块感兴趣的话可以自行查阅。于其他模块感兴趣的话可以自行查阅。
模块 |
描述 |
Qt Core |
Qt 类库的核心,所有其他模块都依赖于此模块 |
Qt GUI |
设计 GUI 界面的基础类,包括 OpenGL |
Qt Multimedia |
音频、视频、摄像头和广播功能的类 |
Qt Multimedia Widgets |
实现多媒体功能的界面组件类 |
Qt Network |
使网络编程更简单和轻便的类 |
Qt QML |
用于 QML 和 JavaScript语言的类 |
Qt Quick |
用于构建具有定制用户界面的动态应用程序的声明框架 |
Qt Quick Controls |
创建桌面样式用户界面,基于 Qt Quick 的用户界面控件 |
Qt Quick Dialogs |
用于 Qt Quick 的系统对话框类型 |
Qt Quick Layouts |
用于 Qt Quick 2 界面元素的布局项 |
Qt SQL |
使用 SQL 用于数据库操作的类 |
Qt Test |
用于应用程序和库进行单元测试的类 |
Qt Widgets |
用于构建 GUI 界面的 C++ 图形组件类 |
4、QT案例
Qt发展至今已经是一个非常成熟的框架,基于这个框架许多公司开发出了很多优秀的软件,下边给大家介绍几款我们常见到的软件:
VirtualBox:虚拟机软件。
VLC多媒体播放器:一个体积小巧、功能强大的开源媒体播放器。
YY语音:又名“歪歪语音”,是一个可以进行在线多人语音聊天和语音会议的免费软件。
咪咕音乐:咪咕音乐是中国移动倾力打造的正版音乐播放器
WPS Office:金山公司(Kingsoft)出品的办公软件,与微软Office兼容性良好,个人版免费。
Skype:一个使用人数众多的基于P2P的VOIP聊天软件。
5、QtCreator
QtCreator是编写Qt程序默认使用的一款 IDE,使用VS写Qt程序也是可以的,在此不做介绍。
- 使用QtCreator创建的项目目录中不能包含中文
- QtCreator默认使用Utf8格式编码对文件字符进行编码
-
-
- 字符必须编码后才能被计算机处理
- 为了处理汉字,程序员设计了用于简体中文的GB2312和用于繁体中文的big5。
- GB2312 支持的汉字太少,1995年的汉字扩展规范GBK1.0,支持了更多的汉字。
- 2000年的 GB18030取代了GBK1.0成为了正式的国家标准。
- Unicode 也是一种字符编码方法,不过它是由国际组织设计,可以容纳全世界所有语言文字的编码方案
-
-
-
-
- utf8
- utf16
-
-
-
-
- vs写Qt程序默认使用的本地编码 -> gbk
- 修改QtCreator的编码, 菜单栏 -> 工具
-
关于这些编译套件跟大家做一个介绍,安装过程中根据自己的情况酌情选择即可。
MSVC2015 64-bit: Visual Studio 2015 使用的64位编译套件
MSVC2017 32-bit: Visual Studio 2017 使用的32位编译套件
MSVC2017 64-bit: Visual Studio 2017 使用的64位编译套件
MinGW7.3.0 32-bit: QtCreator 使用的32位编译套件
MinGW7.3.0 64-bit: QtCreator 使用的64位编译套件
UWP –> Universal Windows Platform: 用于window平台应用程序开发的编译套件
UWP 即Windows通用应用平台,在Windows 10 Mobile/Surface(Windows平板电脑)/ PC/Xbox/HoloLens等平台上运行,uwp不同于传统pc上的exe应用,也跟只适用于手机端的app有本质区别。它并不是为某一个终端而设计,而是可以在所有Windows10设备上运行。
在这个窗口中除了选择必要的编译套件,还有一些非必要组件,常用的有以下两个:
Source: Qt源码, 另外Qt的一些模块运行需要的驱动没有提供现成的动态库需要自己编译, 建议安装
Qt Charts: 用于绘制统计数据对应的图表, 比如: 折线图/曲线图等
默认的编译套件
MinGW -> Minimalist GNU for Windows
- MinGW 提供了一套简单方便的Windows下的基于GCC 程序开发环境。MinGW 收集了一系列免费的Windows 使用的头文件和库文件;
- 整合了GNU的工具集,特别是GNU 程序开发工具,如经典gcc, g++, make等。
- MinGW是完全免费的自由软件,它在Windows平台上模拟了Linux下GCC的开发环境,为C++ 的跨平台开发提供了良好基础支持,为了在Windows下工作的程序员熟悉Linux下的C++工程组织提供了条件。
二、创建第一个QT工程
1、创建项目
创建基于窗口的QT应用程序
指定项目的存储路径
注意: 项目名称根据需求自己指定即可
在指定项目的存储路径的时候, 路径中不能包含中文, 不能包含中文, 不能包含中文
指定默认的窗口类的名字以及窗口的类型
2、工程详解
(1).pro文件
QT += core gui # 用的模块QT基本模块 core 和 GUI模块 greaterThan(QT_MAJOR_VERSION, 4): QT += widgets CONFIG += c++11 # CONFIG += c++11 ----> 告诉qmake 应用程序 相关的配置信息 # ----- 我的工程使用 c++ 11 的标准和特性 # += -----> 在原有的基础上进行添加的意思 # The following define makes your compiler emit warnings if you use # any Qt feature that has been marked deprecated (the exact warnings # depend on your compiler). Please consult the documentation of the # deprecated API in order to know how to port your code away from it. DEFINES += QT_DEPRECATED_WARNINGS # You can also make your code fail to compile if it uses deprecated APIs. # In order to do so, uncomment the following line. # You can also select to disable deprecated APIs only up to a certain version of Qt. #DEFINES += QT_DISABLE_DEPRECATED_BEFORE=0x060000 # disables all the APIs deprecated before Qt 6.0.0 SOURCES += \ main.cpp \ mainwindow.cpp HEADERS += \ mainwindow.h FORMS += \ mainwindow.ui # Default rules for deployment. qnx: target.path = /tmp/$${TARGET}/bin else: unix:!android: target.path = /opt/$${TARGET}/bin !isEmpty(target.path): INSTALLS += target
(2) mainwindow.h
声明!!!
#ifndef MAINWINDOW_H #define MAINWINDOW_H #include <QMainWindow> QT_BEGIN_NAMESPACE // mainwindow.ui 文件中也有一个类叫 MainWindow, 将这个类放到命名空间 Ui 中 namespace Ui { class MainWindow; } QT_END_NAMESPACE class MainWindow : public QMainWindow { Q_OBJECT // 这个宏是为了能够使用Qt中的信号槽机制 public: MainWindow(QWidget *parent = nullptr); ~MainWindow(); private: Ui::MainWindow *ui; // 定义指针指向窗口的 UI 对象 }; #endif // MAINWINDOW_H
(3)mainwindow.cpp
#include "mainwindow.h" #include "ui_mainwindow.h" MainWindow::MainWindow(QWidget *parent): QMainWindow(parent), ui(new Ui::MainWindow) { //会自动调用该类的 构造函数 //这个就是窗口的构造函数 ---> 实现整个UI // 将 mainwindow.ui 的实例对象和 当前类的对象进行关联 // 这样同名的连个类对象就产生了关联, 合二为一了 ui->setupUi(this); } MainWindow::~MainWindow() { delete ui; }
(4)main.cpp
#include "mainwindow.h" #include <QApplication> int main(int argc, char *argv[]) { QApplication a(argc, argv); MainWindow w; w.show(); return a.exec(); }
(5)mainwindow.ui
<!-- 双击这个文件看到的是一个窗口界面, 如果使用文本编辑器打开看到的是一个XML格式的文件 --> <!-- 看不懂这种格式没关系, 我们不需要在这种模式下操作这个文件。 --> <!-- 这里只是给大家介绍这个文件的本质 --> <?xml version="1.0" encoding="UTF-8"?> <ui version="4.0"> <class>MainWindow</class> <widget class="QMainWindow" name="MainWindow"> <property name="geometry"> <rect> <x>0</x> <y>0</y> <width>800</width> <height>600</height> </rect> </property> <property name="windowTitle"> <string>MainWindow</string> </property> <widget class="QWidget" name="centralwidget"/> <widget class="QMenuBar" name="menubar"> <property name="geometry"> <rect> <x>0</x> <y>0</y> <width>800</width> <height>23</height> </rect> </property> </widget> <widget class="QStatusBar" name="statusbar"/> </widget> <resources/> <connections/> </ui>
三、QT中的窗口类
我们在通过Qt向导窗口基于窗口的应用程序的项目过程中倒数第二步让我们选择跟随项目创建的第一个窗口的基类, 下拉菜单中有三个选项,
分别为: QMainWindow、QDialog、QWidget如下图:
1、基础窗口类
常用的窗口类有3个
在创建Qt窗口的时候, 需要让自己的窗口类继承上述三个窗口类的其中一个
- QWidget
-
- 所有窗口类的基类
- Qt中的控件(按钮, 输入框, 单选框…)也属于窗口, 基类都是QWidget
- 可以内嵌到其他窗口中: 没有边框
- 可以不内嵌单独显示: 独立的窗口, 有边框
- QDialog
-
- 对话框类, 后边的章节会具体介绍这个窗口
- 不能内嵌到其他窗口中
- QMainWindow
-
- 有工具栏, 状态栏, 菜单栏, 后边的章节会具体介绍这个窗口
- 不能内嵌到其他窗口中
2、窗口的显示
- 内嵌窗口
-
- 依附于某一个大的窗口, 作为了大窗口的一部分
- 大窗口就是这个内嵌窗口的父窗口
- 父窗口显示的时候, 内嵌的窗口也就被显示出来了
- 不内嵌窗口
-
- 这类窗口有边框, 有标题栏
- 需要调用函数才可以显示
// QWidget是所有窗口类的基类, 调用这个提供的 show() 方法就可以显示将任何窗口显示出来 // 非模态显示 void QWidget::show(); // 显示当前窗口和它的子窗口 // 对话框窗口的非模态显示: 还是调用show() 方法 // 对话框窗口的模态显示 [virtual slot] int QDialog::exec();
四、坐标体系
1、窗口的坐标原点
所有坐标的确定都需要先找到坐标原点, Qt的坐标原点在窗口的左上角
x轴向右递增 y轴向下递增
2、窗口的相对坐标
在一个Qt窗口中一般都有很多子窗口内嵌到这个父窗口中,其中每个窗口都有自己的坐标原点,子窗口的位置也就是其使用的坐标点就是它的父窗口坐标体系中的坐标点。
- 在Qt的某一个窗口中有可能有若干个控件, 这个控件都是嵌套的关系
-
- A窗口包含B窗口, B窗口包含C窗口
- 每个窗口都有坐标原点, 在左上角
-
- 子窗口的位置是基于父窗口的坐标体系来确定的, 也就是说通过父窗口左上角的坐标点来确定自己的位置
- Qt中窗口显示的时候使用的相对坐标, 相对于自己的父窗口
- 将子窗口移动到父窗口的某个位置
// 所有窗口类的基类: QWidget // QWidget中提供了移动窗口的 API函数 // 参数 x, y是要移动的窗口的左上角的点, 窗口的左上角移动到这个坐标点 void QWidget::move(int x, int y); void QWidget::move(const QPoint &);
五、内存回收 了解
在Qt中创建对象的时候会提供一个 Parent对象指针(可以查看类的构造函数),下面来解释这个parent到底是干什么的。 QObject是以对象树的形式组织起来的。当你创建一个QObject对象时,会看到QObject的构造函数接收一个QObject指针作为参数,这个参数就是 parent,也就是父对象指针。 这相当于,在创建QObject对象时,可以提供一个其父对象,我们创建的这个QObject对象会自动添加到其父对象的children()列表。当父对象析构的时候,这个列表中的所有对象也会被析构。(注意,这里的父对象并不是继承意义上的父类!) ----> C++ 虚析构!!! QWidget是能够在屏幕上显示的一切组件的父类。QWidget继承自QObject,因此也继承了这种对象树关系。一个孩子自动地成为父组件的一个子组件。因此,它会显示在父组件的坐标系统中,被父组件的边界剪裁。例如,当用户关闭一个对话框的时候,应用程序将其删除,那么,我们希望属于这个对话框的按钮、图标等应该一起被删除。事实就是如此,因为这些都是对话框的子组件。 Qt 引入对象树的概念,在一定程度上解决了内存问题。 当一个QObject对象在堆上创建的时候,Qt 会同时为其创建一个对象树。不过,对象树中对象的顺序是没有定义的。这意味着,销毁这些对象的顺序也是未定义的。 任何对象树中的 QObject对象 delete 的时候,如果这个对象有 parent,则自动将其从 parent 的children()列表中删除;如果有孩子,则自动 delete 每一个孩子。Qt 保证没有QObject会被 delete 两次,这是由析构顺序决定的。
综上所述, 我们可以得到一个结论: Qt中有内存回收机制, 但是不是所有被new出的对象被自动回收, 满足条件才可以回收, 如果想要在Qt中实现内存的自动回收, 需要满足以下两个条件:
-
- 创建的对象必须是QObject类的子类(间接子类也可以)
-
-
- QObject类是没有父类的, Qt中有很大一部分类都是从这个类派生出去的
-
-
-
-
- Qt中使用频率很高的窗口类和控件都是 QObject 的直接或间接的子类
- 其他的类可以自己查阅Qt帮助文档
-
-
-
- 创建出的类对象, 必须要指定其父对象是谁, 一般情况下有两种操作方式:
// 方式1: 通过构造函数 // parent: 当前窗口的父对象, 找构造函数中的 parent 参数即可 QWidget::QWidget(QWidget *parent = Q_NULLPTR, Qt::WindowFlags f = Qt::WindowFlags()); QTimer::QTimer(QObject *parent = nullptr); // 方式2: 通过setParent()方法 // 假设这个控件没有在构造的时候指定符对象, 可以调用QWidget的api指定父窗口对象 void QWidget::setParent(QWidget *parent); void QObject::setParent(QObject *parent);
六、数据类型
因为Qt是一个C++ 框架, 因此C++中所有的语法和数据类型在Qt中都是被支持的, 但是Qt中也定义了一些属于自己的数据类型, 下边给大家介绍一下这些基础的数类型。
QT基本数据类型定义在#include 中,QT基本数据类型有:
类型名称 |
注释 |
备注 |
qint8 |
signed char |
有符号8位数据 |
qint16 |
signed short |
16位数据类型 |
qint32 |
signed int |
32位有符号数据类型 |
qint64 |
long long int 或(__int64) |
64位有符号数据类型,Windows中定义为__int64 |
qintptr |
qint32 或 qint64 |
指针类型 根据系统类型不同而不同,32位系统为qint32、64位系统为qint64 |
qlonglong |
long long int 或(__int64) |
Windows中定义为__int64 |
qptrdiff |
qint32 或 qint64 |
根据系统类型不同而不同,32位系统为qint32、64位系统为qint64 |
qreal |
double 或 float |
除非配置了-qreal float选项,否则默认为double |
quint8 |
unsigned char |
无符号8位数据类型 |
quint16 |
unsigned short |
无符号16位数据类型 |
quint32 |
unsigned int |
无符号32位数据类型 |
quint64 |
unsigned long long int 或 (unsigned __int64) |
无符号64比特数据类型,Windows中定义为unsigned __int64 |
quintptr |
quint32 或 quint64 |
根据系统类型不同而不同,32位系统为quint32、64位系统为quint64 |
qulonglong |
unsigned long long int 或 (unsigned __int64) |
Windows中定义为__int64 |
uchar |
unsigned char |
无符号字符类型 |
uint |
unsigned int |
无符号整型 |
ulong |
unsigned long |
无符号长整型 |
ushort |
unsigned short |
无符号短整型 |
虽然在Qt中有属于自己的整形或者浮点型, 但是在变成过程中这些一般不用, 常用的类型关键字还是 C/C++中的 int, float, double 等。
七、log日志
1 在调试窗口中输入日志
在Qt中进行log输出, 一般不使用c中的printf, 也不是使用C++中的cout, Qt框架提供了专门用于日志输出的类, 头文件名为 QDebug, 使用方法如下:
#include <QDebug> // 包含了QDebug头文件, 直接通过全局函数 qDebug() 就可以进行日志输出了 qDebug() << " abcdefg" << endl; qDebug() << "Date:" << QDate::currentDate(); qDebug() << "Types:" << QString("String") << QChar('x'); // 和全局函数 qDebug() 类似的日志函数还有: qWarning(), qInfo(), qCritical() int num = 666; float i = 11.11f; qWarning() << "num = " << num << " i = " << i; qInfo() << "num = " << num << " i = " << i; qCritical() << "num = " << num << " i = " << i;
八、字符串类型
在Qt中不仅支持C, C++中的字符串类型, 而且还在框架中定义了专属的字符串类型, 我们必须要掌握在Qt中关于这些类型的使用和相互之间的转换。
语言类型 |
字符串类型 |
C |
char * |
C++ |
std::string, char * |
Qt |
QByteArray, QString 等 |
1、QByteArray
在Qt中QByteArray可以看做是c语言中 char*的升级版本。
我们在使用这种类型的时候可通过这个类的构造函数申请一块动态内存,用于存储我们需要处理的字符串数据。
下面给大家介绍一下这个类中常用的一些API函数,大家要养成遇到问题主动查询帮助文档的好习惯。
(1)构造
// 构造一个空字符串对象 QString::QString(); // 将 char* 字符串 转换为 QString 类型 QString::QString(const char *str); // 将 QByteArray 转换为 QString 类型 QString::QString(const QByteArray &ba); // 其他重载的同名构造函数可参考Qt帮助文档, 此处略
(2)数据操作
// 尾部追加数据 // 其他重载的同名函数可参考Qt帮助文档, 此处略 QString &QString::append(const QString &str); QString &QString::append(const char *str); QString &QString::append(const QByteArray &ba); void QString::push_back(const QString &other); // 头部添加数据 // 其他重载的同名函数可参考Qt帮助文档, 此处略 QString &QString::prepend(const QString &str); QString &QString::prepend(const char *str); QString &QString::prepend(const QByteArray &ba); void QString::push_front(const QString &other); // 插入数据, 将 str 插入到字符串第 position 个字符的位置(从0开始) // 其他重载的同名函数可参考Qt帮助文档, 此处略 QString &QString::insert(int position, const QString &str); QString &QString::insert(int position, const char *str); QString &QString::insert(int position, const QByteArray &str); // 删除数据 // 从大字符串中删除len个字符, 从第pos个字符的位置开始删除 QString &QString::remove(int position, int n); // 从字符串的尾部删除 n 个字符 void QString::chop(int n); // 从字节串的 position 位置将字符串截断 (前边部分留下, 后边部分被删除) void QString::truncate(int position); // 将对象中的数据清空, 使其为null void QString::clear(); // 字符串替换 // 将字节数组中的 子字符串 before 替换为 after // 参数 cs 为是否区分大小写, 默认区分大小写 // 其他重载的同名函数可参考Qt帮助文档, 此处略 QString &QString::replace(const QString &before, const QString &after, Qt::CaseSensitivity cs = Qt::CaseSensitive);
(3)子字符串查找和判断
// 参数 cs 为是否区分大小写, 默认区分大小写 // 其他重载的同名函数可参考Qt帮助文档, 此处略 // 判断字符串中是否包含子字符串 str, 包含返回true, 否则返回false bool QString::contains(const QString &str, Qt::CaseSensitivity cs = Qt::CaseSensitive) const; // 判断字符串是否以字符串 ba 开始, 是返回true, 不是返回false bool QString::startsWith(const QString &s, Qt::CaseSensitivity cs = Qt::CaseSensitive) const; // 判断字符串是否以字符串 ba 结尾, 是返回true, 不是返回false bool QString::endsWith(const QString &s, Qt::CaseSensitivity cs = Qt::CaseSensitive) const;
(4)遍历
// 使用迭代器 iterator QString::begin(); iterator QString::end(); // 使用数组的方式进行遍历 // i的取值范围 0 <= position < size() const QChar QString::at(int position) const const QChar QString::operator[](int position) const;
(5)查看字节数
// 返回字节数组对象中字符的个数 (字符个数和字节个数是不同的概念) int QString::length() const; int QString::size() const; int QString::count() const; // 返回字节串对象中 子字符串 str 出现的次数 // 参数 cs 为是否区分大小写, 默认区分大小写 int QString::count(const QStringRef &str, Qt::CaseSensitivity cs = Qt::CaseSensitive) const;
(6)类型转换
// 将int, short, long, float, double 转换为 QString 类型 // 其他重载的同名函数可参考Qt帮助文档, 此处略 QString &QString::setNum(int n, int base = 10); QString &QString::setNum(short n, int base = 10); QString &QString::setNum(long n, int base = 10); QString &QString::setNum(float n, char format = 'g', int precision = 6); QString &QString::setNum(double n, char format = 'g', int precision = 6); [static] QString QString::number(long n, int base = 10); [static] QString QString::number(int n, int base = 10); [static] QString QString::number(double n, char format = 'g', int precision = 6); // 将 QString 转换为 int, short, long, float, double 类型 int QString::toInt(bool *ok = Q_NULLPTR, int base = 10) const; short QString::toShort(bool *ok = Q_NULLPTR, int base = 10) const; long QString::toLong(bool *ok = Q_NULLPTR, int base = 10) const float QString::toFloat(bool *ok = Q_NULLPTR) const; double QString::toDouble(bool *ok = Q_NULLPTR) const; // 将标准C++中的 std::string 类型 转换为 QString 类型 [static] QString QString::fromStdString(const std::string &str); // 将 QString 转换为 标准C++中的 std::string 类型 std::string QString::toStdString() const; // QString -> QByteArray // 转换为本地编码, 跟随操作系统 QByteArray QString::toLocal8Bit() const; // 转换为 Latin-1 编码的字符串 不支持中文 QByteArray QString::toLatin1() const; // 转换为 utf8 编码格式的字符串 (常用) QByteArray QString::toUtf8() const; // 所有字符转换为大写 QString QString::toUpper() const; // 所有字符转换为小写 QString QString::toLower() const;
(7)字符串格式
// 其他重载的同名函数可参考Qt帮助文档, 此处略 QString QString::arg(const QString &a, int fieldWidth = 0, QChar fillChar = QLatin1Char( ' ' )) const; QString QString::arg(int a, int fieldWidth = 0, int base = 10, QChar fillChar = QLatin1Char( ' ' )) const; // 示例程序 int i; // 假设该变量表示当前文件的编号 int total; // 假设该变量表示文件的总个数 QString fileName; // 假设该变量表示当前文件的名字 // 使用以上三个变量拼接一个动态字符串 QString status = QString("Processing file %1 of %2: %3") .arg(i).arg(total).arg(fileName);
九、QVariant
QVariant这个类很神奇,或者说方便。很多时候,需要几种不同的数据类型需要传递,如果用结构体,又不大方便,容器保存的也只是一种数据类型,而QVariant则可以统统搞定。
QVariant 这个类型充当着最常见的数据类型的联合。QVariant 可以保存很多Qt的数据类型,包括QBrush、QColor、QCursor、QDateTime、QFont、QKeySequence、 QPalette、QPen、QPixmap、QPoint、QRect、QRegion、QSize和QString,并且还有C++基本类型,如 int、float等。
1、标准类型
- 将标准类型转换为QVariant类型
// 这类转换需要使用QVariant类的构造函数, 由于比较多, 大家可自行查阅Qt帮助文档, 在这里简单写几个 QVariant::QVariant(int val); QVariant::QVariant(bool val); QVariant::QVariant(double val); QVariant::QVariant(const char *val); QVariant::QVariant(const QByteArray &val); QVariant::QVariant(const QString &val); ...... // 使用设置函数也可以将支持的类型的数据设置到QVariant对象中 // 这里的 T 类型, 就是QVariant支持的类型 void QVariant::setValue(const T &value); // 该函数行为和 setValue() 函数完全相同 [static] QVariant QVariant::fromValue(const T &value); // 例子: #if 1 QVariant v; v.setValue(5); #else QVariant v = QVariant::fromValue(5); #endif int i = v.toInt(); // i is now 5 QString s = v.toString(); // s is now "5"
判断 QVariant中封装的实际数据类型
// 该函数的返回值是一个枚举类型, 可通过这个枚举判断出实际是什么类型的数据 Type QVariant::type() const;
- 将QVariant对象转换为实际的数据类型
// 如果要实现该操作, 可以使用QVariant类提供的 toxxx() 方法, 全部转换可以参考Qt帮助文档 // 在此举列举几个常用函数: bool QVariant::toBool() const; QByteArray QVariant::toByteArray() const; double QVariant::toDouble(bool *ok = Q_NULLPTR) const; float QVariant::toFloat(bool *ok = Q_NULLPTR) const; int QVariant::toInt(bool *ok = Q_NULLPTR) const; QString QVariant::toString() const; ......
十、位置和尺寸
在QT中我们常见的 点, 线, 尺寸, 矩形 都被进行了封装, 下边依次为大家介绍相关的类。
1、QPoint
QPoint类封装了我们常用用到的坐标点 (x, y), 常用的 API如下:
// 构造函数 // 构造一个坐标原点, 即(0, 0) QPoint::QPoint(); // 参数为 x轴坐标, y轴坐标 QPoint::QPoint(int xpos, int ypos); // 设置x轴坐标 void QPoint::setX(int x); // 设置y轴坐标 void QPoint::setY(int y); // 得到x轴坐标 int QPoint::x() const; // 得到x轴坐标的引用 int &QPoint::rx(); // 得到y轴坐标 int QPoint::y() const; // 得到y轴坐标的引用 int &QPoint::ry(); // 直接通过坐标对象进行算术运算: 加减乘除 QPoint &QPoint::operator*=(float factor); QPoint &QPoint::operator*=(double factor); QPoint &QPoint::operator*=(int factor); QPoint &QPoint::operator+=(const QPoint &point); QPoint &QPoint::operator-=(const QPoint &point); QPoint &QPoint::operator/=(qreal divisor); // 其他API请自行查询Qt帮助文档
2、QLine
QLine是一个直线类, 封装了两个坐标点 (两点确定一条直线)
常用API如下:
// 构造函数 // 构造一个空对象 QLine::QLine(); // 构造一条直线, 通过两个坐标点 QLine::QLine(const QPoint &p1, const QPoint &p2); // 从点 (x1, y1) 到 (x2, y2) QLine::QLine(int x1, int y1, int x2, int y2); // 给直线对象设置坐标点 void QLine::setPoints(const QPoint &p1, const QPoint &p2); // 起始点(x1, y1), 终点(x2, y2) void QLine::setLine(int x1, int y1, int x2, int y2); // 设置直线的起点坐标 void QLine::setP1(const QPoint &p1); // 设置直线的终点坐标 void QLine::setP2(const QPoint &p2); // 返回直线的起始点坐标 QPoint QLine::p1() const; // 返回直线的终点坐标 QPoint QLine::p2() const; // 返回值直线的中心点坐标, (p1() + p2()) / 2 QPoint QLine::center() const; // 返回值直线起点的 x 坐标 int QLine::x1() const; // 返回值直线终点的 x 坐标 int QLine::x2() const; // 返回值直线起点的 y 坐标 int QLine::y1() const; // 返回值直线终点的 y 坐标 int QLine::y2() const; // 用给定的坐标点平移这条直线 void QLine::translate(const QPoint &offset); void QLine::translate(int dx, int dy); // 用给定的坐标点平移这条直线, 返回平移之后的坐标点 QLine QLine::translated(const QPoint &offset) const; QLine QLine::translated(int dx, int dy) const; // 直线对象进行比较 bool QLine::operator!=(const QLine &line) const; bool QLine::operator==(const QLine &line) const; // 其他API请自行查询Qt帮助文档
3、QSize
在QT中QSize类用来形容长度和宽度, 常用的API如下:
// 构造函数 // 构造空对象, 对象中的宽和高都是无效的 QSize::QSize(); // 使用宽和高构造一个有效对象 QSize::QSize(int width, int height); // 设置宽度 void QSize::setWidth(int width) // 设置高度 void QSize::setHeight(int height); // 得到宽度 int QSize::width() const; // 得到宽度的引用 int &QSize::rwidth(); // 得到高度 int QSize::height() const; // 得到高度的引用 int &QSize::rheight(); // 交换高度和宽度的值 void QSize::transpose(); // 交换高度和宽度的值, 返回交换之后的尺寸信息 QSize QSize::transposed() const; // 进行算法运算: 加减乘除 QSize &QSize::operator*=(qreal factor); QSize &QSize::operator+=(const QSize &size); QSize &QSize::operator-=(const QSize &size); QSize &QSize::operator/=(qreal divisor); // 其他API请自行查询Qt帮助文档
4、QRect
在Qt中使用 QRect类来描述一个矩形, 常用的API如下:
// 构造函数 // 构造一个空对象 QRect::QRect(); // 基于左上角坐标, 和右下角坐标构造一个矩形对象 QRect::QRect(const QPoint &topLeft, const QPoint &bottomRight); // 基于左上角坐标, 和 宽度, 高度构造一个矩形对象 QRect::QRect(const QPoint &topLeft, const QSize &size); // 通过 左上角坐标(x, y), 和 矩形尺寸(width, height) 构造一个矩形对象 QRect::QRect(int x, int y, int width, int height); // 设置矩形的尺寸信息, 左上角坐标不变 void QRect::setSize(const QSize &size); // 设置矩形左上角坐标为(x,y), 大小为(width, height) void QRect::setRect(int x, int y, int width, int height); // 设置矩形宽度 void QRect::setWidth(int width); // 设置矩形高度 void QRect::setHeight(int height); // 返回值矩形左上角坐标 QPoint QRect::topLeft() const; // 返回矩形右上角坐标 // 该坐标点值为: QPoint(left() + width() -1, top()) QPoint QRect::topRight() const; // 返回矩形左下角坐标 // 该坐标点值为: QPoint(left(), top() + height() - 1) QPoint QRect::bottomLeft() const; // 返回矩形右下角坐标 // 该坐标点值为: QPoint(left() + width() -1, top() + height() - 1) QPoint QRect::bottomRight() const; // 返回矩形中心点坐标 QPoint QRect::center() const; // 返回矩形上边缘y轴坐标 int QRect::top() const; int QRect::y() const; // 返回值矩形下边缘y轴坐标 int QRect::bottom() const; // 返回矩形左边缘 x轴坐标 int QRect::x() const; int QRect::left() const; // 返回矩形右边缘x轴坐标 int QRect::right() const; // 返回矩形的高度 int QRect::width() const; // 返回矩形的宽度 int QRect::height() const; // 返回矩形的尺寸信息 QSize QRect::size() const;
十一、日期和时间
1、QDate
QDate类可以封装日期信息也可以通过这个类得到日期相关的信息, 包括:年, 月, 日。
// 构造函数 QDate::QDate(); QDate::QDate(int y, int m, int d); // 公共成员函数 // 重新设置日期对象中的日期 bool QDate::setDate(int year, int month, int day); // 给日期对象添加 ndays 天 QDate QDate::addDays(qint64 ndays) const; // 给日期对象添加 nmonths 月 QDate QDate::addMonths(int nmonths) const; // 给日期对象添加 nyears 月 QDate QDate::addYears(int nyears) const; // 得到日期对象中的年/月/日 int QDate::year() const; int QDate::month() const; int QDate::day() const; void QDate::getDate(int *year, int *month, int *day) const; // 日期对象格式化 /* d - The day as a number without a leading zero (1 to 31) dd - The day as a number with a leading zero (01 to 31) ddd - The abbreviated localized day name (e.g. 'Mon' to 'Sun'). Uses the system locale to localize the name, i.e. QLocale::system(). dddd - The long localized day name (e.g. 'Monday' to 'Sunday'). Uses the system locale to localize the name, i.e. QLocale::system(). M - The month as a number without a leading zero (1 to 12) MM - The month as a number with a leading zero (01 to 12) MMM - The abbreviated localized month name (e.g. 'Jan' to 'Dec'). Uses the system locale to localize the name, i.e. QLocale::system(). MMMM - The long localized month name (e.g. 'January' to 'December'). Uses the system locale to localize the name, i.e. QLocale::system(). yy - The year as a two digit number (00 to 99) yyyy - The year as a four digit number. If the year is negative, a minus sign is prepended, making five characters. */ QString QDate::toString(const QString &format) const; // 操作符重载 ==> 日期比较 bool QDate::operator!=(const QDate &d) const; bool QDate::operator<(const QDate &d) const; bool QDate::operator<=(const QDate &d) const; bool QDate::operator==(const QDate &d) const; bool QDate::operator>(const QDate &d) const; bool QDate::operator>=(const QDate &d) const; // 静态函数 -> 得到本地的当前日期 [static] QDate QDate::currentDate();
2、QTime
QTime类可以封装时间信息也可以通过这个类得到时间相关的信息, 包括:时, 分, 秒, 毫秒。
// 构造函数 QTime::QTime(); /* h ==> 取值范围: 0 ~ 23 m and s ==> 取值范围: 0 ~ 59 ms ==> 取值范围: 0 ~ 999 */ QTime::QTime(int h, int m, int s = 0, int ms = 0); // 公共成员函数 // Returns true if the set time is valid; otherwise returns false. bool QTime::setHMS(int h, int m, int s, int ms = 0); QTime QTime::addSecs(int s) const; QTime QTime::addMSecs(int ms) const; // 示例代码 QTime n(14, 0, 0); // n == 14:00:00 QTime t; t = n.addSecs(70); // t == 14:01:10 t = n.addSecs(-70); // t == 13:58:50 t = n.addSecs(10 * 60 * 60 + 5); // t == 00:00:05 t = n.addSecs(-15 * 60 * 60); // t == 23:00:00 // 从时间对象中取出 时/分/秒/毫秒 // Returns the hour part (0 to 23) of the time. Returns -1 if the time is invalid. int QTime::hour() const; // Returns the minute part (0 to 59) of the time. Returns -1 if the time is invalid. int QTime::minute() const; // Returns the second part (0 to 59) of the time. Returns -1 if the time is invalid. int QTime::second() const; // Returns the millisecond part (0 to 999) of the time. Returns -1 if the time is invalid. int QTime::msec() const; // 时间格式化 /* -- 时 -- h ==> The hour without a leading zero (0 to 23 or 1 to 12 if AM/PM display) hh ==> The hour with a leading zero (00 to 23 or 01 to 12 if AM/PM display) H ==> The hour without a leading zero (0 to 23, even with AM/PM display) HH ==> The hour with a leading zero (00 to 23, even with AM/PM display) -- 分 -- m ==> The minute without a leading zero (0 to 59) mm ==> The minute with a leading zero (00 to 59) -- 秒 -- s ==> The whole second, without any leading zero (0 to 59) ss ==> The whole second, with a leading zero where applicable (00 to 59) -- 毫秒 -- zzz ==> The fractional part of the second, to millisecond precision, including trailing zeroes where applicable (000 to 999). -- 上午或者下午 AP or A ==> 使用AM/PM(大写) 描述上下午, 中文系统显示汉字 ap or a ==> 使用am/pm(小写) 描述上下午, 中文系统显示汉字 */ QString QTime::toString(const QString &format) const; // 阶段性计时 // 过时的API函数 // 开始计时 void QTime::start(); // 计时结束 int QTime::elapsed() const; // 重新计时 int QTime::restart(); // 推荐使用的API函数 // QElapsedTimer 类 void QElapsedTimer::start(); qint64 QElapsedTimer::restart(); qint64 QElapsedTimer::elapsed() const; // 操作符重载 ==> 时间比较 bool QTime::operator!=(const QTime &t) const; bool QTime::operator<(const QTime &t) const; bool QTime::operator<=(const QTime &t) const; bool QTime::operator==(const QTime &t) const; bool QTime::operator>(const QTime &t) const; bool QTime::operator>=(const QTime &t) const; // 静态函数 -> 得到当前时间 [static] QTime QTime::currentTime();
3、QDateTime
QDateTime类可以封装日期和时间信息也可以通过这个类得到日期和时间相关的信息, 包括:年, 月, 日, 时, 分, 秒, 毫秒。其实这个类就是QDate 和 QTime 这两个类的结合体。
// 构造函数 QDateTime::QDateTime(); QDateTime::QDateTime(const QDate &date, const QTime &time, Qt::TimeSpec spec = Qt::LocalTime); // 公共成员函数 // 设置日期 void QDateTime::setDate(const QDate &date); // 设置时间 void QDateTime::setTime(const QTime &time); // 给当前日期对象追加 年/月/日/秒/毫秒, 参数可以是负数 QDateTime QDateTime::addYears(int nyears) const; QDateTime QDateTime::addMonths(int nmonths) const; QDateTime QDateTime::addDays(qint64 ndays) const; QDateTime QDateTime::addSecs(qint64 s) const; QDateTime QDateTime::addMSecs(qint64 msecs) const; // 得到对象中的日期 QDate QDateTime::date() const; // 得到对象中的时间 QTime QDateTime::time() const; // 日期和时间格式, 格式字符参考QDate 和 QTime 类的 toString() 函数 QString QDateTime::toString(const QString &format) const; // 操作符重载 ==> 日期时间对象的比较 bool QDateTime::operator!=(const QDateTime &other) const; bool QDateTime::operator<(const QDateTime &other) const; bool QDateTime::operator<=(const QDateTime &other) const; bool QDateTime::operator==(const QDateTime &other) const; bool QDateTime::operator>(const QDateTime &other) const; bool QDateTime::operator>=(const QDateTime &other) const; // 静态函数 // 得到当前时区的日期和时间(本地设置的时区对应的日期和时间) [static] QDateTime QDateTime::currentDateTime();
十二、UI界面介绍
1、窗口组件介绍
2、属性介绍
十三、QT的第一个界面设计程序
1、widget.h和widget.cpp
这两个文件 就是 为了设计窗口的 ,封装了窗口类
所以我们 设置窗口的属性、功能 在这两个文件里面去添加!!!
#include "widget.h" #include "ui_widget.h" Widget::Widget(QWidget *parent) : QWidget(parent) , ui(new Ui::Widget) { // 窗口的布局 或者 设置 在这里 手写代码!!! ui->setupUi(this); //这个函数 是窗口的构造函数 this 表示指向自己 ---> 主窗口的地址 } Widget::~Widget() { delete ui; }
2、窗口大小设置
// 设置窗口大小 resize(800,800); -------> 这种窗口支持缩放!!!
// 设置固定的窗口大小 this->setFixedSize(400,300);
3、添加按钮
#include "widget.h" #include <QPushButton> //按钮的头文件 #include "ui_widget.h" Widget::Widget(QWidget *parent) : QWidget(parent) , ui(new Ui::Widget) { // 设置窗口大小 //resize(400,300); // 设置固定的窗口大小 this->setFixedSize(400,300); //创建Button对象 QPushButton *btn = new QPushButton; //设置btn文本 btn->setText("第一个按钮"); // 设置btn大小 //btn->resize(100,100); btn->setFixedSize(100,100); // btn 按钮 认父亲 设置当前窗口 setParent btn->setParent(this); //创建Button对象 QPushButton *btn1 = new QPushButton; //设置btn文本 btn1->setText("第二个按钮"); // 设置btn大小 //btn->resize(100,100); btn1->setFixedSize(100,100); // btn 按钮 认父亲 设置当前窗口 setParent btn1->setParent(this); //移动显示位置 要不然会重叠!! btn1->move(100,0); //ui->setupUi(this); //这个函数 是窗口的构造函数 this 表示指向自己 ---> 主窗口的地址 }
//设置btn文本 btn->setText("第一个按钮"); //字体设置 QFont font1; // 创建字体对象 font1.setFamily("Arial"); // 选择 字体族 font1.setPointSize(12); //大小 font1.setBold(true); // 粗细!!! btn->setFont(font1);
3、补充 — 设置窗口标题
this->setWindowTitle("第一个UI程序");
4、完整代码
#include "widget.h" #include <QPushButton> #include "ui_widget.h" Widget::Widget(QWidget *parent) : QWidget(parent) , ui(new Ui::Widget) { ui->setupUi(this); //这个函数 是窗口的构造函数 this 表示指向自己 ---> 主窗口的地址 // 设置窗口大小 //resize(400,300); // 设置固定的窗口大小 this->setFixedSize(400,300); //创建Button对象 QPushButton *btn = new QPushButton; //设置btn文本 btn->setText("第一个按钮"); //字体设置 QFont font1; font1.setFamily("Arial"); font1.setPointSize(12); font1.setBold(true); btn->setFont(font1); // 设置btn大小 //btn->resize(100,100); btn->setFixedSize(100,100); // btn 按钮 认父亲 设置当前窗口 setParent btn->setParent(this); //创建Button对象 QPushButton *btn1 = new QPushButton; //设置btn文本 btn1->setText("第二个按钮"); // 设置btn大小 //btn->resize(100,100); btn1->setFixedSize(100,100); // btn 按钮 认父亲 设置当前窗口 setParent btn1->setParent(this); //移动显示位置 要不然会重叠!! btn1->move(100,0); // 设置UI窗口标题 this->setWindowTitle("第一个UI程序"); } Widget::~Widget() { delete ui; }
十四、信号和槽
1、信号和槽的概述
信号和槽是 Qt 框架引以为豪的机制之一。
所谓信号槽,实际就是观察者模式(发布-订阅模式)。
当某个事件发生之后,比如,按钮检测到自己被点击了一下,它就会发出一个信号(signal)。
这种发出是没有目的的,类似广播。如果有对象对这个信号感兴趣,它就会使用连接(connect)函数,意思是,将想要处理的信号和自己的一个函数(称为槽(slot))绑定来处理这个信号。
也就是说,当信号发出时,被连接的槽函数会自动被回调。
这就类似观察者模式:当发生了感兴趣的事件,某一个操作就会被自动触发。
eg:
2、信号 signal
信号是由于用户对窗口或控件进行了某些操作,导致窗口或控件产生了某个特定事件,这时候Qt对应的窗口类会发出某个信号,以此对用户的挑选做出反应。
因此根据上述的描述我们得到一个结论 – 信号的本质就是事件,比如:
-
- 按钮单击、双击
- 窗口刷新
- 鼠标移动、鼠标按下、鼠标释放
- 键盘输入
那么在Qt中信号是通过什么形式呈现给使用者的呢?
-
- 我们对哪个窗口进行操作, 哪个窗口就可以捕捉到这些被触发的事件。
- 对于使用者来说触发了一个事件我们就可以得到Qt框架给我们发出的某个特定信号。
- 信号的呈现形式就是函数, 也就是说某个事件产生了, Qt框架就会调用某个对应的信号函数, 通知使用者。
在QT中信号的发出者是某个实例化的类对象,对象内部可以进行相关事件的检测。
3、槽函数
在Qt中槽函数是一类特殊的功能的函数,在编码过程中也可以作为类的普通成员函数来使用。之所以称之为槽函数是因为它们还有一个职责就是对Qt框架中产生的信号进行处理。
eg:
女朋友: 肚子饿了!! ———> 带她出去吃饭!!
女朋友 对象 —-> 发出一个信号 —-> 肚子饿了!!!
我 收到信号 —–> 处理信号(槽函数) —–> 带她出去吃饭!!
我 —-> 信号接收者!! 也是一个对象!! ——> QT中 槽函数 的所有者 也是某个类的实例化对象!!!
4、信号和槽的关系
在Qt中信号和槽函数都是独立的个体,本身没有任何联系,但是由于某种特性需求我们可以将二者连接到一起,好比牛郎和织女想要相会必须要有喜鹊为他们搭桥一样。
在Qt中我们需要使用QOjbect类中的connect函数进二者的关联。
连接信号和槽的connect()函数原型如下, 其中PointerToMemberFunction是一个指向函数地址的指针
QMetaObject::Connection QObject::connect( const QObject *sender, PointerToMemberFunction signal, const QObject *receiver, PointerToMemberFunction method, Qt::ConnectionType type = Qt::AutoConnection); 参数: - sender: 发出信号的对象 - signal: 属于sender对象, 信号是一个函数, 这个参数的类型是函数 指针, 信号函数地址 - receiver: 信号接收者 - method: 属于receiver对象, 当检测到sender发出了signal信号, receiver对象调用method方法,信号发出之后的处理动作 // 参数 signal 和 method 都是函数地址, 因此简化之后的 connect() 如下: connect(const QObject *sender, &QObject::signal, const QObject *receiver, &QObject::method);
使用connect()进行信号槽连接的注意事项:
-
- connect函数相对于做了信号处理动作的注册
- 调用conenct函数的sender对象的信号并没有产生, 因此receiver对象的method也不会被调用
- method槽函数本质是一个回调函数, 调用的时机是信号产生之后, 调用是Qt框架来执行的
- connect中的sender和recever两个指针必须被实例化了, 否则conenct不会成功
5、标准的信号和槽的使用
(1) 通过QT creator 帮助查找
首先我们可以在Contents中寻找关键字 signals,信号的意思,但是我们发现并没有找到,这时候我们应该看当前类从父类继承下来了哪些信号
因此我们去他的父类QAbstractButton中就可以找到该关键字,点击signals索引到系统自带的信号有如下几个
(2)QT助手查询
(3) 点击退出按钮 实现 窗口关闭
第一种实现
第二种实现
#include "mainwindow.h" #include "ui_mainwindow.h" MainWindow::MainWindow(QWidget *parent) : QMainWindow(parent) , ui(new Ui::MainWindow) { ui->setupUi(this); //QT4 信号和槽 // connect(发送者,SIGNAL(发送者发出的信号),接受者,SLOT(执行的对应操作)); //connect(ui->btn_exit,SIGNAL(clicked(bool)),this,SLOT(close())); //QT5 connect(ui->btn_exit,&QPushButton::clicked,this,&MainWindow::close); } MainWindow::~MainWindow() { delete ui; }
(4)总结
connect() -----> 这个函数就是实现连接的功能 -----> 将信号 和 槽函数进行连接绑定 connect(sender,signal,receiver,slot) 参数说明: sender -----> 发出信号的对象 signal -----> 发送对象发出的信号 receiver -----> 接收信号的对象 slot -----> 接收对象 在 收到信号后 需要调用的函数(槽函数) qt4 的连接方法 //qt4 ----> SIGNAL() SLOT() connect(btn,SIGNAL(clicked(bool)),this,SLOT(close())); //qt5 &QPushButton::clicked &widget::选择信号和槽 connect(btn,&QPushButton::clicked,this,&Widget::close); 注意,注意,注意: 信号也可以连接信号
6、自定义信号和槽
如果我们想要使用自定义的信号和槽。首先要编写新的类—->这个类一般继承QT某些标准类
我们自己编写的类想要在Qt中使用使用信号槽机制,那么必须要满足的如下条件:
-这个类必须从QObject类或者是其子类进行派生
-在定义类的头文件中加入Q_OBJECT宏
(1) 自定义信号
* 1.信号是类的成员函数
* 2.返回值是void类型
* 3.信号的名字可以根据实际情况进行指定
* 4.参数可以随意指定,信号也支持重载
* 5.信号需要使用signals 关键字进行声明,使用方法类似于public等关键字
* 6.信号函数只需要声明,不需要定义(没有函数体实现)
* 7.在程序中发送自定义信号:发送信号的本质就是调用信号函数
* – 习惯性在信号函数前加关键字:emit
* – emit只是显示的声明一下信号要被发送,没有特殊含义-底层emit == #define emit
* 举例:信号重载
* Qt中的类想要使用信号槽机制必须要从QObject类派生(直接或间接派生都可以)
* 1.信号是类的成员函数 * 2.返回值是void类型 * 3.信号的名字可以根据实际情况进行指定 * 4.参数可以随意指定,信号也支持重载 * 5.信号需要使用signals 关键字进行声明,使用方法类似于public等关键字 * 6.信号函数只需要声明,不需要定义(没有函数体实现) * 7.在程序中发送自定义信号:发送信号的本质就是调用信号函数 * - 习惯性在信号函数前加关键字:emit * - emit只是显示的声明一下信号要被发送,没有特殊含义-底层emit == #define emit * 举例:信号重载 * Qt中的类想要使用信号槽机制必须要从QObject类派生(直接或间接派生都可以)
(2)槽函数
1.返回值是void类型
2.槽也是函数,因此也支持重载
-槽函数需要指定多少个参数,需要看连接的信号的参数个数
-槽函数的参数是用来接收信号发送的数据的,信号发送的数据就是信号的参数
-举例:
-信号函数:void testsig( int a,double b);
-槽函数: void testslot ( int a,double b);
总结:
-槽函数的参数应该和对应的信号的参数个数,类型一一对应
-信号的参数可以大于等于槽函数的参数个数 == 信号传递的数据被忽略了
-信号函数: void testsig(int a, double b);
-槽函数: void testslot(int a);
3. Qt中槽函数的类型:
-类的成员函数
-全局函数
-静态函数
– lambda表达式(匿名函数)
4.槽函数可以使用关键字进行声明: slots (Qt5中slots可以省略不写)
– public slots:
– private slots:
– protected slots:
(3)实现一下自定义信号和槽
eg: 女朋友 —–> 饿了
117 ——> 吃火锅
两个对象 —–> 添加两个文件
我的类一样的方法添加!!
1、主窗口 添加 这个两个类的头文件
2、明确指针指向的对象
3、设计信号和槽
(4)带参数的信号和槽 —— 重载
(5)总结
- 总结
-
- Qt4的信号槽连接方式因为使用了宏函数, 宏函数对用户传递的信号槽不会做错误检测, 容易出bug
- Qt5的信号槽连接方式, 传递的是信号槽函数的地址, 编译器会做错误检测, 减少了bug的产生
- 当信号槽函数被重载之后, Qt4的信号槽连接方式不受影响
- 当信号槽函数被重载之后, Qt5中需要给被重载的信号或者槽定义函数指针
应用举例 场景描述: - 我肚子饿了, 我要吃东西。 分析: - 信号的发出者是我自己, 信号的接收者也是我自己 我们首先定义出一个Qt的类。 class Me : public QObject { Q_OBJECT // Qt4中的槽函数必须这样声明, qt5中的关键字 slots 可以被省略 public slots: void eat(); void eat(QString somthing); signals: void hungury(); void hungury(QString somthing); }; // 基于上边的类写出解决方案 // 处理如下逻辑: 我饿了, 我要吃东西 // 分析: 信号的发出者是我自己, 信号的接收者也是我自己 Me m; // Qt4处理方式 connect(&m, SIGNAL(eat()), &m, SLOT(hungury())); connect(&m, SIGNAL(eat(QString)), &m, SLOT(hungury(QString))); // Qt5处理方式 connect(&m, &Me::eat, &m, &Me::hungury); // error void (Me::*func1)(QString) = &Me::eat; // func1指向带参的信号 void (Me::*func2)() = &Me::hungury; // func2指向不带参的槽函数 // 定义函数指针指向重载的某一个具体的信号地址 void (Me::*mysignal)(QString) = &Me::eat; // 定义函数指针指向重载的某一个具体的槽函数地址 void (Me::*myslot)(QString) = &Me::hungury; // 使用定义的函数指针完成信号槽的连接 connect(&m, mysignal, &m, myslot);
7、Lambda 表达式
(1) 作用
Lambda表达式是 C++ 11 最重要也是最常用的特性之一,是现代编程语言的一个特点,简洁,提高了代码的效率并且可以使程序更加灵活,Qt是完全支持c++语法的, 因此在Qt中也可以使用Lambda表达式。
[capture](params) opt -> ret {body;}; - capture: 捕获列表 - params: 参数列表 - opt: 函数选项 - ret: 返回值类型 - body: 函数体
- 捕获列表: 捕获一定范围内的变量
-
- [] – 不捕捉任何变量
- [&] – 捕获外部作用域中所有变量, 并作为引用在函数体内使用 (按引用捕获)
- [=] – 捕获外部作用域中所有变量, 并作为副本在函数体内使用 (按值捕获)
-
-
- 拷贝的副本在匿名函数体内部是只读的
-
-
- [=, &foo] – 按值捕获外部作用域中所有变量, 并按照引用捕获外部变量 foo
- [bar] – 按值捕获 bar 变量, 同时不捕获其他变量
- [&bar] – 按引用捕获 bar 变量, 同时不捕获其他变量
- [this] – 捕获当前类中的this指针
-
-
- 让lambda表达式拥有和当前类成员函数同样的访问权限
- 如果已经使用了 & 或者 =, 默认添加此选项
-
- 参数列表: 和普通函数的参数列表一样
- opt 选项 –> 可以省略
-
- mutable: 可以修改按值传递进来的拷贝(注意是能修改拷贝,而不是值本身)
- exception: 指定函数抛出的异常,如抛出整数类型的异常,可以使用throw();
- 返回值类型:
-
- 标识函数返回值的类型,当返回值为void,或者函数体中只有一处return的地方(此时编译器可以自动推断出返回值类型)时,这部分可以省略
- 函数体:
-
- 函数的实现,这部分不能省略,但函数体可以为空。
(2)定义和调用
// 匿名函数的定义, 程序执行这个匿名函数是不会被调用的 [](){ qDebug() << "hello, 我是一个lambda表达式..."; }; // 匿名函数的定义+调用: int ret = [](int a) -> int { return a+1; }(100); // 100是传递给匿名函数的参数
(3) 信号和槽中的使用
十五、QMainWindow
1、菜单栏
#include "mainwindow.h" #include "ui_mainwindow.h" MainWindow::MainWindow(QWidget *parent) : QMainWindow(parent) , ui(new Ui::MainWindow) { //ui->setupUi(this); // 设置窗口标题 this->setWindowTitle("我的主窗口"); this->resize(400,300); //创建菜单栏 //QMenuBar *menubar = new QMenuBar; //menubar->setParent(this); QMenuBar *menubar = new QMenuBar(this); // 把 菜单栏加入当前窗口 this->setMenuBar(menubar); //创建菜单 QMenu *file_menu = new QMenu("file",this); QMenu *edit_menu = new QMenu("edit",this); // 把菜单加入菜单栏 menubar->addMenu(file_menu); menubar->addMenu(edit_menu); //创建菜单项 QAction *open_file = new QAction("open",this); QAction *save_file = new QAction("save",this); //加入菜单 file_menu->addAction(open_file); file_menu->addAction(save_file); // 给菜单创建快捷键 open_file->setShortcut(QKeySequence(Qt::CTRL + Qt::Key_N)); save_file->setShortcut(QKeySequence(Qt::CTRL + Qt::Key_S)); connect(open_file,&QAction::triggered,[](){ qDebug() << "文件已打开" << endl; }); connect(save_file,&QAction::triggered,[](){ qDebug() << "文件已保存" << endl; }); } MainWindow::~MainWindow() { delete ui; }
2、工具栏
//工具栏 QToolBar *tool=new QToolBar("tool",this); this->addToolBar(tool); tool->addAction(New); tool->addAction(open); tool->setFloatable(false);//false:不允许,true:允许 tool->setAllowedAreas(Qt::LeftToolBarArea|Qt::RightToolBarArea);
3、状态栏 在最下面
状态栏 一般是显示信息的
//状态栏 QStatusBar *stBar=new QStatusBar(this); this->setStatusBar(stBar); QLabel *lab1=new QLabel("left",this); QLabel *lab2=new QLabel("right",this); //将lab1显示在状态栏的左侧 stBar->addWidget(lab1); //将lab2显示在状态栏的右侧 stBar->addPermanentWidget(lab2);
4、资源文件 —- 所有的QT工程都可以添加
QT的资源机制 —->将程序运行的所需要的资源 以 二进制的形式存储在可执行的文件内部
eg: 如果程序中需要用到的资源(图片、图标,文本资源、动画等),就要把这些资源放在资源文件中,这样就不用担心资源丢失,资源找不到。
——> QT的资源是以二进制编译在可执行文件内部!!
——> 便于移植,这样就可以防止因为资源路径等问题 导致资源不可用!
(1)QT资源文件的创建
(2)资源删除
要删除资源 —-> 必须在资源文件中去删除
进入资源文件的编辑者模式
(3)资源文件使用
背景图片自动缩放
label 标签显示图片
MainWindow::MainWindow(QWidget *parent) : QMainWindow(parent) , ui(new Ui::MainWindow) { ui->setupUi(this); ui->label->resize(800,600); // 标签文本显示 //ui->label->setText("hello world!"); #if 0 // 构建图片的对象 QPixmap *img = new QPixmap(":/image/mangsheng.jpg"); // 将图片设置到标签里面去 ui->label->setPixmap(*img); #else QPixmap img(":/image/mangsheng.jpg"); //Qt::KeepAspectRatio ----> 保持宽高比 // Qt::SmoothTransformation 平滑处理 //ui->label->setPixmap(img.scaled(ui->label->size(),Qt::KeepAspectRatio,Qt::SmoothTransformation)); // 将图片设置为 label 标签的大小!! ui->label->setPixmap(img.scaled(ui->label->size())); #endif }
(4)图片的缩放 窗口缩放—-> label —–> 图片
窗口 和label 同比例缩放
图片和label框的缩放
MainWindow::MainWindow(QWidget *parent) : QMainWindow(parent) , ui(new Ui::MainWindow) { ui->setupUi(this); //定义图片对象 QPixmap img(":/image/mangsheng.jpg"); ui->label->setPixmap(img); // 设置label 里面的内容 根据label大小自动缩放 ui->label->setScaledContents(true); // 图片自适应 }
免责声明:本站所有文章内容,图片,视频等均是来源于用户投稿和互联网及文摘转载整编而成,不代表本站观点,不承担相关法律责任。其著作权各归其原作者或其出版社所有。如发现本站有涉嫌抄袭侵权/违法违规的内容,侵犯到您的权益,请在线联系站长,一经查实,本站将立刻删除。 本文来自网络,若有侵权,请联系删除,如若转载,请注明出处:https://haidsoft.com/127013.html