1、事件介绍
SkeyeGisMap
中事件的传递机制如下:
- 1、首先创建
QGuiApplication
并启动主事件循环。 - 2、接着创建
MapItem
接受来自窗口的事件。 - 3、
MapItem
将会把QEvent
转换成MapEvent
并传递给地图根节点MapRootNode
。 - 4、
MapRootNode
遍历所有图层节点并根据MapLayerNode
的视觉层级依次向下传递。
注意: WorldLayer
位于所有 TransformLayer
之上, 因此会优先获得事件。
另一方面, 每一个图层节点都有自己范围 MapLayerNode::boundingRect()
, 因此, 对于范围之外的事件将直接向下传递。
如果某个图层节点接受了事件 MapEvent::isAccepeted()
, 事件将停止传递。
- 5、
MapLayerNode
遍历所有形状节点并根据MapShapeNode
的视觉层级依次向下传递。
如果某个形状节点接受了事件, 事件也将停止传递(即代表该层接受了事件)。
2、具体实施
现在, 我们准备实现一个可移动的多边形:
代码语言:c复制class MovablePolygon: public MapPolygonNode
{
public:
MovablePolygon(const QPolygonF &polygon, const QColor &borderColor, int borderWidth, const QColor &fillColor)
: MapPolygonNode(polygon, borderColor, borderWidth, fillColor) { }
void translate(const QPointF &offset)
{
auto polygon = points();
polygon.translate(offset);
setPoints(polygon);
}
virtual void mousePresseEvent(MapMouseEvent *event) override
{
MapShapeNode::mousePresseEvent(event);
m_startPosition = event->displayCoord();
event->accepted();
}
virtual void mouseMoveEvent(MapMouseEvent *event) override
{
MapShapeNode::mouseMoveEvent(event);
translate(event->displayCoord() - m_startPosition);
m_startPosition = event->displayCoord();
event->accepted();
}
virtual void mouseReleaseEvent(MapMouseEvent *event) override
{
MapShapeNode::mouseReleaseEvent(event);
event->accepted();
}
private:
QPointF m_startPosition;
};
可以看到, 我们的事件处理和 QWidget
或 QQuickItem
几乎一致。
只需重写 mousePresseEvent()
鼠标按下事件, mouseMoveEvent()
鼠标移动事件, mouseReleaseEvent()
鼠标释放事件。
不过要注意的是: 所有重写的事件需要调用其基类实现, 并且, 如果不想事件继续传递, 则需要接受事件 event->accepted()
。
并且, 图层节点不会处理图层边界之外的事件, 相应的形状也会被剪裁, 要关闭请使用 MapLayerNode::setClip()
。
和上一个示例类似, 其地图扩展如下:
代码语言:c复制class HandingEventsExample: public MapItem
{
public:
HandingEventsExample()
{
setProcessFlag(MapItem::ProcessFlag::UsePreLoadProcess);
}
virtual void preLoadProcess() override
{
auto assistant = rootMap()->assistant();
//创建一个矩形
auto leftTop = assistant->mapToDisplay(CoordinateReference::lonlatToWorld({ 40.0365, 90.7359 }));
auto leftBottom = assistant->mapToDisplay(CoordinateReference::lonlatToWorld({ 24.9160, 94.8131 }));
auto rightTop = assistant->mapToDisplay(CoordinateReference::lonlatToWorld({ 43.1443, 116.2369 }));
auto rightBottom = assistant->mapToDisplay(CoordinateReference::lonlatToWorld({ 26.7637, 116.6262 }));
QPolygonF polygon;
polygon << leftTop << leftBottom << rightBottom << rightTop << leftTop;
//添加到最后一个图层中
auto lastLayer = rootMap()->lastLayer();
if (lastLayer) {
lastLayer->setBackground(QColor("#a000b800"));
lastLayer->appendShape(new MovablePolygon(polygon, Qt::black, 2, QColor("#a000a8f3")));
lastLayer->appendShape(new MovablePolygon(polygon, Qt::black, 2, QColor("#a000a8f3")));
}
}
};
另外要提一点, MapPolygonNode
默认实现了 mouseEnterEvent / mouseLeaveEvent
的效果, 如果不需要则重写即可。
3、效果展示
源码地址: https://gitee.com/visual-opening/skeyegismap/tree/master/coremap/example