gpt4 book ai didi

c++ - 模型未使用 setContextProperty 更新

转载 作者:塔克拉玛干 更新时间:2023-11-03 07:38:33 26 4
gpt4 key购买 nike

我是 Qt 的新手,在将我的模型传递到我的 View 时遇到了问题。我的 View 有一堆按钮和一个带有一些标记的 map ,这些标记的纬度/经度来 self 的模型。单击按钮应更新 map 上的标记(删除一些和/或显示新标记)。

问题是:当我的模型(QList)在 C++ 端得到更新时,QML 端却没有。

(我知道这种问题似乎已经有人问过,但是在阅读了不同的答案之后,我无法清楚地了解我是否可以通过更聪明的方式调用 setContextProperty() 或者我是否可以必须使用发出信号和绑定(bind)属性之类的东西,在阅读了一些文档后我也无法清楚地了解这些东西)

架构如下:

  1. 具有 QApplication 实例化和 MainWindow 的主类(MainWindow 是自定义 QMainWindow 类)。应用得到执行并显示窗口。

  2. 具有 updateMap() 方法的 Mapwidget 类(自定义 QQuickWidget 类):

    • 对用户界面上的按钮点击使用react
    • 更新模型(QList)
    • 使用 setContextProperty() 方法将更新后的模型传递给 View
  3. MainWindow 类有一个 Mapwidget 属性

到目前为止我已经尝试过的事情:

  • 在调用 setSource() 方法之前在 Mapwidget 构造函数中调用 setContextProperty() 时,会考虑模型。所以我用于将模型传递到 View 的语法应该是正确的。问题似乎是之后对 setContextProperty() 的任何调用(在这种情况下:在 updateMap() 方法中)都没有传递给 QML 文件。

  • 在不同级别(Mapwidget 类、MainWindow 类)调用 setContextProperty(),结果相同,在应用程序首次启动后从未考虑过。

  • 我已经测试了模型并知道它确实在 updateMap() 方法中得到了更新,只是似乎更新没有传输到 QML 文件。

QML 文件:

