单页面组合网站,六安人才网官网,外网如何查看局域网建设的网站,天元建设集团有限公司重庆分公司Qt中的枚举变量,Q_ENUM,Q_FLAG,Q_NAMESPACE,Q_ENUM_NS,Q_FLAG_NS以及其他 理论基础#xff1a;一、Q_ENUM二、QMetaEnum三、Q_FLAG四、示例 Chapter1 Qt中的枚举变量,Q_ENUM,Q_FLAG,Q_NAMESPACE,Q_ENUM_NS,Q_FLAG_NS以及其他前言Q_ENUM的使用Q_FLAG的引入解决什么问题#xf… Qt中的枚举变量,Q_ENUM,Q_FLAG,Q_NAMESPACE,Q_ENUM_NS,Q_FLAG_NS以及其他 理论基础一、Q_ENUM二、QMetaEnum三、Q_FLAG四、示例 Chapter1 Qt中的枚举变量,Q_ENUM,Q_FLAG,Q_NAMESPACE,Q_ENUM_NS,Q_FLAG_NS以及其他前言Q_ENUM的使用Q_FLAG的引入解决什么问题Q_NAMESPACE,Q_ENUM_NS和Q_FLAG_NS新旧对比 Chapter2 【QT】枚举常用宏Chapter3 Qt中自定义结构体、枚举型做信号参数传递参考链接问题解决示例为什么不使用Q_ENUMS() Chapter4 如何在Qt信号和槽中使用枚举Chapter5 个人总结(2023-10)user.huser.cpp 理论基础
一、Q_ENUM
用Q_ENUM就可以将自定义枚举类型注册到Qt的元对象系统中从而实现枚举到各种类型的转换。
既然是元对象系统就会使用Moc编译因此枚举类型需要放在继承于添加了Q_OBJECT宏继承QObject的类中并且声明为public属性以便外部使用。
二、QMetaEnum
QMetaEnum实现了字符串到枚举枚举到字符串的转换以及一些其他的转换这样可以增加代码的可读性。具体大家可以在帮助手册中看看QMetaEnum的接口。
其他类转换到QMetaEnum 类型可以使用QMetaEnum::fromType()获取QMetaEnum对象。
三、Q_FLAG
Q_ENUM可以实现大部分常用功能引入Q_FLAG主要为了解决枚举变量的组合使用增加枚举变量间与或非计算比如Up是1Left是4则Up|Left是5为一个有意义的值。
四、示例
#ifndef USER_H
#define USER_H#include QObjectclass User : public QObject
{Q_OBJECT
public:explicit User(QObject *parent nullptr);~User();enum Authorization { //增加用户权限枚举类型USER表示操作员ADMIN表示管理员SUPPER_ADMIN表示超级管理员USER 1,ADMIN 2,SUPPER_ADMIN 3};Q_ENUM(Authorization)Q_DECLARE_FLAGS(AuthorizationFlags, Authorization)Q_FLAG(AuthorizationFlags)public:static User* getHandle();User::Authorization getAuthorization(); //获取当前用户权限signals:private:static User* handle;User::Authorization authorization; //用户权限
};Q_DECLARE_OPERATORS_FOR_FLAGS(User::AuthorizationFlags)#endif // USER_HChapter1 Qt中的枚举变量,Q_ENUM,Q_FLAG,Q_NAMESPACE,Q_ENUM_NS,Q_FLAG_NS以及其他
原文链接https://blog.csdn.net/qq_36179504/article/details/100895133
前言
之前做一个比较大工程核心数据里面有很多是枚举变量需要频繁地使用枚举量到字符串和字符串到枚举量的操作为了实现这些操作我把每个枚举类型后面都附加了两个类似Enum_to_String()和String_to_Enum()的函数程序显得很臃肿。这时候就非常羡慕C#或者java等兄弟语言内核内置了枚举量和字符串转换的方法。 最近读Qt文档时偶然间发现Qt内核其实已经提供了这个转换机制使得我们能用很少的代码完成枚举量和字符串的转换甚至还能实现其他更酷更强大的功能下面我们就来看看如何使用Qt的这个功能。 简单来讲Qt还是使用一组宏命令来完成枚举量扩展功能的正如Qt的其他核心机制一样这些宏包括Q_ENUM,Q_FLAG,Q_ENUM_NS,Q_FLAG_NSQ_DECLARE_FLAGSQ_DECLARE_OPERATORS_FOR_FLAGS 这些宏的实现原理和如何展开如何注册到Qt内核均不在本文的讲解范围本文只讲应用。
Q_ENUM的使用
首先讲解最简单明了的宏Q_ENUM先看代码
#include QObjectclass MyEnum : public QObject
{Q_OBJECT
public:explicit MyEnum(QObject *parent nullptr);enum Priority{High 1,Low 2,VeryHigh 3,VeryLow 4};Q_ENUM(Priority)
};这就是在类中定义了一个普通的枚举变量之后额外加入了Q_ENUM枚举类型名这样的一个宏语句那么加入了这个Qt引入的宏语句后我们能得到什么收益呢
qDebug() MyEnum::High MyEnum::Low; //qDebug()可以直接打印出枚举类值的字符串名称
QMetaEnum m QMetaEnum::fromTypeMyEnum::Priority(); //since Qt5.5
qDebug() keyToValue: m.keyToValue(VeryHigh);
qDebug() valueToKey: m.valueToKey(MyEnum::VeryHigh);
qDebug() keyCount: m.keyCount();输出是
MyEnum::High MyEnum::Low
keyToValue: 4
valueToKey: VeryHigh
keyCount: 4 可见使用Q_ENUM注册过的枚举类型可以不加修饰直接被qDebug()打印出来另外通过静态函数QMetaEnum::fromType()可以获得一个QMetaEnum 对象以此作为中介能够轻松完成枚举量和字符串之间的相互转化。 这一点恐怕是引入Q_ENUM机制最直接的好处。 除此以外QMetaEnum还提供了一个内部的索引从1开始给每个枚举量按自然数顺序编号注意和枚举量本身的数值是两回事提供了int value(int index) 和const char *key(int index) 两个便捷函数分别返回枚举量对应的数值和枚举量对应的字符串配合keyCount() 函数可以实现枚举量的遍历
qDebug()m.name():;
for (int i 0; i m.keyCount(); i) {qDebug()m.key(i)m.value(i);
}其中name()函数返回枚举类型名字。 Q_ENUM使用起来很很简单对不对但是还是有几个注意事项需要说明
Q_ENUM只能在使用了Q_OBJECT或者Q_GADGET的类中类可以不继承自QObject但一定要有上面两个宏之一Q_GADGET是Q_OBJECT的简化版提供元对象的一部分功能但不支持信号槽Q_ENUM宏只能放置于所包含的结构体定义之后放在前面编译器会报错结构体定义和Q_ENUM宏之间可以插入其他语句但不建议这样做一个类头文件中可以定义多个Q_ENUM加持的结构体结构体和Q_ENUM是一一对应的关系Q_ENUM加持的结构体必须是公有的Q_ENUM宏引入自Qt5.5版本之前版本的Qt请使用Q_ENUMS宏但Q_ENUMS宏不支持QMetaEnum::fromType()函数(这也是Q_ENUMS被弃用的原因)。
Q_FLAG的引入解决什么问题
除了Q_ENUMQt中还有另一个类似的宏——Q_FLAG着力弥补C中结构体无法组合使用和缺乏类型检查的缺点怎么理解呢我们看一个例子 在经典C中如果我们要定义一个表示方位的结构体
enum Orientation
{
Up 1,
Down 2,
Left 4,
Right 8
};注意这里枚举值被定义成等比数列这个技巧给使用|“操作符扩展留下了空间比如左上可以用Up | Left来简单表示但是这里也带来了一个问题Up | Left值是一个整型并不在枚举结构Orientation中如果函数使用Orientation作为自变量编译器是无法通过的为此往往把函数自变量类型改为整型但因此也就丢掉了类型检查输入量有可能是其他无意义的整型量在运行时带来错误。
Qt引入QFlags类配合一组宏命令完美地解决了这个问题。
QFlags是一个简单的类可以装入一个枚举量并重载了与或非等运算符使得枚举量能进行与或非运算且运算结果还是一个QFlags包装的枚举量。一个普通的枚举类型包装成QFlags型需要使用Q_DECLARE_FLAGS宏在全局任意地方使用”|操作符计算自定义的枚举量需要使用Q_DECLARE_OPERATORS_FOR_FLAGS宏。 再看一段代码
class MyEnum : public QObject
{Q_OBJECT
public:explicit MyEnum(QObject *parent nullptr);enum Orientation{Up 1,Down 2,Left 4,Right 8,};Q_ENUM(Orientation) //如不使用Orientation可省略Q_DECLARE_FLAGS(OrientationFlags, Orientation)Q_FLAG(OrientationFlags)
};Q_DECLARE_OPERATORS_FOR_FLAGS(MyEnum::OrientationFlags)上面这段代码展示了使用Q_FLAG包装枚举定义的方法代码中Q_DECLARE_FLAGS(Flags, Enum)实际上被展开成typedef QFlags Enum Flags所以Q_DECLARE_FLAGS实际上是QFlags的定义式之后才能使用Q_FLAGFlags把定义的Flags注册到元对象系统。Q_FLAG完成的功能和Q_ENUM是类似的使得枚举量可以被QMetaEnum::fromType()调用。 看一下使用代码
qDebug()(MyEnum::Up|MyEnum::Down);
QMetaEnum m QMetaEnum::fromTypeMyEnum::OrientationFlags(); //since Qt5.5
qDebug() keyToValue:m.keyToValue(Up|Down);
qDebug() valueToKey:m.valueToKey(Up|Down);
qDebug() keysToValue:m.keysToValue(Up|Down);
qDebug() valueToKeys:m.valueToKeys(Up|Down)endl;qDebug() isFlag:m.isFlag();
qDebug() name:m.name();
qDebug() enumName:m.enumName(); //since Qt5.12
qDebug() scope:m.scope()endl;执行结果
QFlagsMyEnum::Orientation(Up|Down)
keyToValue: -1
valueToKey:
keysToValue: 3
valueToKeys: Up|Down isFlag: true
name: OrientationFlags
enumName: Orientation
scope: MyEnum 可以看到经过Q_FLAG包装之后QMetaEnum具有了操作复合枚举量的能力注意这时应当使用keysToValue()和valueToKeys()函数 取代之前的keyToValue()和valueToKey()函数。另外isFlag()函数返回值变成了truename()和enumName()分别返回Q_FLAG包装后和包装前的结构名。 实际上此时类中是存在两个结构体的如果在定义时加上了Q_ENUM(Orientation)则Orientation和OrientationFlags都能被QMetaEnum识别并使用只不过通常我们只关注Q_FLAG包装后的结构体。 这样我们顺便明白了Qt官方定义的许多枚举结构都是成对出现的原因比如
enum Qt::AlignmentFlag
flags Qt::Alignmentenum Qt::MatchFlag
flags Qt::MatchFlagsenum Qt::MouseButton
flags Qt::MouseButtons再总结下Q_FLAG以及Q_DECLARE_FLAGS、Q_DECLARE_OPERATORS_FOR_FLAGS使用的要点吧
Q_DECLARE_FLAGS(Flags, Enum)宏将普通结构体Enum重新定义成了一个可以自由进行与或非操作的安全的结构体Flags。Q_DECLARE_FLAG出现在Enum定义之后且定义之后Enum和Flags是同时存在的Q_DECLARE_OPERATORS_FOR_FLAGS(Flags)赋予了Flags一个全局操作符“|”没有这个宏语句Flags量之间进行与操作后的结果将是一个int值而不是Flags值。Q_DECLARE_OPERATORS_FOR_FLAGS应当定义在类外Q_DECLARE_OPERATORS_FOR_FLAGS只提供了“或”操作没有提供“与”“非”操作Q_DECLARE_FLAGS和Q_DECLARE_OPERATORS_FOR_FLAGS都是和元对象系统无关的可以脱离Q_FLAG单独使用事实上这两个宏在Qt4就已经存在不确定更早是否存在而Q_FLAG是在Qt5.5版本才加入的如果在我们的程序中不需要枚举变量的组合扩展那么只用简单的Q_ENUM就好了。
Q_NAMESPACE,Q_ENUM_NS和Q_FLAG_NS
在Qt5.8之后Qt引入了Q_NAMESPACE宏这个宏能够让命名空间具备简化的元对象能力但不支持信号槽类似类里的Q_GADGET。 在使用了Q_NAMESPACE的命名空间中可以使用Q_ENUM_NS和Q_FLAG_NS实现类中Q_ENUM和Q_FLAG的功能。 看一个例子
namespace MyNamespace
{
Q_NAMESPACE
enum Priority
{High 1,Low 2,VeryHigh 4,VeryLow 8,
};
Q_ENUM_NS(Priority) //如不使用Priority可省略
Q_DECLARE_FLAGS(Prioritys, Priority)
Q_FLAG_NS(Prioritys)
Q_DECLARE_OPERATORS_FOR_FLAGS(Prioritys)
}命名空间中Q_ENUM_NS和Q_FLAG_NS的使用和之前相类似不再赘述。Q_DECLARE_OPERATORS_FOR_FLAGS则需要定义在命名空间之内。 使用代码
using namespace MyNamespace;
qDebug()(High|Low);
QMetaEnum m QMetaEnum::fromTypeMyNamespace::Prioritys(); //since Qt5.5
qDebug() keyToValue:m.keyToValue(High|Low);
qDebug() valueToKey:m.valueToKey(High|Low);qDebug() keysToValue:m.keysToValue(High|Low);
qDebug() valueToKeys:m.valueToKeys(High|Low)endl;qDebug() isFlag:m.isFlag();
qDebug() name:m.name();
qDebug() enumName:m.enumName(); //since Qt5.12
qDebug() scope:m.scope()endl;运行结果
QFlagsMyNamespace::Priority(High|Low)
keyToValue: -1
valueToKey:
keysToValue: 3
valueToKeys: High|Low isFlag: true
name: Prioritys
enumName: Priority
scope: MyNamespace 可以看到从定义到使用和之前Q_FLAG几乎一模一样。 在命名空间中使用Q_ENUM_NS或者Q_FLAG_NS能让枚举结构体定义不再局限在类里使我们有更多的选择。另外在今后Qt的发展中相信Q_NAMESPACE能带来更多的功能我们拭目以待。
新旧对比
Qt一直是一个发展的框架不断有新特性加入使得Qt变得更易用。 本文介绍的内容都是在Qt5.5版本以后才引入的Q_NAMESPACE的内容甚至要到Qt5.8版本才引入在之前Qt中也存在着枚举量的扩展封装——主要是Q_ENUMS和Q_FLAGS这套系统虽然已经不建议使用但是为了兼容性还是予以保留。我们看看之前的系统如何使用的 枚举量定义基本一致就是Q_ENUMS(Enum)宏放到定义之前代码从略。 使用上
QMetaObject object MyEnum::staticMetaObject; //before Qt5.5
int index object.indexOfEnumerator(Orientation);
QMetaEnum m object.enumerator(index);对比改进后的
QMetaEnum m QMetaEnum::fromTypeMyEnum::Orientation(); //since Qt5.5不仅仅是3行代码简化成1行更重要的是Qt程序员终于不用再显式调用元对象QMetaObject了。改进的代码元对象机制同样在起着作用但却变得更加隐蔽更加沉默使得程序员可以把精力更多放到功能的实现上这大概就是Qt发展的方向。
Chapter2 【QT】枚举常用宏
原文链接https://blog.csdn.net/WL0616/article/details/131376253
Q_FLAG宏 1.1 Q_FLAG宏的作用 宏Q_FLAG会向元对象系统注册一个单一的标志类型。 使用宏Q_FLAG声明的枚举其枚举值可以作为标志并使用位或操作符(|)进行组合。
如果进行位或操作那上面的代码中枚举值就不能那样定义因为位或操作是按照二进制位进行“或运算”其枚举值的定义需要按照位来定义即不同的枚举值其二进制的每一位都不同。例如
enum Orientation {Up 0x01, //即0000...0001Down 0x02, //即0000...0010Left 0x04, //即0000...0100Right 0x08 //即0000...1000
};1.2 Q_DECLARE_FLAGS()宏的作用 Q_DECLARE_FLAGS(Flags, Enum)宏展开为 typedef QFlagsEnum Flags;QFlags是一个模板类其中Enum是枚举类型QFlags用于存储枚举值的组合。
传统的 C 编程中通常使用整数来保存 enum 的逻辑运算结果 (与、或、非、异或等)在进行逻辑运算的时候没有进行类型检查一个枚举类型可以和其他的枚举类型进行逻辑运算运算的结果可以直接传递给接收参数为整数的函数。
下面看一个例子 enum Orientation{Up 1, //即0000...0001Down 2, //即0000...0010Left 4, //即0000...0100Right 8 //即0000...1000};enum Direction{horizontal 1,vertical 2};这种操作编译器不会报错
Orientation::Up | Direction::horizontal; //两个不相关的枚举值做逻辑运算没有意义对于上面的问题应该怎么解决 Qt 中模板类 QFlags 提供了类型安全的方式保存 enum 的逻辑运算结果来解决上面的问题。
这种方式在 Qt 里很常见例如设置 QLabel 对齐方式的函数是 QLabel::setAlignment(Qt::Alignment) (typedef QFlagsQt::AlignmentFlag Qt::Alignment)这就意味着传给 setAlignment 的参数只能是枚举 Qt::AlignmentFlag 的变量、它们的逻辑运算结果或者 0如果传入其他的枚举类型或者非 0 值编译时就会报错例如
label-setAlignment(0); // OK
label-setAlignment(Qt::AlignLeft | Qt::AlignTop); // OKlabel-setAlignment(Qt::WA_Hover); // Error: 编译时报错总之Q_DECLARE_FLAGS(Flags, Enum)宏将普通结构体Enum重新定义成了一个可以自由进行位或操作的安全的结构体Flags。
1.3 Q_DECLARE_OPERATORS_FOR_FLAGS()宏的作用 Q_DECLARE_OPERATORS_FOR_FLAGS(Flags)赋予了Flags一个全局操作符“|”没有这个宏语句Flags量之间进行与操作后的结果将是一个int值而不是Flags值。这点特别重要。 Q_DECLARE_OPERATORS_FOR_FLAGS必须定义在类外。 Q_DECLARE_OPERATORS_FOR_FLAGS只提供了“或”操作没有提供“与”“非”操作。 Q_DECLARE_FLAGS和Q_DECLARE_OPERATORS_FOR_FLAGS都是和元对象系统无关的可以脱离Q_FLAG单独使用事实上这两个宏在Qt4就已经存在不确定更早是否存在而Q_FLAG是在Qt5.5版本才加入的。 1.4 演示代码
#include QDebug
#include QDialog
#include QMetaEnum
#include QMetaObjectclass MyEnum : public QDialog {Q_OBJECTpublic:enum Orientation {Up 0x01, //即0000...0001Down 0x02, //即0000...0010Left 0x04, //即0000...0100Right 0x08 //即0000...1000};Q_ENUM(Orientation)Q_DECLARE_FLAGS(Orientations, Orientation)Q_FLAG(Orientations)MyEnum(QWidget* parent 0);~MyEnum();
};Q_DECLARE_OPERATORS_FOR_FLAGS(MyEnum::Orientations)#include myenum.hMyEnum::MyEnum(QWidget* parent) :QDialog(parent) {QMetaEnum metaEnum QMetaEnum::fromTypeMyEnum::Orientation(); //通过静态函数fromType获取QMetaEnum对象QString name metaEnum.name(); //枚举名称int count metaEnum.keyCount(); //枚举数量QString keyIndex metaEnum.key(0); //下标为0的keyint valueIndex metaEnum.value(0); //下标为0的valueQString Key metaEnum.valueToKeys(MyEnum::Left | MyEnum::Right); //通过value得到keyint value metaEnum.keysToValue(Up | Down); //通过key得到valueqDebug() 枚举的名称 name;qDebug() 枚举的数量 QString::number(count);qDebug() index下标的key值 keyIndex;qDebug() index下标的Value值 QString::number(valueIndex);qDebug() value对应的key值 Key;qDebug() key值对应的Vaule QString::number(value);
}MyEnum::~MyEnum() {}Chapter3 Qt中自定义结构体、枚举型做信号参数传递
原文链接https://blog.csdn.net/ZefinNg/article/details/109171286
参考链接
如何在Qt信号和槽中使用枚举 https://cloud.tencent.com/developer/ask/sof/120786
问题
当自定义结构体、枚举通过信号的参数进行传递的时候运行以后可能会报错“QObject::connect: Cannot queue arguments of type ‘XXX’”此时信号与槽不一定会生效但是编译过程是没问题的。因此这样的问题比较麻烦应该尽力规避。
解决
出现这样的问题是由于自定义的结构体、枚举没有注册进qt的元对象系统因此无法识别。 在声明结构体和枚举后应使用Q_ENUM()宏进行注册再用qRegisterMetaType(“XXX”);进行注册。
示例
Communication.h如下
class Communication : public QObject
{Q_OBJECT
public:enum COMMUNICATION_METHOD{TCP_CONNECT 0,UDP_CONNECT,COM_CONNECT};enum CONNECT_TYPE {LONG_CONNECTION 0,SHORT_TCONNECTION};Q_ENUM(COMMUNICATION_METHOD)Q_ENUM(CONNECT_TYPE)explicit Communication(QObject *parent NULL);~Communication();
}Communication.cpp如下
Communication::Communication(QObject *parent) : QObject(parent)
{qRegisterMetaTypeCommunication::CONNECT_TYPE(Communication::CONNECTTYPE);qRegisterMetaTypeQAbstractSocket::SocketState(QAbstractSocket::SocketState);
}补充
为什么不使用Q_ENUMS()
关于Q_ENUMS()Qt5.14.2的Qt助手是这样描述的
This function is obsolete. It is provided to keep old source code working. We strongly advise against using it in new code.
This macro registers one or several enum types to the meta-object system.
If you want to register an enum that is declared in another class, the enum must be fully qualified with the name of the class defining it. In addition, the class defining the enum has to inherit QObject as well as declare the enum using Q_ENUMS().
In new code, you should prefer the use of the Q_ENUM() macro, which makes the type available also to the meta type system. For instance, QMetaEnum::fromType() will not work with types declared with Q_ENUMS().大意可翻译为
此功能已过时。 提供它是为了使旧的源代码正常工作。 我们强烈建议不要在新代码中使用它。
此宏将一种或几种枚举类型注册到元对象系统。
如果要注册在另一个类中声明的枚举则该枚举必须使用定义它的类的名称完全限定。 另外定义枚举的类必须继承QObject并使用Q_ENUMS()声明枚举。
在新代码中您应该更喜欢使用Q_ENUM()宏这会使该类型也可用于元类型系统。 例如QMetaEnum :: fromType()不适用于用Q_ENUMS()声明的类型。Chapter4 如何在Qt信号和槽中使用枚举
我在信号中使用enum类型时遇到了一些问题。基本上我有两个类一个状态机和一个处理状态机的线程。当状态改变时我想发送一个带有新状态的信号。我还希望使用enum来表示状态。在我的完整代码中状态机是在一个单独的共享库中实现的但是下面的代码给出了完全相同的错误。
当我运行代码时我得到了以下行为
kotteEMO-Ubuntu:sigenum $ ./sigenum
Object::connect: No such slot MyThread::onNewState(state)
Test signal
Test signal 我在我的示例代码四个文件:statemachine.h,statemachine.cpp,main.h和main.cpp.main函数只是启动线程,然后线程创建一个实例StateMachine并处理来自的线程StateMachine.我对Qt很陌生,所以当我意识到你必须将enum包含在内Q_ENUMS并用类型系统注册它时,我有点困惑.所以我完全有可能犯了一些菜鸟错误
下面的代码有点长,但我希望它与我的真实代码尽可能相似.
statemachine.h 好像:
// statemachine.h
#ifndef _STATEMACHINE_H
#define _STATEMACHINE_H#include QtCoreclass StateMachine : public QObject
{Q_OBJECTQ_ENUMS(state)public:enum state {S0, S1, S2};void setState(state newState);signals:void stateChanged(state newState);void testSignal(void);
};Q_DECLARE_METATYPE(StateMachine::state);#endif并且它被实现为
// statemachine.cpp
#include QtCore#include statemachine.hvoid StateMachine::setState(state newState)
{emit stateChanged(newState);emit testSignal();
}该线程被定义为
// main.h
#ifndef _MAIN_H
#define _MAIN_H#include QtCore#include statemachine.hclass MyThread : public QThread
{Q_OBJECTprivate:void run(void);private slots:void onNewState(StateMachine::state);void onTestSignal(void);private:StateMachine *myStateMachine;
};#endif其实现方式如下
// main.cpp
#include QtCore
#include QApplication#include statemachine.h
#include main.hvoid MyThread::run()
{myStateMachine new StateMachine();qRegisterMetaTypeStateMachine::state(state);// This does not workconnect(myStateMachine, SIGNAL(stateChanged(state)),this, SLOT(onNewState(state)));// But this does...connect(myStateMachine, SIGNAL(testSignal()),this, SLOT(onTestSignal()));forever {// ...myStateMachine-setState(StateMachine::S0);}
}void MyThread::onTestSignal()
{qDebug() Test signal;
}void MyThread::onNewState(StateMachine::state newState)
{qDebug() New state is: newState;
}Chapter5 个人总结(2023-10)
user.h
#ifndef USER_H
#define USER_H#include QObjectclass User : public QObject
{Q_OBJECT
public:explicit User(QObject *parent nullptr);~User();enum Authorization { //增加用户权限枚举类型USER表示操作员ADMIN表示管理员SUPPER_ADMIN表示超级管理员USER 1,ADMIN 2,SUPPER_ADMIN 3};Q_ENUM(Authorization)Q_DECLARE_FLAGS(AuthorizationFlags, Authorization)Q_FLAG(AuthorizationFlags)public:static User* getHandle();void init();User::Authorization getAuthorization(); //获取当前用户权限void setAuthorization(User::Authorization authorization);signals:private:static User* handle;QString filePath;int level_Admin;int level_SuperAdmin;QString admin_Passwd;QString superAdmin_Passwd;User::Authorization m_authorization; //用户权限
};Q_DECLARE_OPERATORS_FOR_FLAGS(User::AuthorizationFlags)Q_DECLARE_METATYPE(User::Authorization);#endif // USER_H
user.cpp
注意在类的构造函数中加入qRegisterMetaTypeUser::Authorization(“User::Authorization”); //向Qt元数据系统注册枚举类型否则无法使用信号槽传递枚举参数
#include user.hUser* User::handle nullptr;User::User(QObject *parent) : QObject(parent)
{qRegisterMetaTypeUser::Authorization(User::Authorization); //向Qt元数据系统注册枚举类型否则无法使用信号槽传递枚举参数this-filePath ConfigPath(user.json);this-m_authorization User::Authorization::USER; //默认是操作员权限
}User::~User()
{}User *User::getHandle()
{if(handle nullptr){handle new User();}return handle;
}void User::init()
{if(!FileExists(filePath)){
// create();}
// load();
}void User::create()
{this-level_Admin 1;this-level_SuperAdmin 2;this-admin_Passwd 123456;this-superAdmin_Passwd 112233;save();
}void User::load()
{}void User::save()
{}User::Authorization User::getAuthorization()
{return this-m_authorization;
}void User::setAuthorization(Authorization authorization)
{this-m_authorization authorization;
}
void LoginDlg::on_btn_Login_clicked()
{if(ui-lineEdit-text().isEmpty()) //如果密码输入为空则执行关闭命令{this-on_btn_Close_clicked();}else{this-passwdInput ui-lineEdit-text().toLatin1(); //获取用户密码this-level ui-comboBox-currentIndex(); //获取用户级别if(this-passwdInput tr(123456)){User::getHandle()-setAuthorization(User::Authorization::ADMIN);}else if(this-passwdInput tr(112233)){User::getHandle()-setAuthorization(User::Authorization::SUPPER_ADMIN);}else{User::getHandle()-setAuthorization(User::Authorization::USER);}ui-lineEdit-clear();this-accept();}}