1.前言
某些业务需求,会要求当鼠标在矢量图层上悬浮时,能弹出某些提示。如下为阿拉斯加州矢量图的shp文件在QGIS画布上的显示,当鼠标移动到阿拉斯加州矢量图上方时,会弹出“Alaska”的工具提示:
怎样用代码实现呢?
2.开发环境说明
- QGIS 3.26.2
- Qt 5.14.1
- Visual Studio 2019
3.代码实现说明
不多说,直接上代码。.h文件如下:
#pragma once
#include <QtWidgets/QMainWindow>
#include "ui_CMyGIS.h"
#include<qgsmaptoolpan.h>
#include"qgsmapcanvas.h"
#include"QgsMapTip.h"
class CMyGIS : public QMainWindow
{
Q_OBJECT
public:
CMyGIS(QWidget *parent = Q_NULLPTR);
private:
// 创建地图提示对象
void createMapTips();
// 加载矢量图层
void addVectorLayer();
void installSlots();
// 显示地图提示
void showMapTip();
private: // slots
void mouseCoordinateChanged(const QgsPointXY& newCoordinate);
private:
private:
Ui::CMyGISClass ui;
// map canvas
QgsMapCanvas* m_pMapCanvas{ nullptr };
QList<QgsMapLayer*> m_lstLayers;
QgsMapToolPan* m_pMapToolPan{nullptr};
QTimer* m_pMapTipsTimer{ nullptr };
QgsMapTip* m_pMapTip{ nullptr };
QgsPointXY m_lastMapPosition;
};
.cpp文件如下:
#include "CMyGIS.h"
#include"qgsvectorlayer.h"
#include"qgsmaptip.h"
CMyGIS::CMyGIS(QWidget *parent)
: QMainWindow(parent)
{
ui.setupUi(this);
m_pMapCanvas = new QgsMapCanvas(this);
m_pMapCanvas->setCanvasColor(QColor(255, 255, 255));
m_pMapCanvas->setVisible(true);
m_pMapCanvas->enableAntiAliasing(true);
m_pMapToolPan = new QgsMapToolPan(m_pMapCanvas);
m_pMapCanvas->setMapTool(m_pMapToolPan);
setCentralWidget(m_pMapCanvas);
createMapTips();
installSlots();
// 加载矢量图层
addVectorLayer();
}
void CMyGIS::installSlots()
{
connect(m_pMapCanvas, &QgsMapCanvas::xyCoordinates, this, &CMyGIS::mouseCoordinateChanged);
}
// 创建地图提示
void CMyGIS::createMapTips()
{
m_pMapTipsTimer = new QTimer(m_pMapCanvas);
connect(m_pMapTipsTimer, &QTimer::timeout, this, &CMyGIS::showMapTip);
m_pMapTipsTimer->setInterval(850);
m_pMapTipsTimer->setSingleShot(true);
// Create the maptips object
m_pMapTip = new QgsMapTip();
}
void CMyGIS::showMapTip()
{
// 鼠标不在地图画布上,直接返回
if (!m_pMapCanvas->underMouse())
{
return;
}
QPoint myPointerPos = m_pMapCanvas->mouseLastXY();
// Make sure there is an active layer before proceeding
QgsMapLayer* mypLayer = m_pMapCanvas->currentLayer();
if (mypLayer)
{
// 仅仅只处理矢量图层
if (mypLayer->type() == QgsMapLayerType::VectorLayer)
{
m_pMapTip->showMapTip(mypLayer, m_lastMapPosition, myPointerPos, m_pMapCanvas);
}
}
}
void CMyGIS::mouseCoordinateChanged(const QgsPointXY& newCoordinate)
{
m_lastMapPosition = newCoordinate;
// 鼠标在地图画布上
if (m_pMapCanvas->underMouse())
{
// Clear the maptip (this is done conditionally)
int interval = qMin(300, m_pMapTipsTimer->interval());
// 如果之前弹出的提示没消失,先让其消失。
m_pMapTip->clear(m_pMapCanvas, interval);
// 启动定时器,以弹出提示
m_pMapTipsTimer->start();
}
}
void CMyGIS::addVectorLayer()
{
QgsVectorLayer* pLayer = new QgsVectorLayer(QString::fromLocal8Bit(R"(D:\GIS测试数据\QGIS-Sample-Data-master\qgis_sample_data\shapefiles\alaska.shp)"), "ogr");
if ((nullptr == pLayer) || !pLayer->isValid())
{
Q_ASSERT(0);
return;
}
m_pMapCanvas->setExtent(pLayer->extent());
m_lstLayers.append(pLayer);
m_pMapCanvas->setLayers(m_lstLayers);
m_pMapCanvas->setCurrentLayer(pLayer); // 注意:必须设置为当前图层,否则鼠标悬浮不起作用,具体参见showMapTip函数第58行
m_pMapCanvas->zoomToProjectExtent();
m_pMapCanvas->refresh();
}
上面加载的alaska.shp包含有QgsFeature(特征),如下,用QGIS官方的QGIS3.26.2.exe打开查看该文件,如下:
按上图表示的步骤操作,可以看到右侧面板有很多 QgsFeature(特征),而上述代码实现的鼠标悬浮弹出的地图提示,其实就是提取的右侧面板的总根名即NAME属性。
注意:
- 不是每个矢量图层会有QgsFeature(特征),也就是说上图右侧面板可能为空,此时前面代码实现的鼠标悬浮地图提示当前就不存在、不会显示了。
- 矢量图层如果没有QgsFeature(特征)或有QgsFeature,但不是我们想要的地图提示,可以通过代码加入或修改,从而显示自己想要的地图提示,关于这点如何实现,后期再写博文说明。