当前位置: 首页 > news >正文

济南手机网站制作深圳网站建设招聘

济南手机网站制作,深圳网站建设招聘,上海正规建设网站私人订制,wordpress 4.6下载文章目录 1. Qt基本结构1.1 Qt本有项目1.1.1 项目文件#xff08;.pro#xff09;1.1.2 main.cpp1.1.3 mainwindow.ui1.1.4 mainwindow.h1.1.5 mainwindow.cpp 1.2 Qt中的窗口类1.2.1基础窗口类1.2.2 窗口的显示 1.3 内存回收 2. Qt中的基础数据类型2.1 基础类型2.2 log输出2… 文章目录 1. Qt基本结构1.1 Qt本有项目1.1.1 项目文件.pro1.1.2 main.cpp1.1.3 mainwindow.ui1.1.4 mainwindow.h1.1.5 mainwindow.cpp 1.2 Qt中的窗口类1.2.1基础窗口类1.2.2 窗口的显示 1.3 内存回收 2. Qt中的基础数据类型2.1 基础类型2.2 log输出2.2.1 在调试窗口中输入日志2.2.2 在终端窗口中输出日志 2.3 字符串类型2.3.1 QByteArray2.3.2 QString 2.4 QVariant2.4.1 标准类型2.4.2 自定义类型 2.5 位置和尺寸2.5.1 QPoint2.5.2 QLine2.5.3 QSize2.5.4 QRect 2.6 日期和时间2.6.1 QDate2.6.2 QTime2.6.3 QDateTime2.6.4 定时器类QTimer2.6.4.1 public/slot function2.6.4.2 signals2.6.4.3 static public function2.6.4.4 定时器使用举例 3. 信号槽3.1 信号和槽概述3.1.1 信号的本质3.1.2 槽的本质3.1.3 信号和槽的关系 3.2 标准信号槽使用3.2.1 标准信号/槽3.2.2 使用 3.3 自定义信号槽使用3.3.1 自定义信号3.3.2 自定义槽 3.4 信号槽拓展3.4.1 信号槽使用拓展3.4.2 信号槽的连接方式 1. Qt基本结构 1.1 Qt本有项目 1.1.1 项目文件.pro 在创建的Qt项目中自动生成了一个后缀为 .pro 的项目文件该文件中记录着项目的一些属性信息具体信息如下 # 在项目文件中, 注释需要使用 井号(#) # 项目编译的时候需要加载哪些底层模块 QT core gui # 如果当前Qt版本大于4, 会添加一个额外的模块: widgets # Qt 5中对gui模块进行了拆分, 将 widgets 独立出来了 greaterThan(QT_MAJOR_VERSION, 4): QT widgets# 使用c11新特性 CONFIG c11 #如果在项目中调用了废弃的函数, 项目编译的时候会有警告的提示 DEFINES QT_DEPRECATED_WARNINGS# 项目中的源文件 SOURCES \main.cpp \mainwindow.cpp# 项目中的头文件 HEADERS \mainwindow.h# 项目中的窗口界面文件 FORMS \mainwindow.ui1.1.2 main.cpp 在这个源文件中有程序的入口函数 main()介绍下这个文件中自动生成的几行代码 #include mainwindow.h // 生成的窗口类头文件 #include QApplication // 应用程序类头文件int main(int argc, char *argv[]) {// 创建应用程序对象, 在一个Qt项目中实例对象有且仅有一个// 类的作用: 检测触发的事件, 进行事件循环并处理QApplication a(argc, argv);// 创建窗口类对象MainWindow w;// 显示窗口w.show();// 应用程序对象开始事件循环, 保证应用程序不退出return a.exec(); }1.1.3 mainwindow.ui 在Qt中每一个窗口都对应一个可编辑的可视化界面*.ui, 这个界面对应的是一个xml格式的文件, 一般情况下不需要在xml格式下对这个文件进行编辑, 关于这个文件结构了解即可。 !-- 双击这个文件看到的是一个窗口界面, 如果使用文本编辑器打开看到的是一个XML格式的文件-- !-- 看不懂这种格式没关系, 我们不需要在这种模式下操作这个文件。 -- !-- 这里只是给大家介绍这个文件的本质 -- ?xml version1.0 encodingUTF-8? ui version4.0classMainWindow/classwidget classQMainWindow nameMainWindowproperty namegeometryrectx0/xy0/ywidth800/widthheight600/height/rect/propertyproperty namewindowTitlestringMainWindow/string/propertywidget classQWidget namecentralwidget/widget classQMenuBar namemenubar/widget classQStatusBar namestatusbar//widgetresources/connections/ /ui1.1.4 mainwindow.h 这个文件是窗口界面对应的类的头文件。 #ifndef MAINWINDOW_H #define MAINWINDOW_H#include QMainWindow // Qt标准窗口类头文件QT_BEGIN_NAMESPACE // mainwindow.ui 文件中也有一个类叫 MainWindow, 将这个类放到命名空间 Ui 中 namespace Ui { class MainWindow; } QT_END_NAMESPACEclass MainWindow : public QMainWindow {Q_OBJECT // 这个宏是为了能够使用Qt中的信号槽机制public:MainWindow(QWidget *parent nullptr);~MainWindow();private:Ui::MainWindow *ui; // 定义指针指向窗口的 UI 对象 }; #endif // MAINWINDOW_H1.1.5 mainwindow.cpp 这个文件是窗口界面对应的类的源文件。 #include mainwindow.h #include ui_mainwindow.hMainWindow::MainWindow(QWidget *parent): QMainWindow(parent), ui(new Ui::MainWindow) // 基于mainwindow.ui创建一个实例对象 {// 将 mainwindow.ui 的实例对象和 当前类的对象进行关联// 这样同名的连个类对象就产生了关联, 合二为一了ui-setupUi(this); }MainWindow::~MainWindow() {delete ui; }1.2 Qt中的窗口类 在通过Qt向导窗口基于窗口的应用程序的项目过程中倒数第二步选择跟随项目创建的第一个窗口的基类, 下拉菜单有三个选项, 分别为: QMainWindow、QDialog、QWidget如下图 1.2.1基础窗口类 常用的窗口类有3个 在创建Qt窗口的时候, 需要让自己的窗口类继承上述三个窗口类的其中一个 QWidget 所有窗口类的基类Qt中的控件(按钮, 输入框, 单选框…)也属于窗口, 基类都是QWidget可以内嵌到其他窗口中: 没有边框可以不内嵌单独显示: 独立的窗口, 有边框 QDialog 对话框类, 后边的章节会具体介绍这个窗口不能内嵌到其他窗口中 QMainWindow 有工具栏, 状态栏, 菜单栏, 后边的章节会具体介绍这个窗口不能内嵌到其他窗口中 1.2.2 窗口的显示 内嵌窗口 依附于某一个大的窗口, 作为了大窗口的一部分大窗口就是这个内嵌窗口的父窗口父窗口显示的时候, 内嵌的窗口也就被显示出来了 不内嵌窗口 这类窗口有边框, 有标题栏需要调用函数才可以显示 // QWidget是所有窗口类的基类, 调用这个提供的 show() 方法就可以显示将任何窗口显示出来 // 非模态显示 void QWidget::show(); // 显示当前窗口和它的子窗口// 对话框窗口的非模态显示: 还是调用show() 方法 // 对话框窗口的模态显示 [virtual slot] int QDialog::exec();1.3 内存回收 在Qt中创建对象的时候会提供一个 Parent对象指针可以查看类的构造函数parent是干什么的? . QObject是以对象树的形式组织起来的。当你创建一个QObject对象时会看到QObject的构造函数接收一个QObject指针作为参数这个参数就是parent也就是父对象指针。 这相当于在创建QObject对象时可以提供一个其父对象我们创建的这个QObject对象会自动添加到其父对象的children()列表。当父对象析构的时候这个列表中的所有对象也会被析构。这里的父对象并不是继承意义上的父类 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);2. Qt中的基础数据类型 主要介绍Qt中常用数据类型, 主要内容包括: 基础数据类型, Log日志输出, 字符串类型, QVariant, 位置和尺寸相关类型, 日期和时间相关类型。 2.1 基础类型 因为Qt是一个C 框架, 因此C中所有的语法和数据类型在Qt中都是被支持的, 但是Qt中也定义了一些属于自己的数据类型, 介绍一下这些基础的数类型。 QT基本数据类型定义在#include QtGlobal 中QT基本数据类型有 类型名称注释备注qint8signed char有符号8位数据qint16signed short16位数据类型qint32signed short32位有符号数据类型qint64long long int 或 (__int64)64位有符号数据类型Windows中定义为__int64qintptrqint32 或 qint64指针类型 根据系统类型不同而不同32位系统为qint32、64位系统为qint64qlonglonglong long int 或 (__int64)Windows中定义为__int64qptrdiffqint32 或 qint64根据系统类型不同而不同32位系统为qint32、64位系统为qint64qrealdouble 或 float除非配置了-qreal float选项否则默认为doublequint8unsigned char无符号8位数据类型quint16unsigned short无符号16位数据类型quint32unsigned int无符号32位数据类型quint64unsigned long long int 或 (unsigned __int64)无符号64比特数据类型Windows中定义为unsigned __int64quintptrquint32 或 quint64根据系统类型不同而不同32位系统为quint32、64位系统为quint64qulonglongunsigned long long int 或 (unsigned __int64)Windows中定义为__int64ucharunsigned char无符号字符类型uintunsigned int无符号整型ulongunsigned long无符号长整型ushortunsigned short无符号短整型 虽然在Qt中有属于自己的整形或者浮点型, 但是在变成过程中这些一般不用, 常用的类型关键字还是 C/C中的 int, float, double 等。 2.2 log输出 2.2.1 在调试窗口中输入日志 在Qt中进行log输出, 一般不使用c中的printf, 也不是使用C中的cout Qt框架提供了专门用于日志输出的类, 头文件名为QDebug // 包含了QDebug头文件, 直接通过全局函数 qDebug() 就可以进行日志输出了 qDebug() Date: QDate::currentDate(); qDebug() Types: QString(String) QChar(x)QRect(0, 10, 50, 40); qDebug() Custom coordinate type: coordinate;// 和全局函数 qDebug() 类似的日志函数还有: qWarning(), qInfo(), qCritical() int number 666; float i 11.11; qWarning() Number: number Other value: i; qInfo() Number: number Other value: i; qCritical() Number: number Other value: i;qDebug() 我是要成为海贼王的男人!!!; qDebug() 我是隔壁的二柱子...; qDebug() 我是鸣人, 我擅长嘴遁!!!;2.2.2 在终端窗口中输出日志 使用上面的方法只能在项目调试过程中进行日志输出, 如果不是通过IDE进行程序调试, 而是直接执行可执行程序在这种情况下是没有日志输出窗口的,因此也就看不到任何的日志输出。 默认情况下日志信息是不会打印到终端窗口的, 如果想要实现这样的效果, 必须在项目文件中添加相关的属性信息 打开项目文件*.pro找到配置项 config, 添加 console 控制台属性: CONFIG c11 console2.3 字符串类型 在Qt中不仅支持C, C中的字符串类型, 而且还在框架中定义了专属的字符串类型, 必须要掌握在Qt中关于这些类型的使用和相互之间的转换。 语言类型字符串类型Cchar*Cstd::string, char*QtQByteArray, QString 2.3.1 QByteArray 在Qt中QByteArray可以看做是c语言中char*的升级版本。我们在使用这种类型的时候可通过这个类的构造函数申请一块动态内存用于存储我们需要处理的字符串数据。 介绍一下这个类中常用的一些API函数 构造函数 // 构造空对象, 里边没有数据 QByteArray::QByteArray(); // 将data中的size个字符进行构造, 得到一个字节数组对象 // 如果 size-1 函数内部自动计算字符串长度, 计算方式为: strlen(data) QByteArray::QByteArray(const char *data, int size -1); // 构造一个长度为size个字节, 并且每个字节值都为ch的字节数组 QByteArray::QByteArray(int size, char ch);数据操作 // 在尾部追加数据 // 其他重载的同名函数可参考Qt帮助文档, 此处略 QByteArray QByteArray::append(const QByteArray ba); void QByteArray::push_back(const QByteArray other);// 头部添加数据 // 其他重载的同名函数可参考Qt帮助文档, 此处略 QByteArray QByteArray::prepend(const QByteArray ba); void QByteArray::push_front(const QByteArray other);// 插入数据, 将ba插入到数组第 i 个字节的位置(从0开始) // 其他重载的同名函数可参考Qt帮助文档, 此处略 QByteArray QByteArray::insert(int i, const QByteArray ba);// 删除数据 // 从大字符串中删除len个字符, 从第pos个字符的位置开始删除 QByteArray QByteArray::remove(int pos, int len); // 从字符数组的尾部删除 n 个字节 void QByteArray::chop(int n); // 从字节数组的 pos 位置将数组截断 (前边部分留下, 后边部分被删除) void QByteArray::truncate(int pos); // 将对象中的数据清空, 使其为null void QByteArray::clear();// 字符串替换 // 将字节数组中的 子字符串 before 替换为 after // 其他重载的同名函数可参考Qt帮助文档, 此处略 QByteArray QByteArray::replace(const QByteArray before, const QByteArray after);子字符串查找和判断 // 判断字节数组中是否包含子字符串 ba, 包含返回true, 否则返回false bool QByteArray::contains(const QByteArray ba) const; bool QByteArray::contains(const char *ba) const; // 判断字节数组中是否包含子字符 ch, 包含返回true, 否则返回false bool QByteArray::contains(char ch) const;// 判断字节数组是否以字符串 ba 开始, 是返回true, 不是返回false bool QByteArray::startsWith(const QByteArray ba) const; bool QByteArray::startsWith(const char *ba) const; // 判断字节数组是否以字符 ch 开始, 是返回true, 不是返回false bool QByteArray::startsWith(char ch) const;// 判断字节数组是否以字符串 ba 结尾, 是返回true, 不是返回false bool QByteArray::endsWith(const QByteArray ba) const; bool QByteArray::endsWith(const char *ba) const; // 判断字节数组是否以字符 ch 结尾, 是返回true, 不是返回false bool QByteArray::endsWith(char ch) const;遍历 // 使用迭代器 iterator QByteArray::begin(); iterator QByteArray::end();// 使用数组的方式进行遍历 // i的取值范围 0 i size() char QByteArray::at(int i) const; char QByteArray::operator[](int i) const;查看字节数 // 返回字节数组对象中字符的个数 int QByteArray::length() const; int QByteArray::size() const; int QByteArray::count() const;// 返回字节数组对象中 子字符串ba 出现的次数 int QByteArray::count(const QByteArray ba) const; int QByteArray::count(const char *ba) const; // 返回字节数组对象中 字符串ch 出现的次数 int QByteArray::count(char ch) const;类型转换 // 将QByteArray类型的字符串 转换为 char* 类型 char *QByteArray::data(); const char *QByteArray::data() const;// int, short, long, float, double - QByteArray // 其他重载的同名函数可参考Qt帮助文档, 此处略 QByteArray QByteArray::setNum(int n, int base 10); QByteArray QByteArray::setNum(short n, int base 10); QByteArray QByteArray::setNum(qlonglong n, int base 10); QByteArray QByteArray::setNum(float n, char f g, int prec 6); QByteArray QByteArray::setNum(double n, char f g, int prec 6); [static] QByteArray QByteArray::number(int n, int base 10); [static] QByteArray QByteArray::number(qlonglong n, int base 10); [static] QByteArray QByteArray::number(double n, char f g, int prec 6);// QByteArray - int, short, long, float, double int QByteArray::toInt(bool *ok Q_NULLPTR, int base 10) const; short QByteArray::toShort(bool *ok Q_NULLPTR, int base 10) const; long QByteArray::toLong(bool *ok Q_NULLPTR, int base 10) const; float QByteArray::toFloat(bool *ok Q_NULLPTR) const; double QByteArray::toDouble(bool *ok Q_NULLPTR) const;// std::string - QByteArray [static] QByteArray QByteArray::fromStdString(const std::string str); // QByteArray - std::string std::string QByteArray::toStdString() const;// 所有字符转换为大写 QByteArray QByteArray::toUpper() const; // 所有字符转换为小写 QByteArray QByteArray::toLower() const;2.3.2 QString QString也是封装了字符串, 但是内部的编码为utf8, UTF-8属于Unicode字符集,它固定使用多个字节window为2字节, linux为3字节来表示一个字符这样可以将世界上几乎所有语言的常用字符收录其中。 介绍一下这个类中常用的一些API函数。 构造函数 // 构造一个空字符串对象 QString::QString(); // 将 char* 字符串 转换为 QString 类型 QString::QString(const char *str); // 将 QByteArray 转换为 QString 类型 QString::QString(const QByteArray ba); // 其他重载的同名构造函数可参考Qt帮助文档, 此处略数据操作 // 尾部追加数据 // 其他重载的同名函数可参考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);子字符串查找和判断 // 参数 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;遍历 // 使用迭代器 iterator QString::begin(); iterator QString::end();// 使用数组的方式进行遍历 // i的取值范围 0 position size() const QChar QString::at(int position) const const QChar QString::operator[](int position) const;查看字节数 // 返回字节数组对象中字符的个数 (字符个数和字节个数是不同的概念) 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;类型转换 // 将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;字符串格式 // 其他重载的同名函数可参考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);2.4 QVariant QVariant这个类很神奇或者说方便。很多时候需要几种不同的数据类型需要传递如果用结构体又不大方便容器保存的也只是一种数据类型而QVariant则可以统统搞定。 QVariant 这个类型充当着最常见的数据类型的联合。QVariant可以保存很多Qt的数据类型包括QBrush、QColor、QCursor、QDateTime、QFont、QKeySequence、QPalette、QPen、QPixmap、QPoint、QRect、QRegion、QSize和QString并且还有C基本类型如int、float等。 2.4.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); #endifint i v.toInt(); // i is now 5 QString s v.toString(); // s is now 5判断 QVariant中封装的实际数据类型 // 该函数的返回值是一个枚举类型, 可通过这个枚举判断出实际是什么类型的数据 Type QVariant::type() const;返回值Type的部分枚举定义, 全部信息可查阅Qt帮助文档 将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; ......2.4.2 自定义类型 除标准类型, 自定义的类型也可以使用QVariant类进行封装,被QVariant存储的数据类型需有一个默认的构造函数和一个拷贝构造函数。为实现此功能首先必须使用Q_DECLARE_METATYPE()宏。 通常会将这个宏放在类的声明所在头文件的下面原型为 Q_DECLARE_METATYPE(Type) 使用步骤如下: 第一步: 在头文件中声明 // *.h struct MyTest {int id;QString name; }; // 自定义类型注册 Q_DECLARE_METATYPE(MyTest)第二步: 在源文件中定义 MyTest t; t.name 张三丰; t.num 666; // 值的封装 QVariant vt QVariant::fromValue(t);// 值的读取 if(vt.canConvertMyTest()) {MyTest t vt.valueMyTest();qDebug() name: t.name , num: t.num; }以上操作用到的QVariant类的API如下: // 如果当前QVariant对象可用转换为对应的模板类型 T, 返回true, 否则返回false bool QVariant::canConvert() const; // 将当前QVariant对象转换为实际的 T 类型 T QVariant::value() const;2.5 位置和尺寸 2.5.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);2.5.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;2.5.3 QSize 在QT中QSize类用来形容长度和宽度 // 构造函数 // 构造空对象, 对象中的宽和高都是无效的 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);2.5.4 QRect 在Qt中使用 QRect类来描述一个矩形 // 构造函数 // 构造一个空对象 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;2.6 日期和时间 2.6.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.6.2 QTime QTime类可以封装时间信息也可以通过这个类得到时间相关的信息, 包括:时, 分, 秒, 毫秒。 // 构造函数 QTime::QTime(); /*h 取值范围 0 ~ 23m and s 取值范围 0 ~ 59ms 取值范围 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:00QTime t;t n.addSecs(70); // t 14:01:10t n.addSecs(-70); // t 13:58:50t n.addSecs(10 * 60 * 60 5); // t 00:00:05t 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();2.6.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();2.6.4 定时器类QTimer 在进行窗口程序的处理过程中, 经常要周期性的执行某些操作, 或者制作一些动画效果看似比较复杂的问题使用定时器就可以完美的解决这些问题 Qt中提供了定时器方式,介绍一下Qt中的定时器类 QTimer 的使用方法。 要使用它只需创建一个QTimer类对象然后调用其 start() 函数开启定时器此后QTimer对象就会周期性的发出 timeout() 信号。我们先来了解一下这个类的相关API。 2.6.4.1 public/slot function // 构造函数 // 如果指定了父对象, 创建的堆内存可以自动析构 QTimer::QTimer(QObject *parent nullptr);// 设置定时器时间间隔为 msec 毫秒 // 默认值是0一旦窗口系统事件队列中的所有事件都已经被处理完一个时间间隔为0的QTimer就会触发 void QTimer::setInterval(int msec); // 获取定时器的时间间隔, 返回值单位: 毫秒 int QTimer::interval() const;// 根据指定的时间间隔启动或者重启定时器, 需要调用 setInterval() 设置时间间隔 [slot] void QTimer::start(); // 启动或重新启动定时器超时间隔为msec毫秒。 [slot] void QTimer::start(int msec); // 停止定时器。 [slot] void QTimer::stop();// 设置定时器精度 /* 参数: - Qt::PreciseTimer - 精确的精度, 毫秒级- Qt::CoarseTimer - 粗糙的精度, 和1毫秒的误差在5%的范围内, 默认精度- Qt::VeryCoarseTimer - 非常粗糙的精度, 精度在1秒左右 */ void QTimer::setTimerType(Qt::TimerType atype); Qt::TimerType QTimer::timerType() const; // 获取当前定时器的精度// 如果定时器正在运行返回true; 否则返回false。 bool QTimer::isActive() const;// 判断定时器是否只触发一次 bool QTimer::isSingleShot() const; // 设置定时器是否只触发一次, 参数为true定时器只触发一次, 为false定时器重复触发, 默认为false void QTimer::setSingleShot(bool singleShot);2.6.4.2 signals 这个类的信号只有一个, 当定时器超时时该信号就会被发射出来。 给这个信号通过conect()关联一个槽函数, 就可以在槽函数中处理超时事件了。 [signal] void QTimer::timeout();2.6.4.3 static public function // 其他同名重载函数可以自己查阅帮助文档 /* 功能: 在msec毫秒后发射一次信号, 并且只发射一次 参数:- msec: 在msec毫秒后发射信号- receiver: 接收信号的对象地址- method: 槽函数地址 */ [static] void QTimer::singleShot(int msec, const QObject *receiver, PointerToMemberFunction method);2.6.4.4 定时器使用举例 周期性定时器 // 创建定时器对象 QTimer* timer new QTimer(this);// 修改定时器对象的精度 timer-setTimerType(Qt::PreciseTimer);// 按钮 loopBtn 的点击事件 // 点击按钮启动或者关闭定时器, 定时器启动, 周期性得到当前时间 connect(ui-loopBtn, QPushButton::clicked, this, []() {// 启动定时器if(timer-isActive()){timer-stop(); // 关闭定时器ui-loopBtn-setText(开始);}else{ui-loopBtn-setText(关闭);timer-start(1000); // 1000ms 1s} });connect(timer, QTimer::timeout, this, []() {QTime tm QTime::currentTime();// 格式化当前得到的系统时间QString tmstr tm.toString(hh:mm:ss.zzz);// 设置要显示的时间ui-curTime-setText(tmstr); });一次性定时器 // 点击按钮 onceBtn 只发射一次信号 // 点击按钮一次, 发射一个信号, 得到某一个时间点的时间 connect(ui-onceBtn, QPushButton::clicked, this, []() {// 获取2s以后的系统时间, 不创建定时器对象, 直接使用类的静态方法QTimer::singleShot(2000, this, [](){QTime tm QTime::currentTime();// 格式化当前得到的系统时间QString tmstr tm.toString(hh:mm:ss.zzz);// 设置要显示的时间ui-onceTime-setText(tmstr);}); });3. 信号槽 介绍Qt中的信号槽, 主要内容包括: 信号槽的本质, 信号槽的关系, 标准信号槽的使用, 自定义信号槽的使用, 信号槽的拓展 。 3.1 信号和槽概述 信号槽是 Qt框架引以为豪的机制之一。所谓信号槽实际就是观察者模式(发布-订阅模式)。 当某个事件发生之后比如按钮检测到自己被点击了一下它就会发出一个信号signal。这种发出是没有目的的类似广播。 如果有对象对这个信号感兴趣它就会使用连接connect函数意思是将想要处理的信号和自己的一个函数称为槽slot绑定来处理这个信号。 也就是说当信号发出时被连接的槽函数会自动被回调。这就类似观察者模式当发生了感兴趣的事件某一个操作就会被自动触发。 3.1.1 信号的本质 信号是由于用户对窗口或控件进行了某些操作导致窗口或控件产生了某个特定事件这时候Qt对应的窗口类会发出某个信号以此对用户的挑选做出反应。 因此根据上述的描述我们得到一个结论 – 信号的本质就是事件比如 按钮单击、双击 窗口刷新 鼠标移动、鼠标按下、鼠标释放 键盘输入 那么在Qt中信号是通过什么形式呈现给使用者的呢 我们对哪个窗口进行操作, 哪个窗口就可以捕捉到这些被触发的事件。对于使用者来说触发了一个事件我们就可以得到Qt框架给我们发出的某个特定信号。信号的呈现形式就是函数 也就是说某个事件产生了 Qt框架就会调用某个对应的信号函数 通知使用者。 在QT中信号的发出者是某个实例化的类对象对象内部可以进行相关事件的检测。 3.1.2 槽的本质 在Qt中槽函数是一类特殊的功能的函数在编码过程中也可以作为类的普通成员函数来使用。 之所以称之为槽函数是因为它们还有一个职责就是对Qt框架中产生的信号进行处理。 在Qt中槽函数的所有者也是某个类的实例对象。 3.1.3 信号和槽的关系 在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不会成功 3.2 标准信号槽使用 3.2.1 标准信号/槽 在Qt提供的很多标准类中都可以对用户触发的某些特定事件进行检测, 因此当用户做了这些操作之后, 事件被触发类的内部就会产生对应的信号,这些信号都是Qt类内部自带的, 因此称之为标准信号。 同样的在Qt的很多类内部为我了提供了很多功能函数并且这些函数也可以作为触发的信号的处理动作有这类特性的函数在Qt中称之为标准槽函数。 系统自带的信号和槽通常如何查找呢这个就需要利用帮助文档了比如在帮助文档中查询按钮的点击信号那么需要在帮助文档中输入QPushButton 首先我们可以在Contents中寻找关键字signals信号的意思但是我们发现并没有找到这时候我们应该看当前类从父类继承下来了哪些信号 因此我们去他的父类QAbstractButton中就可以找到该关键字点击signals索引到系统自带的信号有如下几个 3.2.2 使用 掌握标准信号、槽的查找方式之后以及connect()函数的作用之后, 一个简单的例子了解使用方式。 功能实现 点击窗口上的按钮, 关闭窗口 功能分析:- 按钮: 信号发出者 - QPushButton 类型- 窗口: 信号的接收者和处理者 - QWidget 类型需要使用的标准信号槽函数 // 单击按钮发出的信号 [signal] void QAbstractButton::clicked(bool checked false) // 关闭窗口的槽函数 [slot] bool QWidget::close();对于上边的需求只需要一句代码, 只需要写一句代码就能实现了 // 单击按钮关闭窗口 connect(ui-closewindow, QPushButton::clicked, this, MainWindow::close);connect()操作一般写在窗口的构造函数中, 相当于在事件产生之前在qt框架中先进行注册, 这样在程序运行过程中假设产生了按钮的点击事件, 框架就会调用信号接收者对象对应的槽函数了, 如果信号不产生, 槽函数也就一直不会被调用。 3.3 自定义信号槽使用 Qt框架提供的信号槽在某些特定场景下是无法满足我们的项目需求的因此我们还设计自己需要的的信号和槽同样还是使用connect()对自定义的信号槽进行连接。 如果想要在QT类中自定义信号槽, 需要满足一些条件, 并且有些事项也需要注意: 要编写新的类并且让其继承Qt的某些标准类这个新的子类必须从QObject类或者是QObject子类进行派生在定义类的头文件中加入 Q_OBJECT 宏 // 在头文件派生类的时候首先像下面那样引入Q_OBJECT宏 class MyMainWindow : public QWidget {Q_OBJECT...... }3.3.1 自定义信号 在Qt中信号的本质是事件, 但是在框架中也是以函数的形式存在的, 只不过信号对应的函数只有声明,没有定义。如果Qt中的标准信号不能满足我们的需求可以在程序中进行信号的自定义当自定义信号对应的事件产生之后认为的将这个信号发射出去即可其实就是调用一下这个信号函数。 下边给大家阐述一下, 自定义信号的要求和注意事项: 信号是类的成员函数返回值必须是 void 类型信号的名字可以根据实际情况进行指定参数可以随意指定, 信号也支持重载信号需要使用 signals 关键字进行声明, 使用方法类似于public等关键字信号函数只需要声明, 不需要定义(没有函数体实现)在程序中发射自定义信号: 发送信号的本质就是调用信号函数 习惯性在信号函数前加关键字: emit, 但是可以省略不写emit只是显示的声明一下信号要被发射了, 没有特殊含义底层 emit #define emit // 举例: 信号重载 // Qt中的类想要使用信号槽机制必须要从QObject类派生(直接或间接派生都可以) class Test : public QObject {Q_OBJECT signals:void testsignal();// 参数的作用是数据传递, 谁调用信号函数谁就指定实参// 实参最终会被传递给槽函数void testsignal(int a); };3.3.2 自定义槽 槽函数就是信号的处理动作在Qt中槽函数可以作为普通的成员函数来使用。如果标准槽函数提供的功能满足不了需求可以自己定义槽函数进行某些特殊功能的实现。自定义槽函数和自定义的普通函数写法是一样的。 下边给大家阐述一下, 自定义槽的要求和注意事项: 返回值必须是 void 类型 槽也是函数, 因此也支持重载 槽函数需要指定多少个参数, 需要看连接的信号的参数个数 槽函数的参数是用来接收信号传递的数据的, 信号传递的数据就是信号的参数 举例: 信号函数: void testsig(int a, double b);槽函数: void testslot(int a, double b); 总结: 槽函数的参数应该和对应的信号的参数个数, 从左到右类型依次对应信号的参数可以大于等于槽函数的参数个数 信号传递的数据被忽略了 信号函数: void testsig(int a, double b);槽函数: void testslot(int a); Qt中槽函数的类型是多样的 Qt中的槽函数可以是类的成员函数、全局函数、静态函数、Lambda表达式匿名函数 槽函数可以使用关键字进行声明: slots (Qt5中slots可以省略不写) public slots:private slots: – 这样的槽函数不能在类外部被调用protected slots: – 这样的槽函数不能在类外部被调用 // 槽函数书写格式举例 // 类中的这三个函数都可以作为槽函数来使用 class Test : public QObject {public:void testSlot();static void testFunc();public slots:void testSlot(int id); };​ 根据特定场景自定义信号槽: // class GirlFriend class GirlFriend : public QObject {Q_OBJECT public:explicit GirlFriend(QObject *parent nullptr);signals:void hungry(); // 不能表达出想要吃什么void hungry(QString msg); // 可以通过参数表达想要吃什么 };// class Me class Me : public QObject {Q_OBJECT public:explicit Me(QObject *parent nullptr);public slots:// 槽函数void eatMeal(); // 不能知道信号发出者要吃什么void eatMeal(QString msg); // 可以知道信号发出者要吃什么 };3.4 信号槽拓展 3.4.1 信号槽使用拓展 一个信号可以连接多个槽函数, 发送一个信号有多个处理动作 需要写多个connect连接槽函数的执行顺序是随机的, 和connect函数的调用顺序没有关系信号的接收者可以是一个对象, 也可以是多个对象 一个槽函数可以连接多个信号, 多个不同的信号, 处理动作是相同的 需要写多个connect连接 信号可以连接信号 信号接收者可不处理接收的信号, 而是继续发射新的信号这相当于传递了数据, 并没有对数据进行处理 connect(const QObject *sender, QObject::signal, const QObject *receiver, QObject::siganl-new);信号槽是可以断开的 disconnect(const QObject *sender, QObject::signal, const QObject *receiver, QObject::method);3.4.2 信号槽的连接方式 Qt5的连接方式 // 语法: QMetaObject::Connection QObject::connect(const QObject *sender, PointerToMemberFunction signal, const QObject *receiver, PointerToMemberFunction method, Qt::ConnectionType type Qt::AutoConnection);// 信号和槽函数也就是第2,4个参数传递的是地址, 编译器在编译过程中会对数据的正确性进行检测 connect(const QObject *sender, QObject::signal, const QObject *receiver, QObject::method);Qt4的连接方式 这种旧的信号槽连接方式在Qt5中是支持的, 但是不推荐使用, 因为这种方式在进行信号槽连接的时候,信号槽函数通过宏SIGNAL和SLOT转换为字符串类型。 因为信号槽函数的转换是通过宏来进行转换的因此传递到宏函数内部的数据不会被进行检测如果使用者传错了数据编译器也不会报错但实际上信号槽的连接已经不对了只有在程序运行起来之后才能发现问题而且问题不容易被定位。 // Qt4的信号槽连接方式 [static] QMetaObject::Connection QObject::connect(const QObject *sender, const char *signal, const QObject *receiver, const char *method, Qt::ConnectionType type Qt::AutoConnection);connect(const QObject *sender,SIGNAL(信号函数名(参数1, 参数2, ...)),const QObject *receiver,SLOT(槽函数名(参数1, 参数2, ...)));Qt4中声明槽函数必须要使用 slots 关键字, 不能省略。 应用举例 场景描述 我肚子饿了, 我要吃东西。 分析 信号的发出者是我自己, 信号的接收者也是我自己 先定义出一个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); // errorQt5处理方式错误原因分析 上边的写法之所以错误是因为这个类中信号槽都是重载过的, 信号和槽都是通过函数名去关联函数的地址, 但是这个同名函数对应两块不同的地址, 一个带参, 一个不带参, 因此编译器就不知道去关联哪块地址了, 所以如果我们在这种时候通过以上方式进行信号槽连接, 编译器就会报错。 解决方案 可以通过定义函数指针的方式指定出函数的具体参数这样就可以确定函数的具体地址了。定义函数指针指向重载的某个信号或者槽函数在connect函数中将函数指针名字作为实参就可以了。 // 举例 void (Me::*func1)(QString) Me::eat; // func1指向带参的信号 void (Me::*func2)() Me::hungury; // func2指向不带参的槽函数Qt正确的处理方式: // 定义函数指针指向重载的某一个具体的信号地址 void (Me::*mysignal)(QString) Me::eat; // 定义函数指针指向重载的某一个具体的槽函数地址 void (Me::*myslot)(QString) Me::hungury; // 使用定义的函数指针完成信号槽的连接 connect(m, mysignal, m, myslot);总结 Qt4的信号槽连接方式因为使用了宏函数, 宏函数对用户传递的信号槽不会做错误检测, 容易出bugQt5的信号槽连接方式, 传递的是信号槽函数的地址, 编译器会做错误检测, 减少了bug的产生当信号槽函数被重载之后, Qt4的信号槽连接方式不受影响当信号槽函数被重载之后, Qt5中需要给被重载的信号或者槽定义函数指针
文章转载自:
http://www.morning.jzsgn.cn.gov.cn.jzsgn.cn
http://www.morning.ylqpp.cn.gov.cn.ylqpp.cn
http://www.morning.ntdzjx.com.gov.cn.ntdzjx.com
http://www.morning.xwqxz.cn.gov.cn.xwqxz.cn
http://www.morning.hbpjb.cn.gov.cn.hbpjb.cn
http://www.morning.ltrz.cn.gov.cn.ltrz.cn
http://www.morning.mjpgl.cn.gov.cn.mjpgl.cn
http://www.morning.rfpb.cn.gov.cn.rfpb.cn
http://www.morning.rscrj.cn.gov.cn.rscrj.cn
http://www.morning.lblsx.cn.gov.cn.lblsx.cn
http://www.morning.knsmh.cn.gov.cn.knsmh.cn
http://www.morning.dwmtk.cn.gov.cn.dwmtk.cn
http://www.morning.cpktd.cn.gov.cn.cpktd.cn
http://www.morning.bpmdg.cn.gov.cn.bpmdg.cn
http://www.morning.pzwfw.cn.gov.cn.pzwfw.cn
http://www.morning.bxczt.cn.gov.cn.bxczt.cn
http://www.morning.jhfkr.cn.gov.cn.jhfkr.cn
http://www.morning.mmjyk.cn.gov.cn.mmjyk.cn
http://www.morning.sbdqy.cn.gov.cn.sbdqy.cn
http://www.morning.wfhnz.cn.gov.cn.wfhnz.cn
http://www.morning.tgwfn.cn.gov.cn.tgwfn.cn
http://www.morning.rsdm.cn.gov.cn.rsdm.cn
http://www.morning.lffrh.cn.gov.cn.lffrh.cn
http://www.morning.xxwfq.cn.gov.cn.xxwfq.cn
http://www.morning.jmdpp.cn.gov.cn.jmdpp.cn
http://www.morning.msxhb.cn.gov.cn.msxhb.cn
http://www.morning.cxryx.cn.gov.cn.cxryx.cn
http://www.morning.fsjcn.cn.gov.cn.fsjcn.cn
http://www.morning.gmjkn.cn.gov.cn.gmjkn.cn
http://www.morning.hbqhz.cn.gov.cn.hbqhz.cn
http://www.morning.hkswt.cn.gov.cn.hkswt.cn
http://www.morning.rbgwj.cn.gov.cn.rbgwj.cn
http://www.morning.qrmry.cn.gov.cn.qrmry.cn
http://www.morning.yxmcx.cn.gov.cn.yxmcx.cn
http://www.morning.pngdc.cn.gov.cn.pngdc.cn
http://www.morning.sglcg.cn.gov.cn.sglcg.cn
http://www.morning.kzcfr.cn.gov.cn.kzcfr.cn
http://www.morning.zcncb.cn.gov.cn.zcncb.cn
http://www.morning.gsksm.cn.gov.cn.gsksm.cn
http://www.morning.cgmzt.cn.gov.cn.cgmzt.cn
http://www.morning.qdsmile.cn.gov.cn.qdsmile.cn
http://www.morning.hxxyp.cn.gov.cn.hxxyp.cn
http://www.morning.wkhfg.cn.gov.cn.wkhfg.cn
http://www.morning.gxcit.com.gov.cn.gxcit.com
http://www.morning.lcjw.cn.gov.cn.lcjw.cn
http://www.morning.jrbyz.cn.gov.cn.jrbyz.cn
http://www.morning.ygwyt.cn.gov.cn.ygwyt.cn
http://www.morning.lnyds.cn.gov.cn.lnyds.cn
http://www.morning.zlxrg.cn.gov.cn.zlxrg.cn
http://www.morning.jcnmy.cn.gov.cn.jcnmy.cn
http://www.morning.lwcqh.cn.gov.cn.lwcqh.cn
http://www.morning.lhxkl.cn.gov.cn.lhxkl.cn
http://www.morning.prznc.cn.gov.cn.prznc.cn
http://www.morning.sxfmg.cn.gov.cn.sxfmg.cn
http://www.morning.gdpai.com.cn.gov.cn.gdpai.com.cn
http://www.morning.jykzy.cn.gov.cn.jykzy.cn
http://www.morning.gjwkl.cn.gov.cn.gjwkl.cn
http://www.morning.djpzg.cn.gov.cn.djpzg.cn
http://www.morning.rrrrsr.com.gov.cn.rrrrsr.com
http://www.morning.tdgwg.cn.gov.cn.tdgwg.cn
http://www.morning.qzdxy.cn.gov.cn.qzdxy.cn
http://www.morning.jwmws.cn.gov.cn.jwmws.cn
http://www.morning.plqqp.cn.gov.cn.plqqp.cn
http://www.morning.zmqb.cn.gov.cn.zmqb.cn
http://www.morning.nsncq.cn.gov.cn.nsncq.cn
http://www.morning.qbmjf.cn.gov.cn.qbmjf.cn
http://www.morning.qdscb.cn.gov.cn.qdscb.cn
http://www.morning.fwkq.cn.gov.cn.fwkq.cn
http://www.morning.kngqd.cn.gov.cn.kngqd.cn
http://www.morning.wfkbk.cn.gov.cn.wfkbk.cn
http://www.morning.pphgl.cn.gov.cn.pphgl.cn
http://www.morning.pxtgf.cn.gov.cn.pxtgf.cn
http://www.morning.bpmz.cn.gov.cn.bpmz.cn
http://www.morning.epeij.cn.gov.cn.epeij.cn
http://www.morning.dpfr.cn.gov.cn.dpfr.cn
http://www.morning.shuanga.com.cn.gov.cn.shuanga.com.cn
http://www.morning.dmtld.cn.gov.cn.dmtld.cn
http://www.morning.hcsqznn.cn.gov.cn.hcsqznn.cn
http://www.morning.ntqlz.cn.gov.cn.ntqlz.cn
http://www.morning.yxwrr.cn.gov.cn.yxwrr.cn
http://www.tj-hxxt.cn/news/238020.html

