QT之QFlags详解

简介: QT之QFlags详解

学习之前我们先补习一下枚举和或运算的基础,因为很多人直接学Qt的或者c++忘的有点多的,需要有一些基础才能搞懂QFlag这个东西。

枚举:

枚举类型(Enum Types)是一种用户定义的数据类型,用于表示具名的整数常量。枚举类型可以帮助提高代码的可读性,使程序更易于理解。

以下是一些使用枚举类型的典型情况:

代替魔法数值: 枚举类型可以用于替代代码中的魔法数值(Magic Numbers)。例如,假设你的程序中有一个表示星期的整数,你可以使用枚举类型:
enum Weekday {
    Monday,
    Tuesday,
    Wednesday,
    Thursday,
    Friday,
    Saturday,
    Sunday
};

这样你的代码中就可以使用 Weekday 枚举来表示星期,而不是使用 0 到 6 之间的数字。

有限的选项集: 当你的变量只能有有限的一组选项时,使用枚举类型可以提高代码的清晰度。例如,表示颜色的枚举:
enum Color {
    Red,
    Green,
    Blue,
    Yellow,
    // ...
};

这样你可以使用 Color 枚举来表示颜色,而不是使用数字或字符串。

在以上代码中这个Weekday和Color是枚举类型,其中Red或者Sunday是枚举常量

枚举类型与运算

枚举类型的或运算通常用于创建一个组合值,其中一个枚举值的位被设置。这在处理一组选项或标志时非常有用。以下是一个简单的例子:

假设有一个表示文件权限的枚举类型:

enum FileAccess { Read = 1, Write = 2, Execute = 4 };

现在,假设你有一个文件,你想给它读和写的权限:

FileAccess myFilePermissions = Read | Write;

在这里,| 是按位或运算符,用于将 ReadWrite 枚举值的对应位进行组合。现在,myFilePermissions 的值是 Read | Write 的组合,它的二进制表示为11;所以值就是十进制的3

计算过程

关键词复习:组合值(类型枚举的组合)(或运算)这种逻辑运算有时候也叫做位掩码(bitmasks)

进入正题QFlags:

首先说一下普通枚举得缺点:

QFlags<Enum>类是一个模板类,其中Enum是枚举类型。QFlags在Qt中用于存储枚举值的组合。

用于存储或组合枚举值的传统C++方法是使用整型变量。这种方法的不便之处在于根本没有类型检查,任何枚举值都可以与任何其他枚举值进行逻辑运算。

enum Orientation
    {
        Up = 1,
        Down = 2,
        Left = 4,
        Right = 8,
    };
    enum Direction
    {
        horizontal = 2,
        vertical = 3,
    };

这两种操作编译器不会报错:

Orientation::Up | Direction::horizontal;
Orientation::Up | Orientation::Down;

第一种两个不相关的枚举值做逻辑运算没有意义,第二种运算结果是3,但Orientation中没有值是3的标识符。

在Qt6中c++开发指南中是这样介绍QFlags的:

QFlags<Enum>是一个模板类,其中Enum是枚举类型,QFlags用于定义枚举值的或运算组合,在Qt中经常用到 QFlags 类。例如,QLabel 有一个alignment 属性,其读写函数分别定义如下:

Qt::Alignment alignment()
void setAlignment(Ot::Alignment)

alignment属性值是Qt:Alignment类型Qt帮助文档中显示的Qt::Alignment信息有如下表示

enum Qt::AlignmentFlag  //枚举类型
flags Qt::Alignment     //标志类型

第一行代码翻译一下就是Qt命名空间下的有一个变量名字叫做AlignmentFlag他是枚举类型

这表示Qt::Alignment是QFlags<Qt::AlignmentFlag>类型,但是Qt中并没有定义实际的类型Qt::Alignment,也就是不存在如下的定义:

这样的定义实际不存在

typedef QFlags<Qt::AlignmentFlag> Qt::Alignment;

Qt::AlignmentFlag 是枚举类型,其有一些枚举常量。

如:

详见Qt文档。

Ot::Alignment是一个或多个Qt:AlignmentFlag类型枚举值的组合,是一种特性标志。

即Alignment可以是 AlignLeft | AlignRight

也可以是 AlignHCenter | AlignLeft所以我们把Qt::Alignment称为枚举类型Qt::AlignmentFlag的标志类型。

给窗口上的OLabel组件label 设置对齐方式,可以使用如下的代码

ui->label->setAlignment(Qt::AlignLeft lQt::AlignVCenter);

这实际上是创建了一个Qt::Alignment类型的临时变量,相当于如下的代码:

 

QFlags<Qt::AlignmentFlag> flags = Qt::AlignLeft | Qt::AlignVCenter;
ui->label->setAlignment(flags);

看这段代码并有没有写Qt::Alignment = Qt::AlignLeft | Qt::AlignVCenter;

