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

版权声明:本文为博主原创文章,未经博主允许不得转载。 https://blog.csdn.net/r5014/article/details/71159279

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)

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















猜你喜欢

转载自blog.csdn.net/r5014/article/details/71159279