QML和C ++之间的数据类型转换---枚举

前言

众所周知,如果要在 QML使用 C++中定义的类型,有些数据类型是是可以直接使用的,如常见的 int,但是还有一些相对特殊的类型就需要做些特定的操作才可以使用了,那么,这里来看一下如何在 QML 中使用 C++中定义的枚举类型。

正文

1

要将自定义枚举用作数据类型,必须注册其类,并且还必须使用Q_ENUM()声明枚举,以将其注册到Qt的元对象系统。
话不多说,直接上代码:

首先我们定义一个类,继承于 QObject,然后在类中定义一个枚举类型

#include <QObject>

class Message : public QObject
{
    Q_OBJECT
    Q_PROPERTY(Status status READ getStatus WRITE setStatus NOTIFY sigStatusChanged)
public:
    explicit Message(QObject *parent = nullptr);

    enum Status{
       Ready,
       Loading,
       Finished
    };
    Q_ENUM(Status)

    Status getStatus() const{return m_status;}
    void setStatus(Status st){
        m_status = st;
        emit sigStatusChanged(st);
    }

signals:
    void sigStatusChanged(Status st);

private:
    Status m_status;
};

然后将 Message 类注册成 QML 可使用的类型:

qmlRegisterType<Message>("Message",1,0,"Message");

然后在 QML 中直接进行调用:

import QtQuick 2.9
import QtQuick.Window 2.2
import QtQuick.Controls 2.2
import QtQuick.Layouts 1.3
import Message 1.0

Window {
    visible: true
    width: 640
    height: 480
    title: qsTr("Hello World")

    Message{
        id:msg
        onSigStatusChanged: {
            console.log("status = ",st)
        }
    }

    Row{
        anchors.centerIn: parent
        Button{
            text: "Ready"
            onClicked: {
                console.log("Ready btn clicked")
                msg.status = Message.Ready
            }
        }
        Button{
            text: "Loading"
            onClicked: {
                console.log("Loading btn clicked")
                msg.status = Message.Loading
            }
        }
        Button{
            text: "Finished"
            onClicked: {
                console.log("Finished btn clicked")
                msg.status = Message.Finished
            }
        }

    }

}

为方便演示,我这里定义了三个按钮,点击每个按钮切换可以分别设置 status,然后在 QML 中查看打印信息,看是否为我们想要的结果。

代码跑起来:

输出打印信息:

qml: Ready btn clicked
qml: status =  0
qml: Loading btn clicked
qml: status =  1
qml: Finished btn clicked
qml: status =  2

通过打印信息可以看到,当前 status 已经发生了变化。
以上是最基本的枚举使用方法。
注意:枚举值的名称必须以大写字母开头,以便可以从QML访问。

2

定义枚举时,还有一种写法,如下:

enum class Status{
       Ready,
       Loading,
       Finished
    };
    Q_ENUM(Status)

就是在枚举名前面加一个class,这叫枚举类,枚举类QML中注册为范围和非范围属性。该Ready值将在Message.Status.Ready和注册Message.Ready。
所以如果这种写法就可以直接在 QML 中通过Message.Status.Ready来调用了。

3

上面说到的枚举类的用途通常是,当有多个枚举定义时,并每个枚举值的名称如果有重复,如 A 枚举中的值是 value1,value2,而枚举 B 里面也包含value1,value2两个值,这时候就需要用到枚举类,要不然会报错。

定义为枚举类后,如果直接通过类名获取枚举值,那么在后面定义的值将会替换前面定义的枚举值。来看个示例:

#include <QObject>

class Message : public QObject
{
    Q_OBJECT
public:
    explicit Message(QObject *parent = nullptr);

    enum class Status{
       Ready= 0,
       Loading,
       Finished
    };
    enum class StatusTwo{
        Ready = 4,
        Loading,
        Finished
    };
    Q_ENUM(Status)
    Q_ENUM(StatusTwo)
};

这里定义了两个枚举,其枚举成员的名称是一样的,这时候如果直接通过Message.Ready来引用,结果将为4,如下:

Window {
    visible: true
    width: 640
    height: 480
    title: qsTr("Hello World")

    Message{
        id:msg
        Component.onCompleted: {
            console.log("Message.Ready=",Message.Ready)
            console.log("Message.Loading=",Message.Loading)
            console.log("Message.Finished=",Message.Finished)
            
            console.log("Message.Status.Ready=",Message.Status.Ready)
            console.log("Message.Status.Loading=",Message.Status.Loading)
            console.log("Message.Status.Finished=",Message.Status.Finished)
            
            console.log("Message.StatusTwo.Ready=",Message.StatusTwo.Ready)
            console.log("Message.StatusTwo.Loading=",Message.StatusTwo.Loading)
            console.log("Message.StatusTwo.Finished=",Message.StatusTwo.Finished)
        }
    }
}

输出结果:

qml: Message.Ready= 4
qml: Message.Loading= 5
qml: Message.Finished= 6

qml: Message.Status.Ready= 0
qml: Message.Status.Loading= 1
qml: Message.Status.Finished= 2

qml: Message.StatusTwo.Ready= 4
qml: Message.StatusTwo.Loading= 5
qml: Message.StatusTwo.Finished= 6

结果很明显,只有通过枚举类的方式来调用才能得到正确的值。

4

若想在 QML 中定义信号,并且信号是带枚举类型参数的,那么定义信号的参数可以直接写成 int 类型,如下

Message{
        id:msg
        signal sigSendStatus(int status)
        Component.onCompleted: {
            sigSendStatus(Message.Ready)
        }
    }

OK,关于 QML 中使用 C++定义的枚举类型介绍就到这里。
上述的两份源码在这里

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

luoyayun361

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值