QML 使用QtObject定义私有变量

学习过qml的都知道,在qml中是无法定义“私有变量”的;

在自定义的控件内部定义的变量,在调用者外部是可以被使用,这不符合某些情况下的项目需求,那么该如何取巧的解决这个问题呢?

有的,可通过QtObject控件实现。

官方文档介绍:

Detailed Description

The QtObject type is a non-visual element which contains only the objectName property.

It can be useful to create a QtObject if you need an extremely lightweight type to enclose a set of custom properties.

案例场景:

首先我们新建一个MyRectangle.qml文件,在文件内实现一个自定义的简易的Rectangle控件;

内部有定义变量供外部调用者使用;如下:

// MyRectangle.qml
import QtQuick 2.0

Rectangle {
    id: borderRect
    property int innerTopMargin: 1        // 上边距
    property int innerBottomMargin: 1     // 下边距
    property int innerLeftMargin: 1       // 左边距
    property int innerRightMargin: 1      // 右边距
    property string innerColor: "white"   // 矩形颜色
    property string bodercolor: "black"   // 边框颜色

    width: 100
    height: 50
    color: bodercolor


    Rectangle {
        id: innerRect
        color: innerColor
        z:1

        anchors.fill: parent    // 填充满父类
        anchors.topMargin: innerTopMargin
        anchors.bottomMargin: innerBottomMargin
        anchors.leftMargin: innerLeftMargin
        anchors.rightMargin: innerRightMargin
    }
}

然后在main.qml文件内可以直接使用:

import QtQuick 2.9
import QtQuick.Window 2.2
import QtQuick.Controls 2.14

Window {
    id: root
    visible: true
    width: SCREEN_WIDTH
    height: 500
    title: qsTr("Hello World")
    color: "white"

    MyRectangle {
        x: 100
        y: 200
        width: 300
        height: 200

        // 可以在调用者外部直接使用内部定义变量
        innerColor: "yellow"
    }
}

可以看到,在外部,即调用者处,直接使用了innerColor变量对矩形的颜色做了修改;

假设我们不希望矩形的内部的颜色被修改,那么,就得将innerColor变量设置为“私有变量”;这时候,QtObject就排上用用场。

在MyRectangle.qml文件内,定义QtObject控件,并将innerColor变量的定义放入到QtObject控件内。

// MyRectangle.qml
// 可通过定义QtObject控件,在控件内部定义变量,从而实现私有变量的效果                   
QtObject {                                                 
    id: attributes                                         
    property string innerColor: "white"   // 矩形颜色          
}                                                         

此时,在调用者处,已经发生了报错:

