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

来源:互联网 发布:欧文赛季数据统计 编辑:程序博客网 时间:2024/05/16 13:03

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


主要实现2点:

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

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


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

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


这个视图的QML代码如下:

import QtQuick 2.5import QtQuick.Window 2.2import QtQuick.Controls 1.4import QtQuick.Layouts 1.1import QtQuick.Controls.Styles 1.4Window{    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_OBJECTprivate:    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)

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















0 0
原创粉丝点击