2017-03-03 1 views
1

Ich brauche ein Modell zu erstellen, die ++ und QML-Code in C bearbeitet werden kann. Dieses Modell wird in einer Desktopanwendung verwendet, die sowohl Qt Widgets als auch Qml enthält. Für das qml Rendering verwende ich die QQuickWidget.Probleme mit dem Bearbeiten von C++ QList <Object*> Modell in QML-Code und einige QML Warnungen

Ich habe Datenobjekt mit zwei Eigenschaften: Name und Farbe.

dataobject.h

#ifndef DATAOBJECT_H 
#define DATAOBJECT_H 

#include <QObject> 

class DataObject : public QObject 
{ 
    Q_OBJECT 

    Q_PROPERTY(QString name READ name WRITE setName NOTIFY nameChanged) 
    Q_PROPERTY(QString color READ color WRITE setColor NOTIFY colorChanged) 

public: 
    DataObject(QObject *parent = Q_NULLPTR); 
    DataObject(const QString &name, const QString &color, QObject *parent = Q_NULLPTR); 

    QString name() const; 
    void setName(const QString &name); 

    QString color() const; 
    void setColor(const QString &color); 

signals: 
    void nameChanged(); 
    void colorChanged(); 

private: 
    QString m_name; 
    QString m_color; 
}; 

#endif // DATAOBJECT_H 

dataobject.cpp

#include "dataobject.h" 

#include <QDebug> 

DataObject::DataObject(QObject *parent) 
    : QObject(parent) 
{ 
} 

DataObject::DataObject(const QString &name, const QString &color, QObject *parent) 
    : QObject(parent), m_name(name), m_color(color) 
{ 
} 

QString DataObject::name() const 
{ 
    return m_name; 
} 

void DataObject::setName(const QString &name) 
{ 
    qDebug() << Q_FUNC_INFO; 

    if (name != m_name) { 
     m_name = name; 
     emit nameChanged(); 
    } 
} 

QString DataObject::color() const 
{ 
    return m_color; 
} 

void DataObject::setColor(const QString &color) 
{ 
    qDebug() << Q_FUNC_INFO; 

    if (color != m_color) { 
     m_color = color; 
     emit colorChanged(); 
    } 
} 

für das Hauptfenster I Unterklasse von QMainWindow verwenden. Das zentrale Widget enthält QQuickWidget mit der Quelle MainView.qml. Im Konstruktor fülle ich das QList<Object*> Modell und setze es als Kontexteigenschaft "nameColorModel" für MainView.qml.

mainwindow.h

#ifndef MAINWINDOW_H 
#define MAINWINDOW_H 

#include <QMainWindow> 

class MainWindow : public QMainWindow 
{ 
    Q_OBJECT 

public: 
    explicit MainWindow(QWidget *parent = Q_NULLPTR); 
    ~MainWindow(); 

public slots: 
    void onAccepted(); 

private: 
    QList<QObject*> nameColorModel; 
}; 

#endif // MAINWINDOW_H 

mainwindow.cpp

#include "mainwindow.h" 
#include "dataobject.h" 

#include <QQuickWidget> 
#include <QQmlContext> 
#include <QQuickItem> 

#include <QDebug> 

MainWindow::MainWindow(QWidget *parent) : 
    QMainWindow(parent) 
{ 
    auto qmlWidget = new QQuickWidget(QUrl("qrc:/MainView.qml"), this); 
    qmlWidget->setResizeMode(QQuickWidget::SizeRootObjectToView); 

    this->setCentralWidget(qmlWidget); 
    this->resize(600, 400); 

    nameColorModel.append(new DataObject("Item 1", "red")); 
    nameColorModel.append(new DataObject("Item 2", "green")); 
    nameColorModel.append(new DataObject("Item 3", "blue")); 
    nameColorModel.append(new DataObject("Item 4", "yellow")); 

    qmlWidget->rootContext()->setContextProperty("nameColorModel", QVariant::fromValue(nameColorModel)); 

    connect(qmlWidget->rootObject(), SIGNAL(accepted()), SLOT(onAccepted())); 
} 

MainWindow::~MainWindow() 
{ 
    qDeleteAll(nameColorModel.begin(), nameColorModel.end()); 
} 

void MainWindow::onAccepted() 
{ 
    for(auto& object: nameColorModel) 
    { 
     auto item = qobject_cast<DataObject*>(object); 
     qDebug() << item->name() << item->color(); 
    } 
} 

MainView.qml enthält einige zusätzliche Komponenten (firstTextField, secondComboBox, "OK" und "Abbrechen" -Tasten) und GroupBox enthält Repeater die benutzt mein "nameColorModel". NameColorEdit.qml wird als Stellvertreter von Repeater verwendet.

MainView.qml

import QtQuick 2.4 
import QtQuick.Controls 1.3 
import QtQuick.Layouts 1.1 

