gpt4 book ai didi

qt - MapItemView 在 dataChanged 信号后不更新

转载 作者:行者123 更新时间:2023-12-04 19:48:10 27 4
gpt4 key购买 nike

我将 QML MapItemView 组件与基于 C++ QAbstractListModel 的模型一起使用。 MapItemView 在重置模型、添加新项目或删除现有项目时工作正常。但是,MapItemView 并未反射(reflect)对已添加项目的更改。

我第一次遇到这个问题是在 Qt 5.4 上,但在更新到 Qt 5.5 后我仍然遇到这个问题

以下示例显示了 2 个不同模型的问题:一个基于 QAbstractListModel 的 C++ 模型和一个 QML ListModel。可以从一个模型切换到另一个模型,按下右上角的按钮:

  • 当使用QML模型时,点击 map 将添加一个新元素并修改第一个元素。
  • C++ 模型使用 QTimer 每秒修改其内容。

无论模型类型是什么,MapItemView 都不会显示模型更改。从一种模型切换到另一种模型时,可以看到 MapView 已更新。

我可能遗漏了一些非常明显的东西,但我不明白它是什么。预先感谢您的帮助。

ma​​in.cpp 代码:

#include <QGuiApplication>
#include <QQmlApplicationEngine>
#include <QQmlContext>
#include "playermodel.h"

int main(int argc, char *argv[])
{
QGuiApplication app(argc, argv);

QQmlApplicationEngine engine;
PlayerModel playerModel;
engine.rootContext()->setContextProperty("playerModel", &playerModel);
engine.load(QUrl(QStringLiteral("qrc:/main.qml")));

return app.exec();
}

C++ 模型头文件 (playermodel.h):

#ifndef PLAYERMODEL_H
#define PLAYERMODEL_H


#include <QObject>
#include <QAbstractListModel>
#include <QGeoPositionInfoSource>
#include <QTimer>
#include <QDebug>

struct PlayerData
{
PlayerData(){ }
PlayerData(int _Azimuth, double lat, double lng){
Azimuth = _Azimuth;
Latitude = lat;
Longitude = lng;
}

int Azimuth = -1;
double Latitude = 0.;
double Longitude = 0.;

QVariant getRole(int role) const;

enum Roles{
RoleAzimuth = Qt::UserRole + 1,
RoleLatitude,
RoleLongitude

};

};

class PlayerModel : public QAbstractListModel
{
Q_OBJECT
public:
PlayerModel();

~PlayerModel();

int rowCount(const QModelIndex & parent = QModelIndex()) const;
QVariant data( const QModelIndex & index, int role = Qt::DisplayRole ) const;
Q_INVOKABLE Qt::ItemFlags flags(const QModelIndex &index) const Q_DECL_OVERRIDE;

virtual bool setData(const QModelIndex & index, const QVariant & value, int role = Qt::EditRole);

bool removeRows(int row, int count, const QModelIndex & parent = QModelIndex());

void resetModel();
void updateModel();

public slots:
void testUpdateModel();

protected:
QHash<int, QByteArray> roleNames() const;

private:
QTimer m_timer;
QVector< PlayerData> m_lstValues ;
};


#endif // PLAYERMODEL_H

C++ 模型 (playermodel.cpp)

#include "playermodel.h"

QVariant PlayerData::getRole(int role) const
{
switch (role)
{
case Roles::RoleAzimuth:
return Azimuth;
case Roles::RoleLatitude:
return Latitude;
case Roles::RoleLongitude:
return Longitude;

default:
return QVariant();
}
}

PlayerModel::PlayerModel()
{

resetModel();
connect(&m_timer, SIGNAL(timeout()), this, SLOT(testUpdateModel()));
m_timer.start(1000);

}

PlayerModel::~PlayerModel()
{

}

void PlayerModel::testUpdateModel()
{
updateModel();

}

int PlayerModel::rowCount(const QModelIndex & parent) const
{
Q_UNUSED(parent);
return m_lstValues.size();
}

QVariant PlayerModel::data( const QModelIndex & index, int role ) const
{
if ( (index.row() < 0) || (index.row() >= rowCount()) )
return QVariant();

return m_lstValues[ index.row()].getRole( role);

}

void PlayerModel::resetModel()
{
qDebug() << "Reset players model";

beginResetModel();

m_lstValues.clear();
//populate with dummy value

m_lstValues.push_back( PlayerData( 10, 47.1, -1.6 ));
m_lstValues.push_back( PlayerData( 20, 47.2, -1.6 ));
m_lstValues.push_back( PlayerData( 30, 47.1, -1.5 ));
m_lstValues.push_back( PlayerData( 40, 47.2, -1.5 ));

endResetModel();

}


void PlayerModel::updateModel()
{
qDebug() << "update players model upon timeout";

//change the Azimuth of every model items
int row = 0;
for (PlayerData player : m_lstValues)
{
setData( index(row), (player.Azimuth + 1) % 360, PlayerData::RoleAzimuth);
row++;
}

//qDebug() << "First element azimuth is now : " << data( index(0),PlayerData::RoleAzimuth).toInt() << "°";
}

