Мне нужно создать модель, которую можно редактировать в коде 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
, Центральный виджет содержит QQuickWidget
с источником MainView.qml. В конструкторе я заполняю QList<Object*>
модель и установите его как свойство контекста «nameColorModel» для 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 содержит некоторые дополнительные компоненты (firstTextField, secondComboBox, кнопки «ОК» и «Отмена») и 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
}
}
}
Когда я изменяю текст в «nameField» NameColorEdit.qml, «nameColorModel» не изменяется в коде С ++.
Как я могу это исправить?
Также есть следующие предупреждения в qml-коде:
qrc: /MainView.qml: 50: 9: QML GroupBox: обнаружен цикл привязки для
свойство «implicitWidth» qrc: /MainView.qml: 61: ReferenceError:
nameColorModel не определено
Обратите внимание, что модель будет установлена после вызова setSource QQuickWidget
,
Как я могу исправить эти предупреждения?
Вы также можете дать мне рекомендации по написанию кода.
Спасибо!
Проблема была решена с помощью Binding
за DataObject
собственность и 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 }
}
}
Теперь при редактировании nameField в NameColorEdit.qml содержимое QList<Object*>
Модель в коде C ++ успешно обновлена. Кроме того, если мы изменим содержание QList<Object*>
модель в коде C ++, NameColorEdit.qml будет обновлен.
Других решений пока нет …