相关文章:

  • 莱芜网站建设与管理网站开发周期安排
  • html5网站是用什么软件做的吗谷歌seo排名优化
  • 网站建设的需要是什么做云教育集群网站
  • 免费游戏网站建设雷锋书签制作图片
  • 工程机械网站设计佛山做优化的公司哪家好
  • 南阳市网站建设wordpress与织梦
  • 关于文化建设网站电商业务推广
  • 东莞长安网站制作计算机网络技术 网站建设
  • 医院网站建设医生需要做什么阿里云简单网站建设
  • 电商网站建设服务平台wordpress文章分类导航
  • 烘焙食品网站建设需求分析仿京东电商的网站开发报价
  • 中英文的网站设计电脑做系统都是英文选哪个网站
  • 语音网站怎么做怎么设置自己的网站
  • 网站优化seo教程flash网站系统
  • 做网站ps的图片上海人才网招聘网最新招聘
  • 黄石网站建设费用百度联盟怎么赚钱
  • 注册网站会员需要详细邢台市做网站
  • 莆田网站关键词优化网站被黑解决方案
  • 可以免费做简历的网站wordpress 自建网站
  • 微科技h5制作网站模板哪些网站的做的好看
  • 网站的维护电子商务网站开发技术支持
  • 制作网站的专业公司吗计算机网站建设 是什么
  • 有特效的网站制作古城西安网页
  • 网络企业做网站房产中介如何找客源
  • 做网站哪些公司好网站建设服务器维护内容
  • 沈阳专门做网站做网站年入百万
  • 上海网站建设 推荐站霸网络三合一网站是什么
  • 福州百度网站快速优化注册深圳公司流程及费用
  • wordpress 安卓主题网站推广优化排名公司
  • 肃北蒙古族自治县建设局网站地情网站建设总结