bool PlayerModel::setData(const QModelIndex & index, const QVariant & value, int role)
{
if ( (index.row() < 0) || (index.row() >= rowCount()) ) return false;

PlayerData& player = m_lstValues[ index.row() ];
switch (role)
{

case PlayerData::RoleAzimuth:
player.Azimuth = value.toInt();
break;
case PlayerData::RoleLatitude:
player.Latitude = value.toDouble();
break;
case PlayerData::RoleLongitude:
player.Longitude = value.toDouble();
break;

}
emit dataChanged(index, index );//, QVector<int>( role));

return true;
}

bool PlayerModel::removeRows(int row, int count, const QModelIndex & parent)
{
Q_UNUSED(count);
Q_UNUSED(parent);
beginRemoveRows(QModelIndex(), row, row);
m_lstValues.remove( row);
endRemoveRows();
return true;
}

QHash<int, QByteArray> PlayerModel::roleNames() const
{
QHash<int, QByteArray> roles;

roles[PlayerData::Roles::RoleAzimuth] = "Azimuth";
roles[PlayerData::Roles::RoleLatitude] = "Latitude";
roles[PlayerData::Roles::RoleLongitude] = "Longitude";

return roles;

}

Qt::ItemFlags PlayerModel::flags(const QModelIndex &index) const
{
if (!index.isValid())
return 0;

return Qt::ItemIsEditable | QAbstractItemModel::flags(index);
}

最后是 QML 文件:

import QtQuick 2.4
import QtQuick.Window 2.2
import QtLocation 5.3
import QtPositioning 5.0

Window {
id:mainWnd
visible: true
width : 1024
height:768
property bool useQMLModel: true
Map {
id: map
anchors.fill: parent
anchors.margins: 50
plugin: Plugin{ name:"osm";}
center: QtPositioning.coordinate(47.1, -1.6)
zoomLevel: map.maximumZoomLevel

MapItemView{
id:mapItemView
model: mainWnd.useQMLModel ? qmlModel : playerModel

delegate: MapQuickItem {
//anchorPoint:
id:delegateMQI
rotation: model.Azimuth
sourceItem: Rectangle{
id:defaultDelegate
width:32
height:32
radius:16
opacity: 0.6
rotation:Azimuth
color:"blue"

Text{
text: Azimuth
anchors.centerIn : parent
}

}
coordinate: QtPositioning.coordinate(Latitude,Longitude)
}

}
MouseArea{
anchors.fill: parent
enabled : useQMLModel
//preventStealing: true
propagateComposedEvents: true
onClicked:
{
//Modify an item
var newAzim = Math.random()*360;
qmlModel.setProperty(0, "Azimuth", newAzim);
//Check modification
console.log("Azim:" + qmlModel.get(0).Azimuth );
qmlModel.setProperty(0, "Color", "blue");


//add a new item
qmlModel.append({"Latitude": 47.05 + Math.random() *0.2, "Longitude":-1.75 + Math.random() *0.3, "Azimuth":0, "Color":"red"})
console.log("Nb item:" + qmlModel.count );


map.update();
map.fitViewportToMapItems();

mouse.accepted = false

}
}
}


Connections{
target:mapItemView.model
onDataChanged:{
if (useQMLModel)
console.log("dataChanged signal Azim:" + qmlModel.get(0).Azimuth );
else
console.log("dataChanged signal Azim:" + playerModel.data( topLeft, 0x0101) );
}
}

ListModel{
id:qmlModel
ListElement {
Latitude: 47.1
Longitude: -1.6
Azimuth: 10.0
}

}

Rectangle{
anchors.top : parent.top
anchors.left : parent.left
width : 400
height : 300
radius: 10
color:"grey"
ListView{
id:lstView
model:mapItemView.model
anchors.fill:parent
delegate: Text{
width:parent.width
height:50
verticalAlignment: TextInput.AlignVCenter
fontSizeMode : Text.Fit
font.pixelSize: 42
minimumPixelSize: 5
text: "Latitude : " + Latitude + " - Longitude :" + Longitude + " - Azimuth : " + Azimuth
}
}
}




Rectangle{
anchors.right : parent.right
anchors.top : parent.top
radius : 10
color : "red"
width : 200
height : 50
Text{
anchors.centerIn: parent
text:"switch model"
}
MouseArea{
anchors.fill: parent
onClicked:{
mainWnd.useQMLModel = !mainWnd.useQMLModel;
}
}
}

}

最佳答案

以防万一有人面临同样的问题issue经博主反馈,问题已在Qt 5.6.0中解决

Note that this is fixed by changeset Ib92252d18c2229bc6d43e11362b8f13cdb48f315 (https://codereview.qt-project.org/#/c/123660/ ) already merged in the 5.6 branch

关于qt - MapItemView 在 dataChanged 信号后不更新,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/31536014/

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