好吧,我正在学习使用QML,我有一个疑问。在我的例子中,我有一个ListModel和QML的ListElements,我有一个带有矩形,PathView等的QML主文件。
我也有一个QWidget,而不是我的主窗口。在这个QWidget中,我将QML UI包含在一个组件中。 OK!
如何使用C ++处理QML ListElements?
注意:当我说“处理”时,我想说例如包含一个元素。
以下是我的代码的一些部分......
包含我的ListElement的QML,名为“Menu1”:
import QtQuick 1.0
ListModel {
id: listMovieModel
ListElement { name: "Image 1"; iconSource: "pics/image_1.jpg" }
ListElement { name: "Image 2"; iconSource: "pics/image_2.jpg" }
ListElement { name: "Image 3"; iconSource: "pics/image_3.jpg" }
ListElement { name: "Image 4"; iconSource: "pics/image_4.jpg" }
ListElement { name: "Image 5"; iconSource: "pics/image_5.jpg" }
ListElement { name: "Image 6"; iconSource: "pics/image_6.jpg" }
}
我的主要QML:
Rectangle {
width: 500
height: 600
color: "transparent"
PathView {
id: view
focus: true
width: parent.width
height: parent.height + y
y: -150
model: Menu1 {} //First QML showed
delegate: Image {
source: iconSource
width: 64
height: 90
scale: PathView.isCurrentItem ? 3.5 * y / parent.height : 2.0 * y / parent.height
z: y
smooth: true
}
path: MyGeometricFigure { //This a another file, but is confidential
width: view.width
height: view.height
}
preferredHighlightBegin: 0
preferredHighlightEnd: 0
highlightRangeMode: PathView.StrictlyEnforceRange
Keys.onLeftPressed: decrementCurrentIndex()
Keys.onRightPressed: incrementCurrentIndex()
}
}
因为我像我的QWidget一样使用QML:
MainForm::MainForm(QWidget *parent) :
QWidget(parent),
ui(new Ui::MainForm)
{
ui->setupUi(this);
this->resize(1024, 576);
QDeclarativeView *myQMLTest = new QDeclarativeView(QUrl::fromLocalFile("myMainQML.qml"));
myQMLTest->setStyleSheet(QString("background: transparent; width: 600px"));
this->ui->frameListVideoGallery->layout()->addWidget(myQMLTest);
myQMLTest->setFocus();
myQMLTest->installEventFilter(this);
}
我看到了一些关于此的文章,但我无法使用C ++更改我的LisModel。我在这里看到了http://doc.qt.nokia.com/4.7/qdeclarativemodels.html#c-data-models,这里是使用PathView http://doc.qt.nokia.com/4.7/qdeclarativeexamples.html
的示例有人可以帮助我吗?
谢谢!
答案 0 :(得分:8)
好的。我想你可以这样做:
在主要的QML文件中添加简单的功能。
Rectangle {
// ...
function append(newElement) {
view.model.append(newElement)
}
PathView {
id: view
// ...
model: Menu1 {} //First QML showed
// ...
}
}
此方法只会从ListModel调用相应的方法。您可以使用更多支持的方法find there。
然后您只需要从C ++代码调用此方法。你可以这样做:
MainForm::MainForm(QWidget *parent) :
QWidget(parent),
ui(new Ui::MainForm)
{
ui->setupUi(this);
this->resize(1024, 576);
QDeclarativeView *myQMLTest = new QDeclarativeView(QUrl::fromLocalFile ("myMainQML.qml"));
myQMLTest->setStyleSheet(QString("background: transparent; width: 600px"));
QVariantMap newElement; // QVariantMap will implicitly translates into JS-object
newElement.insert("name", "Image 13" );
newElement.insert("iconSource", "pics/image_13.jpg");
QMetaObject::invokeMethod(
myQMLTest->rootObject(), // for this object we will call method
"append", // actually, name of the method to call
Q_ARG(QVariant, QVariant::fromValue(newElement)) // method parameter
);
this->ui->frameListVideoGallery->layout()->addWidget(myQMLTest);
myQMLTest->setFocus();
myQMLTest->installEventFilter(this);
}
您应该查看this以获取更多信息。
您还可以选择另一种方法:通过qml属性传递一些数据(使用QDeclarativeEngine和QDeclarativeContext),然后在JavaScript代码中处理这些数据和列表模型。
答案 1 :(得分:1)
我想让@GooRoo的答案对Qt初学者更加完整/有用。如果您使用Qt Creator,您将使用QmlApplicationViewer从模板开始。要应用GooRoo的答案,你必须做这样的事情(感谢http://www.lothlorien.com/kf6gpe/?p=309):
CPP:
Q_DECL_EXPORT int main(int argc, char *argv[])
{
QScopedPointer<QApplication> app(createApplication(argc, argv));
QScopedPointer<QmlApplicationViewer> viewer(QmlApplicationViewer::create());
viewer->setOrientation(QmlApplicationViewer::ScreenOrientationAuto);
viewer->setMainQmlFile(QLatin1String("qml/mydemo/main.qml"));
viewer->showExpanded();
QMetaObject::invokeMethod(
(QObject *)viewer->rootObject()->findChild<QObject *>("myModel"), // QML item
"test" // name of the method to call
// without parameters
);
return app->exec();
}
QML:
PageStackWindow {
id: mainApp
...
ListModel {
id: myModel
objectName: myModel //THIS IS NEEDED BY findChild()
...
function test() {
console.log("TEST OK");
}
}
Page {
...
}
}
答案 2 :(得分:0)
这是从C ++在QML TableView中填充数据的另一个完整示例。 请原谅错误的变量名。我只是出于测试目的而制作它。
我使用了QVariantList
,并用QVariantMap
个对象填充了它。
在这里,通过将QML表的两列(即what
和session_name
中的for循环中填充了多个数据,方法是将它们放入QVariantMap
中,然后插入{{ 1}}在QVariantMap
中。
HH.h
QVariantList
在这里,我已经使用#ifndef HH_H
#define HH_H
#include <QVariant>
class AA : public QObject
{
Q_OBJECT
QVariantList m_gname;
public:
Q_PROPERTY(QVariantList gname READ gname WRITE setGname NOTIFY gnameChanged)
AA()
{
QVariantList q;
for(int i = 0; i < 10; i++)
{
QVariantMap p;
p.insert("what", "qq");
p.insert("session_name", "aa");
q.push_back(p);
}
setGname(q);
}
QVariantList gname() const
{
return m_gname;
}
public slots:
void setGname(QVariantList gname)
{
if (m_gname == gname)
return;
m_gname = gname;
emit gnameChanged(m_gname);
}
signals:
void gnameChanged(QVariantList gname);
};
#endif // HH_H
注册了我在上面创建的类qmlRegisterType
。
main.cpp
AA
在QML中,我通过#include <QGuiApplication>
#include <QQmlApplicationEngine>
#include "HH.h"
int main(int argc, char *argv[])
{
QCoreApplication::setAttribute(Qt::AA_EnableHighDpiScaling);
QGuiApplication app(argc, argv);
qmlRegisterType<AA>("ZZZ", 1, 0, "AA");
QQmlApplicationEngine engine;
const QUrl url(QStringLiteral("qrc:/main.qml"));
QObject::connect(&engine, &QQmlApplicationEngine::objectCreated,
&app, [url](QObject *obj, const QUrl &objUrl) {
if (!obj && url == objUrl)
QCoreApplication::exit(-1);
}, Qt::QueuedConnection);
engine.load(url);
return app.exec();
}
创建了一个TableView。它具有两列,即QtQuick.Controls 1.4
和what
。我在这里及其上的session_name
类中创建了一个对象AA
,名为Component.onCompleted
(
像这样:
append
main.qml
mymodel.append( gname )