我有一个QAbstractListModel
对象,该对象维护要在地图上显示的项目列表。这些项目的位置每隔几秒钟更改一次,很容易在将来的60秒内计算出非常准确的位置。我要做的是设置物品在获得新位置时的位置(该零件工作良好),然后立即将其移向计算出的将来位置。
没有动画的代码如下所示,并且工作正常:
Component {
id: drawTarget
MapQuickItem {
id: marker
coordinate: data.coords
sourceItem: Item {
id: item
...
data
对象具有一个属性,该属性可在60秒后返回该项目的估计位置,所以我尝试了此操作:
Component {
id: drawTarget
MapQuickItem {
id: marker
coordinate: data.coords
CoordinateAnimation {
id:anim
property: "coordinate"
}
onCoordinateChanged: {
anim.stop()
anim.from = data.coords
anim.to = data.coordsIn60sec
anim.duration = 60000
anim.start()
}
sourceItem: Item {
id: item
...
但是,尽管每次更新位置时对象的位置都会正确更新,但是指向未来估计位置的动画根本无法工作。
人们将如何做这样的事情?
答案 0 :(得分:1)
在其代码中,它制作了一个绑定coordinate: data.coords
,其中声明“坐标”采用“坐标”的值,但同时又说“坐标”取决于动画,这不是矛盾的吗?好吧,这是矛盾的。
想法不是进行绑定coordinate: data.coords
,而是仅通过动画来更新属性。
以下代码是一个可行的示例:
main.qml
import QtQuick 2.14
import QtQuick.Window 2.14
import QtLocation 5.6
import QtPositioning 5.6
Window {
visible: true
width: 640
height: 480
Plugin {
id: mapPlugin
name: "osm"
}
Map {
anchors.fill: parent
plugin: mapPlugin
center: QtPositioning.coordinate(59.91, 10.75) // Oslo
zoomLevel: 10
MapItemView{
model: datamodel
delegate: MapQuickItem{
id: item
// begin configuration
property var position: model.position
property var nextposition: model.nextposition
onPositionChanged: restart();
onNextpositionChanged: restart();
function restart(){
anim.stop()
anim.from = position
anim.to = nextposition
anim.start()
}
CoordinateAnimation {
id: anim
target: item
duration: 60 * 1000
property: "coordinate"
}
// end of configuration
anchorPoint.x: rect.width/2
anchorPoint.y: rect.height/2
sourceItem: Rectangle{
id: rect
color: "green"
width: 10
height: 10
}
}
}
}
}
数据模型.h
#ifndef DATAMODEL_H
#define DATAMODEL_H
#include <QAbstractListModel>
#include <QGeoCoordinate>
#include <QTimer>
#include <random>
#include <QDebug>
struct Data{
QGeoCoordinate position;
QGeoCoordinate nextposition;
};
static QGeoCoordinate osloposition(59.91, 10.75); // Oslo;
class DataModel : public QAbstractListModel
{
Q_OBJECT
QList<Data> m_datas;
public:
enum PositionRoles {
PositionRole = Qt::UserRole + 1,
NextPositionRole
};
explicit DataModel(QObject *parent = nullptr)
: QAbstractListModel(parent)
{
init();
}
int rowCount(const QModelIndex &parent = QModelIndex()) const override{
return parent.isValid() ? 0: m_datas.count();
}
QVariant data(const QModelIndex &index, int role = Qt::DisplayRole) const override{
if (!index.isValid() || index.row() < 0 || index.row() >= m_datas.count())
return QVariant();
const Data &data = m_datas[index.row()];
if (role == PositionRole)
return QVariant::fromValue(data.position);
else if (role == NextPositionRole)
return QVariant::fromValue(data.nextposition);
return QVariant();
}
QHash<int, QByteArray> roleNames() const override{
QHash<int, QByteArray> roles;
roles[PositionRole] = "position";
roles[NextPositionRole] = "nextposition";
return roles;
}
private:
void init(){
for(int i=0; i< 10; ++i){
Data data;
data.position = osloposition;;
data.nextposition = data.position;
m_datas << data;
}
QTimer *timer = new QTimer(this);
QObject::connect(timer, &QTimer::timeout, this, &DataModel::updateData);
timer->start(60 * 1000);
updateData();
}
void updateData(){
qDebug() << __PRETTY_FUNCTION__;
static std::default_random_engine e;
static std::uniform_real_distribution<> dis(-.1, .1);
for(int i=0; i < m_datas.count(); ++i){
Data & data = m_datas[i];
QModelIndex ix = index(i);
data.position = data.nextposition;
data.nextposition = QGeoCoordinate(osloposition.latitude() + dis(e),
osloposition.longitude() + dis(e));
Q_EMIT dataChanged(ix, ix, {PositionRole, NextPositionRole});
}
}
};
#endif // DATAMODEL_H
下面的link是完整的示例