当然,其他的变量还是可以正常使用的,例如将矩形的边框颜色修改为红色(bodercolor: "red"),然后注释掉报错代码,(// innerColor: "yellow"),运行截图:

那么,在MyRectangle.qml文件内如何使用QtObject内定义的变量呢?

其实,可以直接使用QtObject的id值去使用到其内部定义的变量!

例如,在自定义控件MyRectangle被构建之后,使用QtObject的id值调用innerColor,将矩形背景颜色修改为灰色;

// MyRectangle.qml
// 在QtObject外部如果需要使用,则可以使用id直接使用
Component.onCompleted: {
    attributes.innerColor = "gray"  // 修改矩形颜色为灰色
    console.log("innerColor:", attributes.innerColor);
}

可以看出,在MyRectangle.qml文件内,我们使用attributes.innerColor确实可以对在QtObject内定义的变量做修改;而且在调用者处,也确实是修改不了innerColor变量了,innerColor实际上变成了“私有变量”。

如果说,期望在调用者处也能使用innerColor变量,这该如何处理呢?

还是有一个办法,将id值attributes通过别名方式暴露给外部使用!

在MyRectangle.qml文件内,给attributes定义别名:

// 可通过别名的方式给外部提供内部变量的父id,就可以外部使用到内部的变量的
property alias attr: attributes        

那么在调用者处,就可以直接使用attr调用到innerColor变量了;

import QtQuick 2.9
import QtQuick.Window 2.2
import QtQuick.Controls 2.14

Window {
    id: root
    visible: true
    width: SCREEN_WIDTH
    height: 500
    title: qsTr("Hello World")
    color: "white"

    MyRectangle {
        x: 100
        y: 200
        width: 300
        height: 200

        // 可以在调用者外部直接使用内部定义变量
//        innerColor: "yellow"
        bodercolor: "red"

        // 通过别名方式可使用内部的变量
        Component.onCompleted: {
            attr.innerColor = "green"    // 修改矩形颜色为绿色
            console.log("innerColor:", attr.innerColor);
        }
    }
}

通过使用别名方式,真的就使用到了innerColor变量了。

上述就是介绍了在qml中如何定义“私有变量”的全部过程,通过使用QtObject可以取巧定义到“私有变量”,因为qml本身并不支持定义私有变量。

最后附上MyRectangle.qml文件全部代码:

import QtQuick 2.0

Rectangle {
    id: borderRect
    property int innerTopMargin: 1        // 上边距
    property int innerBottomMargin: 1     // 下边距
    property int innerLeftMargin: 1       // 左边距
    property int innerRightMargin: 1      // 右边距

    property string bodercolor: "black"   // 边框颜色

    width: 100
    height: 50
    color: bodercolor

    // 可通过别名的方式给外部提供内部变量的父id,就可以外部使用到内部的变量的
    property alias attr: attributes



    Rectangle {
        id: innerRect
        color: attributes.innerColor
        z:1

        anchors.fill: parent    // 填充满父类
        anchors.topMargin: innerTopMargin
        anchors.bottomMargin: innerBottomMargin
        anchors.leftMargin: innerLeftMargin
        anchors.rightMargin: innerRightMargin
    }

    // 可通过定义QtObject控件,在控件内部定义变量,从而实现私有变量的效果
    QtObject {
        id: attributes
        property string innerColor: "white"   // 矩形颜色
    }

    // 在QtObject外部如果需要使用,则可以使用id直接使用
    Component.onCompleted: {
        attributes.innerColor = "gray"  // 修改矩形颜色为灰色
        console.log("innerColor:", attributes.innerColor);
    }
}
Qt中,可以使用信号和槽机制来将二维数组传递给QML界面。这里我们可以使用QVariantList和QVariantMap来实现。 下面是一个示例,其中包含一个QObject派生类,该类存储一个二维数组,并通过信号将它传递给QML。在QML中,可以使用JavaScript来访问这个二维数组。 C++代码: ```cpp #include <QObject> #include <QVariant> #include <QVariantList> #include <QVariantMap> class MyObject : public QObject { Q_OBJECT Q_PROPERTY(QVariantList data READ getData NOTIFY dataChanged) public: explicit MyObject(QObject *parent = nullptr); QVariantList getData() const; signals: void dataChanged(); private: QVector<QVector<int>> m_data; }; ``` 在MyObject类中,我们定义了一个QVector<QVector<int>>类型的私有成员变量m_data,其存储了一个二维数组。getData()函数将二维数组转换为QVariantList类型,并返回给QML界面。 ```cpp QVariantList MyObject::getData() const { QVariantList list; for (int i = 0; i < m_data.size(); i++) { const QVector<int> &row = m_data.at(i); QVariantList rowList; for (int j = 0; j < row.size(); j++) { rowList.append(row.at(j)); } list.append(rowList); } return list; } ``` 接下来,我们在MyObject类中定义了一个名为dataChanged()的信号,它将在二维数组发生变化时发射。 ```cpp signals: void dataChanged(); ``` 在MyObject类中,我们定义了一个名为setData()的槽函数,它将接受一个QVariantList类型的参数,并将其转换为二维数组,然后将其存储到m_data变量中,并发射dataChanged()信号。 ```cpp public slots: void setData(const QVariantList &data) { m_data.clear(); for (int i = 0; i < data.size(); i++) { QVariantList rowList = data.at(i).toList(); QVector<int> row; for (int j = 0; j < rowList.size(); j++) { row.append(rowList.at(j).toInt()); } m_data.append(row); } emit dataChanged(); } ``` 在QML界面中,我们可以通过连接MyObject类的dataChanged()信号来接收二维数组的变化。 ```qml import QtQuick 2.0 import MyModule 1.0 Item { MyObject { id: myObject } Component.onCompleted: { myObject.setData([ [1, 2, 3], [4, 5, 6], [7, 8, 9] ]); } Connections { target: myObject onDataChanged: { var data = myObject.data; console.log(data); // 输出 QVariantList for (var i = 0; i < data.length; i++) { var row = data[i]; for (var j = 0; j < row.length; j++) { var value = row[j]; console.log(value); } } } } } ``` 在QML界面中,我们可以使用setData()函数来设置二维数组的值。当二维数组发生变化时,dataChanged()信号将被发射,并执行Connections中的onDataChanged()函数。在onDataChanged()函数中,我们可以使用JavaScript来访问二维数组。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

打赏作者

cpp_learners

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

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

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

打赏作者

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

抵扣说明:

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

余额充值