在 Qml 代码中编辑 C++ QList<Object*> 模型的问题和一些 Qml 警告
Posted
技术标签:
【中文标题】在 Qml 代码中编辑 C++ QList<Object*> 模型的问题和一些 Qml 警告【英文标题】:Problems with editing C++ QList<Object*> model in Qml code and some Qml warnings 【发布时间】:2017-03-03 20:54:49 【问题描述】:我需要创建一个可以在 C++ 和 Qml 代码中编辑的模型。该模型将用于同时包含 Qt Widgets 和 Qml 的桌面应用程序。对于 qml 渲染,我使用QQuickWidget
。
我有两个属性的数据对象:名称和颜色。
数据对象.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
数据对象.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 小部件包含 QQuickWidget
和源 MainView.qml。在构造函数中,我填写 QList<Object*>
模型并将其设置为 MainView.qml 的上下文属性“nameColorModel”。
主窗口.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
主窗口.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
,其中包含使用我的“nameColorModel”的Repeater
。 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后设置。
如何解决这些警告?
你也可以给我写代码的建议。
谢谢!
【问题讨论】:
你的视图是在设置上下文属性之前创建的,所以第一次运行会报错nameColorModel。尝试早点设置 context 属性。 您可能还想考虑拥有一个“数据处理程序”类来管理您的值对并为更改通知提供信号,并在 QtWidgets 的表模型和 QtQuick 的列表模型中使用它。或者,为这两种情况提供一个表模型,但将 QML 属性映射到列中 @arynaq,有没有办法在视图创建后设置上下文属性而不发出警告? @Kevin Krammer,感谢您的推荐! 【参考方案1】:问题已通过使用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
现在,在 C++ 代码中编辑 QList<Object*>
模型的 NameColorEdit.qml 中的 nameField 内容时已成功更新。此外,如果我们在 C++ 代码中更改 QList<Object*>
模型的内容,NameColorEdit.qml 将被更新。
【讨论】:
以上是关于在 Qml 代码中编辑 C++ QList<Object*> 模型的问题和一些 Qml 警告的主要内容,如果未能解决你的问题,请参考以下文章