import "." as Views 

Item { 
    id: root 
    width: 600 
    height: 400 

    property alias firstText: firstTextField.text 
    property alias secondText: secondComboBox.currentText 

    signal accepted() 
    signal rejected() 

    ColumnLayout { 
     spacing: 10 
     anchors.fill: parent 
     anchors.margins: 10 

     GridLayout { 
      columns: 2 
      rowSpacing: 10 
      columnSpacing: 10 

      Label { 
       text: "First" 
      } 

      TextField { 
       id: firstTextField 
       implicitHeight: 42 
       Layout.fillWidth: true 
      } 

      Label { 
       text: "Second" 
      } 

      ComboBox { 
       id: secondComboBox 
       implicitHeight: 42 
       model: 5 
       Layout.fillWidth: true 
      } 
     } 

     GroupBox { 
      title: qsTr("Name-color objects:") 
      Layout.fillWidth: true 

      ColumnLayout { 
       id: col 
       spacing: 10 
       anchors.fill: parent 

       Repeater { 
        id: repeater 
        model: nameColorModel //// <-- QList<Object*> model 

        Views.NameColorEdit { 
         name: modelData.name 
         color: modelData.color 
         Layout.row: index 
         Layout.fillWidth: true 
        } 
       } 
      } 
     } 

     Item { 
      Layout.fillHeight: true 
     } 

     RowLayout { 
      Layout.alignment: Qt.AlignRight 

      Button { 
       text: "Ок" 
       Layout.minimumWidth: 42 
       Layout.minimumHeight: 42 
       onClicked: accepted() 
      } 

      Button { 
       text: "Cancel" 
       Layout.minimumWidth: 42 
       Layout.minimumHeight: 42 
       onClicked: rejected() 
      } 
     } 
    } 
} 

NameColorEdit.qml

import QtQuick 2.4 
import QtQuick.Controls 1.3 
import QtQuick.Layouts 1.1 

Item { 
    id: root 
    implicitWidth: nameField.implicitWidth 
    implicitHeight: nameField.implicitHeight 

    property alias name: nameField.text 
    property alias color: colorField.text 

    RowLayout { 
     spacing: 10 
     anchors.fill: parent 

     Label { 
      text: "Color" 
     } 

     TextField { 
      id: colorField 
      enabled: false 
      implicitWidth: 150 
      implicitHeight: 42 
     } 

     Label { 
      text: "Name" 
     } 

     TextField { 
      id: nameField 
      implicitHeight: 42 
      Layout.fillWidth: true 
     } 
    } 
} 

Wenn ich Text in der "namefield" von NameColorEdit.qml ändern "nameColorModel" ändert sich nicht in С ++ Code . Wie kann ich das beheben?

Auch gibt es folgende Warnungen in QML-Code:

qrc:/MainView.qml:50:9: QML GroupBox: Binding loop detected for property "implicitWidth" qrc:/MainView.qml:61: ReferenceError: nameColorModel is not defined

Beachten Sie, dass das Modell nach dem Aufruf setSource von QQuickWidget eingestellt werden. Wie kann ich diese Warnungen beheben?

Sie können mir auch Empfehlungen zum Schreiben von Code geben.

Vielen Dank!

+0

Ihre Ansicht wird erstellt, bevor die context -Eigenschaft festgelegt wird, so dass der erste Lauf über nameColorModel beschwert wird. Versuchen Sie, die contextproperty früher festzulegen. – arynaq

+0

Sie sollten auch eine "Data Handler" -Klasse in Betracht ziehen, die Ihre Wertepaare verwaltet und Signale für Änderungsbenachrichtigungen bereitstellt und diese in einem Tabellenmodell für QtWidgets und einem Listenmodell für QtQuick verwendet. Alternativ ein Tabellenmodell für beide Fälle, das aber die QML-Eigenschaften in Spalten abbildet –

+0

@arynaq, Gibt es eine Möglichkeit, Kontexteigenschaften nach der Erstellung von Ansichten ohne Warnungen festzulegen? – user7655285

Antwort

1

Das Problem wurde durch Binding für DataObject Eigentum und NameColorEdit Eigenschaft verwenden gelöst:

 Repeater { 
      id: repeater 
      model: nameColorModel //// <-- QList<Object*> model 

      Views.NameColorEdit { 
       name: modelData.name 
       color: modelData.color 
       Layout.row: index 
       Layout.fillWidth: true 

       Binding { target: modelData; property: "name"; value: name } 
       Binding { target: modelData; property: "color"; value: color } 
      } 
     } 

Wenn nun in NameColorEdit.qml namefield Inhalt QList<Object*> Modell in C++ Bearbeitung aktualisiert Code erfolgreich. Wenn wir den Inhalt des Modells QList<Object*> in C++ - Code ändern, wird auch NameColorEdit.qml aktualisiert.

Verwandte Themen