QML界面与Qt/C++代码进行数据交互

QML界面与Qt/C++代码进行数据交互


主要实现2点:

     1,c++ 数据传递到QML界面使用

2,QML界面的数据传递到c++代码使用


为了方便说明,我使用QML创建了一个ListView视图,用于展示商品名字和价格(name, value)。

一开始的时候这个界面没有任何数据,截图如下:


这个视图的QML代码如下:

import QtQuick 2.5
import QtQuick.Window 2.2
import QtQuick.Controls 1.4
import QtQuick.Layouts 1.1
import QtQuick.Controls.Styles 1.4

Window
{
    id: mainWindow
    width: 600
    height: 300
    visible: true
    property var myModel: ""
    signal printMyModel(var model)
    signal printItem(var item)

    //list view
    ListView
    {
        id: view
        anchors.fill: parent

        header: myHeader
        footer: myFooter

        model: myModel
        delegate: myDelegate
    }

    //header, 被双击的时候发送打印myModel信号
    Component
    {
        id: myHeader
        Rectangle
        {
            implicitHeight: 25
            implicitWidth: view.width
            color: "gray"

            Text
            {
                anchors.centerIn: parent
                text: "示例所用的ListView"
                color: "darkblue"
            }

            MouseArea
            {
                anchors.fill: parent
                onDoubleClicked: printMyModel(myModel)
            }
        }
    }

    //footer, 被双击的时候发送打印myModel信号
    Component
    {
        id: myFooter
        Rectangle
        {
            implicitHeight: 25
            implicitWidth: view.width
            color: "lightblue"

            Text
            {
                anchors.right: parent.right
                anchors.rightMargin: 20
                anchors.verticalCenter: parent.verticalCenter
                text: "created by Eosin_Sky"
                color: "gray"
            }

            MouseArea
            {
                anchors.fill: parent
                onDoubleClicked: printMyModel(myModel)
            }
        }
    }

    //delegate, 被双击的时候发送打印item信号
    Component
    {
        id: myDelegate
        Rectangle // container
        {
            id: container
            implicitHeight: 25
            implicitWidth: view.width
            color: index %2 == 0 ? "darkgray" : "lightblue"

            RowLayout //layout
            {
                anchors.top: parent.top
                anchors.bottom: parent.bottom
                anchors.left: parent.left
                anchors.leftMargin: 20
                anchors.right: parent.right
                anchors.rightMargin: 20


                Rectangle //name
                {
                    implicitWidth: name.width
                    Layout.fillHeight: true
                    color: container.color
                    Text
                    {
                        id: name
                        anchors.centerIn: parent
                        text: modelData.name
                    }
                }

                //spacer
                Rectangle
                {
                    Layout.fillWidth: true
                    Layout.fillHeight: true
                    Layout.topMargin: 2
                    Layout.bottomMargin: 2
                    color: Qt.darker(container.color)
                    opacity: 0.7

                    Text
                    {
                        anchors.centerIn: parent
                        text:  "点击打印该条目"
                    }

                    MouseArea
                    {
                        anchors.fill: parent
                        onDoubleClicked: printItem(myModel[index])
                    }
                }

                Rectangle //value
                {
                    implicitWidth: value.width
                    implicitHeight: value.height

                    TextField
                    {
                        id: value
                        anchors.centerIn: parent
                        height: 20
                        text: modelData.value
                        validator: DoubleValidator{bottom: 0.01;top: 9999.99; decimals: 2;}

                        style:TextFieldStyle
                        {
                            background:Rectangle
                            {
                                border.width: 1
                                border.color: Qt.darker(color)
                                color: Qt.darker(container.color)
                            }
                        }


                    }
                }

                Rectangle //¥
                {
                    implicitWidth: yuan.width
                    Layout.fillHeight: true
                    color: container.color
                    Text
                    {
                        id: yuan
                        anchors.centerIn: parent
                        text: "¥"
                    }
                }
            }
        }
    }
}

其中mainWindow中定义的var类型的myModel就是用于给ListView提供数据的。 当点击ListView的Header和Footer

的时候会发送打印myModel的信号,这时候使用c++将数据打印出来;当点击ListView的条目的时候会发送打印item

的信号,这时候使用c++将这个条目打印出来。


现在这个ListView是空的,因为一开始myModel是空的。我们准备使用c++将数据设置给myModel。

首先我们先实现一个类(MyQmlGUI)用来控制这个mainWindow,代码如下:

#ifndef MYQMLGUI_H
#define MYQMLGUI_H

#include <QJSEngine>
#include <QJSValue>
#include <QDebug>