也可以看出实际并没有Qt::Alignment,他只是一个标志。

QFlags 类支持或、与、异或等位运算,所以也可以这样写代码\

QFlags<Qt::AlignmentFlag> flags= ui->label->alignment();//获取alignment 属性值
flags = flags | Qt::AlignVCenter;//增加垂直对齐
u1->label->setAlignment(flags);//设置alignment 属性值

这里主要是要区分帮助文档中enum Qt:AlignmentFlag 和flags Qt::Alignment的意义,不要把QLabel的setAlignment()函数的输入参数认为是枚举类型,它实际上是标志类型。

QFlags类有一个函数testFlag()可以测试某个枚举值是否包含在此标志变量中,例如:

 

//获取alignment 属性值//是否包含
QFlags<Ot;:AlignmentFlag> flags= ui->label->alignment();
bool isLeft = flags.testFlag(Qt::AlignLeft);

Qt使用QFlags来提供类型安全性。

如果要对自己的枚举类型使用QFlags,应使用Q_DECLARE_FLAGS()和Q_DECLARE_OPERATORS_FOR_FLAGS()。

例:
  class MyClass
  {
  public:
    enum Orientation
    {
        Up = 1,
        Down = 2,
        Left = 4,
        Right = 8,
    };
    Q_DECLARE_FLAGS(Orientations, Orientation)
      ...
  };
  Q_DECLARE_OPERATORS_FOR_FLAGS(MyClass::Orientations)

这样为枚举Orientation创建了一个Flags:Orientations,这个Orientations的类型就是QFlags<MyClass::Orientation>。可以用Orientations对象接收逻辑运算的值了:

Orientations f = Orientation::Up | Orientation::Down;

总结:

个人觉得QFLags其实就是一个存储枚举组合值得东西

大家如果想要在深入了解,可以去看下面这篇博客

采用博客内容:

版权声明:本文为CSDN博主「友善啊,朋友」的原创文章,遵循CC 4.0 BY-SA版权协议,转载请附上原文出处链接及本声明。

原文链接:https://blog.csdn.net/kenfan1647/article/details/114801093

目录
相关文章
|
设计模式 编译器 API
【C/C++ Pimpl模式】隐藏实现细节的高效方式 (Pimpl Idiom: An Efficient Way to Hide Implementation Details)
【C/C++ Pimpl模式】隐藏实现细节的高效方式 (Pimpl Idiom: An Efficient Way to Hide Implementation Details)
1501 1
|
存储 C++ 容器
QVariant类应用 和 Q_DECLARE_METATYPE说明
QVariant类应用 和 Q_DECLARE_METATYPE说明
|
数据库 数据库管理
qt对sqlite数据库多线程的操作
本文总结了在Qt中进行SQLite数据库多线程操作时应注意的四个关键问题,包括数据库驱动加载、加锁、数据库的打开与关闭,以及QsqlQuery变量的使用。
768 1
|
Linux 图形学
深入理解Qt定时器:QTimer的魅力与挑战(一)
深入理解Qt定时器:QTimer的魅力与挑战
7463 0
|
存储 算法 编译器
【C++ 引用 】C++深度解析:引用成员变量的初始化及其在模板编程中的应用(一)
【C++ 引用 】C++深度解析:引用成员变量的初始化及其在模板编程中的应用
1688 0
|
C++ 缓存 存储
面向 C++ 的现代 CMake 教程(一)(3)
面向 C++ 的现代 CMake 教程(一)
364 0
【Qt 学习笔记】Qt窗口 | 标准对话框 | 文件对话框QFileDialog
【Qt 学习笔记】Qt窗口 | 标准对话框 | 文件对话框QFileDialog
2883 4
|
前端开发 开发者 UED
UI 框架:nav-ui&uni-ui&vant
本文档介绍了`nav-ui`、`uni-ui`和`vant`三个UI库的基本使用方法,包括图标、表格和树的使用示例,以及如何在项目中安装和配置这些UI组件。对于`nav-ui`,详细说明了图标组件的安装与使用,包括本地图标和第三方图标库的集成方式。`uni-ui`部分则重点讲解了CSS的使用方法。最后,`vant`部分提供了从项目创建到组件安装的具体步骤,以及如何将下载的组件正确地集成到项目中。
506 4
|
存储 编译器 C++
【Qt 元对象系统 02】深入探索Qt的元对象编译器:从原理到实践
【Qt 元对象系统 02】深入探索Qt的元对象编译器:从原理到实践
850 0
|
安全 Linux 网络安全
【工具使用】几款优秀的SSH连接客户端软件工具推荐FinalShell、Xshell、MobaXterm、OpenSSH、PUTTY、Terminus、mRemoteNG、Terminals等
【工具使用】几款优秀的SSH连接客户端软件工具推荐FinalShell、Xshell、MobaXterm、OpenSSH、PUTTY、Terminus、mRemoteNG、Terminals等
119914 0