2017-03-03 90 views
1

我需要创建一个可以在C++和Qml代码中编辑的模型。此模型将用于包含Qt Widgets和Qml的桌面应用程序。对于qml渲染,我使用QQuickWidget在Qml代码和一些Qml警告中编辑C++ QList <Object*>模型的问题

我有两个属性的数据对象:名称和颜色。

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

因为我使用的QMainWindow子类的主窗口。 Сentral小部件包含源代码为MainView.qml的QQuickWidget。在构造函数中,填充QList<Object*>模型并将其设置为MainView.qml的上下文属性“nameColorModel”。

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含有一些另外的组分(firstTextField,secondComboBox, “OK” 和 “取消” 按钮)和GroupBox含有Repeater其使用我的“nameColorModel”。 NameColorEdit.qml用作Repeater的代表。

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

当我更改NameColorEdit.qml的 “名称字段” 文本 “nameColorModel” 不С改变++代码。 我该如何解决这个问题?

还有一些在QML代码以下警告:

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

注意,该模型将调用的QQuickWidget的SetSource后设置。 如何解决这些警告?

你也可以给我编写代码的建议。

谢谢!

+0

您的视图是在设置上下文属性之前创建的,所以第一次运行会抱怨nameColorModel。尽早设置contextproperty。 – arynaq

+0

您可能还想考虑拥有一个“数据处理程序”类,它管理您的值对并提供更改通知的信号,并将其用于QtWidgets的表模型和QtQuick的列表模型。 或者这两种情况下的表模型,但将QML属性映射到列 –

+0

@arynaq,有没有一种方法来设置视图创建后的上下文属性没有警告? – user7655285

回答

1

问题解决了使用BindingDataObject财产和财产NameColorEdit

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

现在,在用C QList<Object*>模型NameColorEdit.qml内容编辑名称字段时++代码更新成功。另外,如果我们在C++代码中更改QList<Object*>模型的内容,则NameColorEdit.qml将被更新。