class MyQmlGUI: public QObject
{
    Q_OBJECT
private:
    QObject* qmlRoot;
public:
    MyQmlGUI(QObject* root):qmlRoot(root)
    {
        connect(qmlRoot, SIGNAL(printMyModel(QVariant)), this, SLOT(printModel(QVariant)));
        connect(qmlRoot, SIGNAL(printItem(QVariant)), this, SLOT(printItem(QVariant)));
    }

public slots:
    void initModel()
    {
        /** create 3 items for list view (name - value) **/
        int rowCount = 3;
        QJSEngine JS;
        QJSValue array = JS.newArray(rowCount);

        for(int i = 0; i < 3; i++)
        {
            QJSValue item = JS.newObject();
            item.setProperty("name", "goods " + QString::number(i));
            item.setProperty("value", i * 3);
            array.setProperty(i, item);
        }

        /** update model to qml object **/
        qmlRoot->setProperty("myModel", array.toVariant());
    }

    void printModel(QVariant model)
    {
        qDebug() << "print model:";

        /** this model is an Array **/
        QJSValue array = model.value<QJSValue>();
        int rowCount = array.property("length").toInt();
        for(int i = 0; i < rowCount; i++)
        {
            QString name = array.property(i).property("name").toString();
            QString value = array.property(i).property("value").toString();
            qDebug() << "row at " << i << ":" << "name=" << name << ", value=" << value;
        }
    }

    void printItem(QVariant item)
    {
        /** this item is a js object **/
        QJSValue obj = item.value<QJSValue>();
        QString name = obj.property("name").toString();
        QString value = obj.property("value").toString();
        qDebug() << "print item:" << "name=" << name << ", value=" << value;
    }
};

#endif // MYQMLGUI_H

这个类在实例化的时候会将传入的mainWindow对象进行信号绑定,printModel槽会绑定mainWindow

的printMyModel信号;printItem槽会绑定mainWindow的printItem信号。


然后这个类实现了一个InitModel的方法,当被调用的时候会生成ListView所需要的Model并设置到mainWindow

中的myModel中去。


我们来启动一下:

QQmlEngine engine;
QQmlComponent component(&engine);

component.loadUrl(QUrl::fromLocalFile("D:/QtProject/DataExchange/main.qml"));
if(!component.isReady())
   return -1;

QQuickWindow* mainWindow = qobject_cast<QQuickWindow*>(component.create());
if(mainWindow == NULL){
   return -2;
}

mainWindow->show();

MyQmlGUI gui(mainWindow);
gui.initModel();


当mainWindow显示的 时候初始化gui并调用gui的initModel。

得到界面如图:



现在点击Header或者是Footer可以看到std out 输出内容:



点击单个条目可以看到如下的输出内容:



至此,我们的QML界面与Qt/c++ 代码进行的数据交互就结束了。


原理:

QML中能处理JS的数据类型,Qt中也能处理JS的数据类型(QJSValue & QJSEngine)

当然,除了这种方式还有其他方式。欢迎交流!















  • 7
    点赞
  • 35
    收藏
    觉得还不错? 一键收藏
  • 3
    评论
Qt是一个跨平台的C++应用程序开发框架,而QMLQt中的一种声明式语言,用于构建用户界面QML可以与Qt进行数据交互,具体的方法如下。 首先,我们需要在Qt中定义C++类型的变量或者对象,并将其暴露给QML使用。这可以通过使用QObject的派生类来实现,将类对象注册到QML引擎中。 其次,在QML中,我们可以引用这些已经注册的C++对象或者变量,从而与之进行数据交互。可以使用信号和槽机制来实现数据的传递和处理。 比如,假设我们在Qt中定义了一个名为MyData的类,该类有一个属性message,我们可以将其暴露给QML使用: ```cpp class MyData : public QObject { Q_OBJECT Q_PROPERTY(QString message READ message WRITE setMessage NOTIFY messageChanged) public: QString message() const; void setMessage(const QString& msg); signals: void messageChanged(); }; ``` 然后,在Qt中,我们将这个类对象注册到QML引擎中: ```cpp qmlRegisterType<MyData>("com.example", 1, 0, "MyData"); ``` 接下来,我们可以在QML中使用这个已经注册的C++对象: ```qml import com.example 1.0 MyData { id: myObject message: "Hello World" } Text { text: myObject.message } ``` 这样,我们就可以在QML中使用myObject对象的属性message,并将其显示在Text组件上。当myObject对象的属性发生改变时,Text组件也会相应地更新。 另外,我们还可以在QML中发射C++对象的信号,然后在Qt中捕获这些信号,进行相应的处理。 总之,QMLQt数据交互主要通过在Qt中注册C++对象,并在QML中引用这些对象来实现。这样,我们可以方便地在QML中使用Qt提供的各种功能,并实现复杂的交互逻辑。
评论 3
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值