Item {
width: 1200
height: 1000
visible: true

Plugin {
id: osmPlugin
name: "osm"
}

Map {
id: map
anchors.fill: parent
plugin: osmPlugin
center: QtPositioning.coordinate(45.782074, 4.871263)
zoomLevel: 5

MapItemView {
model : myModel
delegate: MapQuickItem {
coordinate:QtPositioning.coordinate(
model.modelData.lat,model.modelData.lon)
sourceItem: Image {
id:image_1
source: <picturePath>
}
anchorPoint.x: image_1.width / 2
anchorPoint.y: image_1.height / 2
}

}
}

map 小部件类:

mapwidget::mapwidget(QWidget *parent) : QQuickWidget(parent)
{
this->setSource(QUrl(QStringLiteral("qrc:/main.qml")));
}

void mapwidget::updateMap(QList<QObject *> &data)
{
/**
DO OPERATIONS TO UPDATE data
Each append has the following form :
data.append(new DataObject(someLatitude, someLongitude))
*/
this->rootContext()->setContextProperty("myModel", QVariant::fromValue(data));
}

在 updateMap() 方法中,附加到列表的 QObjects 是自定义类 DataObject :

class DataObject : public QObject
{
Q_OBJECT

Q_PROPERTY(double lat READ lat WRITE setLat)
Q_PROPERTY(double lon READ lon WRITE setLon)


public:
explicit DataObject(QObject *parent = nullptr);
DataObject(double latitude, double longitude, QObject *parent =
nullptr);

void setLat(double latitude);
void setLon(double longitude);
double lat() const;
double lon() const;

double d_lat;
double d_lon;
}

为什么即使在调用 setContextProperty() 之后 View 也看不到更新的模型?

谢谢你的帮助

最佳答案

通过setContextProperty(...)传递给你的名字是您传递的对象的别名,在绑定(bind) model: myModel 的情况下,它是在对象之间创建的,在您的情况下,当您传递具有相同别名的新对象时,不再是初始绑定(bind)是有效的,因为它们是不同的对象,它类似于:

T *t = new T;
connect(t, &T::foo_signal, obj, &U::foo_slot);
t = new T;

虽然两个对象具有相同的别名 (t),但这并不意味着与第二个对象的连接持续存在。


解决方案是使用通知更新到 QML 的同一对象,在这种情况下,解决方案是实现自定义 QAbstractListModel:

坐标模型类

// coordinatemodel.h
#ifndef COORDINATEMODEL_H
#define COORDINATEMODEL_H

#include <QAbstractListModel>
#include <QGeoCoordinate>

class CoordinateModel : public QAbstractListModel
{
Q_OBJECT
public:
enum{
PositionRole = Qt::UserRole + 1000
};
explicit CoordinateModel(QObject *parent = nullptr);

void insert(int index, const QGeoCoordinate & coordinate);
void append(const QGeoCoordinate & coordinate);
void clear();

int rowCount(const QModelIndex &parent = QModelIndex()) const override;
QVariant data(const QModelIndex &index, int role = Qt::DisplayRole) const override;
QHash<int, QByteArray> roleNames() const override;

private:
QList<QGeoCoordinate> m_coordinates;
};

#endif // COORDINATEMODEL_H

// coordinatemodel.cpp

#include "coordinatemodel.h"

CoordinateModel::CoordinateModel(QObject *parent)
: QAbstractListModel(parent)
{
}

void CoordinateModel::insert(int index, const QGeoCoordinate &coordinate){
int i = index;
if(index < 0) // prepend
i = 0;
else if (index >= rowCount()) // append
i = rowCount();
beginInsertRows(QModelIndex(), i, i);
m_coordinates.insert(i, coordinate);
endInsertRows();
}

void CoordinateModel::append(const QGeoCoordinate &coordinate){
insert(rowCount(), coordinate);
}

void CoordinateModel::clear(){
beginResetModel();
m_coordinates.clear();
endResetModel();
}

int CoordinateModel::rowCount(const QModelIndex &parent) const{
if (parent.isValid())
return 0;
return m_coordinates.count();
}

QVariant CoordinateModel::data(const QModelIndex &index, int role) const{
if (index.row() < 0 || index.row() >= m_coordinates.count())
return QVariant();
if (!index.isValid())
return QVariant();
const QGeoCoordinate &coordinate = m_coordinates[index.row()];
if(role == PositionRole)
return QVariant::fromValue(coordinate);
return QVariant();
}

QHash<int, QByteArray> CoordinateModel::roleNames() const{
QHash<int, QByteArray> roles;
roles[PositionRole] = "position";
return roles;
}

MapWidget 类

// mapwidget.h

#ifndef MAPWIDGET_H
#define MAPWIDGET_H

#include <QQuickWidget>

class CoordinateModel;

class MapWidget : public QQuickWidget
{
public:
MapWidget(QWidget *parent=nullptr);
CoordinateModel *model() const;
private:
CoordinateModel *m_model;
};

#endif // MAPWIDGET_H

// mapwidget.cpp

#include "coordinatemodel.h"
#include "mapwidget.h"

#include <QQmlContext>

MapWidget::MapWidget(QWidget *parent):
QQuickWidget(parent),
m_model(new CoordinateModel{this})
{
rootContext()->setContextProperty("myModel", m_model);
setSource(QUrl(QStringLiteral("qrc:/main.qml")));
}

CoordinateModel *MapWidget::model() const
{
return m_model;
}

然后您可以将其用作:

MapWidget w;
w.model()->append(QGeoCoordinate(45.782074, -6.871263));
w.model()->append(QGeoCoordinate(50.782074, -1.871263));
w.model()->append(QGeoCoordinate(55.782074, 4.871263));
w.model()->append(QGeoCoordinate(45.782074, 4.871263));
w.model()->append(QGeoCoordinate(50.782074, 4.871263));
w.model()->append(QGeoCoordinate(55.782074, 4.871263));

ma​​in.qml

import QtQuick 2.12
import QtLocation 5.12
import QtPositioning 5.12

Item {
width: 1200
height: 1000
visible: true

Plugin {
id: osmPlugin
name: "osm"
}

Map {
id: map
anchors.fill: parent
plugin: osmPlugin
center: QtPositioning.coordinate(45.782074, 4.871263)
zoomLevel: 5

MapItemView {
model : myModel
delegate: MapQuickItem {
coordinate: model.position
sourceItem: Image {
id: image_1
source: "http://maps.gstatic.com/mapfiles/ridefinder-images/mm_20_red.png"
}
anchorPoint.x: image_1.width / 2
anchorPoint.y: image_1.height / 2
}
}
}
}

enter image description here

完整的例子是here .

关于c++ - 模型未使用 setContextProperty 更新,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/56614203/

26 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com