在dataChanged信号后未更新MapItemView [英] MapItemView is not updated after a dataChanged signal
问题描述
我正在将QML MapItemView
组件与基于C ++ QAbstractListModel
的模型一起使用.重置模型或添加新项目或删除现有项目时,MapItemView
正常工作.但是,MapItemView
不能反映对已添加项目的更改.
I am using the QML MapItemView
component with a C++ QAbstractListModel
-based model. The MapItemView
is working fine when the model is reset, or whenever a new item is added or an existing item is removed. However, the MapItemView
is not reflecting changes to already added items.
我第一次在Qt 5.4上遇到了这个问题,但是在更新到Qt 5.5之后我仍然面对它
I have first experienced this issue with Qt 5.4 but I still face it after updating to Qt 5.5
以下示例显示了2种不同模型的问题:基于QAbstractListModel
的C ++模型和QML ListModel
.
按下右上角的按钮,可以从一种模式切换到另一种模式:
The following example shows the issue with 2 different models : a C++ model based on QAbstractListModel
and a QML ListModel
.
It is possible to switch from one model to another, pressing the top-right button:
- 使用QML模型时,单击地图将添加一个新元素并修改第一个元素.
- C ++模型使用
QTimer
每秒钟修改其内容.
- When the QML model is used, clicking in the map will add a new element and modify the first element.
- The C++ model used a
QTimer
to modify its content every seconds.
MapItemView
不会显示模型更改,无论模型类型是什么.从一种模型切换到另一种模型时,可以看到MapView
得到更新.
The MapItemView
is not showing the model changes whatever the model type is. When switching from one model to another, one can see that the MapView
gets updated.
我可能缺少一些非常明显的东西,但是我看不到它是什么.预先感谢您的帮助.
I am probably missing something very obvious but I don't see what it is. Thank you in advance for your help.
main.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;
}
}
}
}
推荐答案
Just in case that someone faces the same issue reported by the post's author, the problem was solved in Qt 5.6.0
请注意,此问题已通过更改集Ib92252d18c2229bc6d43e11362b8f13cdb48f315( https://codereview.qt -project.org/#/c/123660/)已合并到5.6分支中
Note that this is fixed by changeset Ib92252d18c2229bc6d43e11362b8f13cdb48f315 (https://codereview.qt-project.org/#/c/123660/ ) already merged in the 5.6 branch
这篇关于在dataChanged信号后未更新MapItemView的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!