首页 文章

在Qml代码中编辑C QList <Object *>模型的问题和一些Qml警告

提问于
浏览
1

我需要创建一个可以用C和Qml代码编辑的模型 . 此模型将用于包含Qt Widgets和Qml的桌面应用程序 . 对于qml渲染,我使用 QQuickWidget .

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

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*> model并将其设置为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"和"Cancel"按钮)和 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的“nameField”中更改文本时,“nameColorModel”在С代码中不会更改 . 我怎样才能解决这个问题?

qml代码中还有以下警告:

qrc:/MainView.qml:50:9:QML GroupBox:检测到属性“implicitWidth”的绑定循环qrc:/MainView.qml:61:ReferenceError:nameColorModel未定义

请注意,在调用 QQuickWidget 的setSource之后将设置模型 . 我该如何解决这些警告?

您也可以给我编写代码的建议 .

谢谢!

1 回答

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

    现在,当在NameColorEdit.qml中编辑nameField时,C代码中 QList<Object*> 模型的内容已成功更新 . 此外,如果我们在C代码中更改 QList<Object*> 模型的内容,将更新NameColorEdit.qml .

相关问题