您的位置:首页 > 编程语言 > Qt开发

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

2017-05-04 11:06 519 查看
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)

当然,除了这种方式还有其他方式。欢迎交流!
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: 
相关文章推荐