2012-02-02 5 views
4

Ну, я учу работать с QML, и у меня есть одно сомнение. В моем примере у меня есть ListModel с ListElements в QML, и у меня есть основной файл QML с прямоугольником, PathView и т. Д.Как вставить ListElement в QML ListModel с помощью C++?

У меня есть QWidget, а также мое главное окно. В этом QWidget я включаю QML-интерфейс как компонент. ОК!

Как я могу обработать QML ListElements с помощью C++?
Примечание: когда я говорю «обрабатывать», я хочу сказать, например, включить элемент.

Ниже приведены некоторые части моего кода ...

QML, содержащий мой ListElement, называемый "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() 
    } 
} 

И как я используйте QML как компонент для моего QWidget:

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); 
} 

Я видел некоторые статьи об этом, но я не могу изменить свой LisModel с помощью C++. Я видел здесь http://doc.qt.nokia.com/4.7/qdeclarativemodels.html#c-data-models и здесь, в примерах с использованием PathView http://doc.qt.nokia.com/4.7/qdeclarativeexamples.html

Может кто-нибудь мне помочь?

Спасибо!

ответ

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-коде.

+0

Эй @GooRoo, спасибо за Ваш ответ. Но я сделал по-другому ... На самом деле, этот пример показан здесь [ссылка] (http://cdumez.blogspot.com/2010/11/how-to-use-c-list-model-in-qml.html), я изменил его пример и изменил также «model: Menu1 {}» в моей PathView для «model: adrianoTest», поэтому в примере, который я использовал в моем main.cpp: this-> m_ImageCarousel-> rootContext() > setContextProperty ("testeAdriano", this-> m_Model); И работал! Спасибо большое ... –

+0

Я просто попытался ответить на ваш вопрос :) Рад, что вы нашли другой способ сделать то, что хотите. – GooRoo

+0

@AdrianoLeal, эта ссылка мертва, каким-либо образом показать, как вы обрабатывали заполнение списка из C++? – Boy

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 { 
     ... 
    } 
}