1.简介

QgsMapTool地图工具是用于操作地图画布的用户交互式工具。例如,地图平移和缩放功能被实现为地图工具。

QgsMapTool是抽象基类,以下是类的继承关系:

QgsMapToolEdit:用于编辑矢量几何图形的映射工具的基类 QgsMapToolEmitPoint:一个地图工具,当单击地图时,它只是发出一个点。 将一个槽连接到它的canvasClicked()信号将允许您为传入点实现自定义行为。QgsMapToolExtent:地图画布上绘制矩形发出一个范围。QgsMapToolIdentify :用于识别图层特征的映射工具。QgsMapToolPan:用于平移地图的地图工具。QgsMapToolZoom :用于放大/缩小地图的地图工具。

2.常用接口

virtual void canvasDoubleClickEvent (QgsMapMouseEvent *e)重写鼠标双击事件virtual void canvasMoveEvent (QgsMapMouseEvent *e)重写鼠标移动事件virtual void canvasPressEvent (QgsMapMouseEvent *e)重写鼠标按下事件virtual void canvasReleaseEvent (QgsMapMouseEvent *e)重写鼠标抬起事件virtual void setCursor (const QCursor &cursor)设置光标QgsPointXY toMapCoordinates (QPoint point)将点从屏幕坐标转换为地图坐标。

3.示例 

示例1:画布移动、放大、缩小

源码:

#pragma once

#include

#include "ui_GisCtrl.h"

#include

#include

#include

#include

#include

#include

#include

#include

#include

class GisCtrl : public QMainWindow

{

Q_OBJECT

public:

GisCtrl(QWidget *parent = Q_NULLPTR);

private:

Ui::GisCtrlClass ui;

private slots:

void slotXyCoordinates(const QgsPointXY &p);

void slotMove();

void slotZoomIn();

void slotZoomOut();

private:

QgsMapCanvas *m_mapCanvas = nullptr;

QList m_layers;

QgsMapToolPan *m_toolPan = nullptr; // 新建移动工具

QgsMapToolZoom *m_toolZoomIn = nullptr;//放大

QgsMapToolZoom *m_toolZoomOut = nullptr;//缩小

QActionGroup *m_actionGroup = nullptr;

};

#include "GisCtrl.h"

#include

#include

#pragma execution_character_set("utf-8")

GisCtrl::GisCtrl(QWidget *parent)

: QMainWindow(parent)

{

ui.setupUi(this);

//创建画布

m_mapCanvas = new QgsMapCanvas(this);

QString url = "F:/arcgis/TMS.xml";

m_mapCanvas->setCanvasColor(QColor(255, 255, 255));

//加载瓦片地图

QgsRasterLayer *layer = new QgsRasterLayer(url);

if (!layer->isValid())

{

qDebug() << "load map faild";

}

m_layers.append(layer);

// 新建移动工具

m_toolPan = new QgsMapToolPan(m_mapCanvas);

m_mapCanvas->setExtent(layer->extent());

m_mapCanvas->enableAntiAliasing(true);

m_mapCanvas->setLayers(m_layers);

m_mapCanvas->setMapTool(m_toolPan);

m_toolZoomIn = new QgsMapToolZoom(m_mapCanvas, false);

m_toolZoomOut = new QgsMapToolZoom(m_mapCanvas, true);

m_actionGroup = new QActionGroup(this);

m_actionGroup->addAction(ui.actionMove);

m_actionGroup->addAction(ui.actionZoomIn);

m_actionGroup->addAction(ui.actionZoomOut);

m_actionGroup->setExclusive(true);

connect(m_mapCanvas, &QgsMapCanvas::xyCoordinates, this, &GisCtrl::slotXyCoordinates);

connect(ui.actionMove, &QAction::triggered, this, &GisCtrl::slotMove);

connect(ui.actionZoomIn, &QAction::triggered, this, &GisCtrl::slotZoomIn);

connect(ui.actionZoomOut, &QAction::triggered, this, &GisCtrl::slotZoomOut);

setCentralWidget(m_mapCanvas);

ui.actionMove->setChecked(true);

ui.actionLineManager->setVisible(false);

ui.actionLayer->setVisible(false);

ui.actionSelect->setVisible(false);

ui.actionItem->setVisible(false);

}

void GisCtrl::slotXyCoordinates(const QgsPointXY &p)

{

QString str = QString("经度= %1,纬度=%2").arg(QString::number(p.x(), 'f', 6)).arg(QString::number(p.y(), 'f', 6));

this->statusBar()->showMessage(str);

}

void GisCtrl::slotMove()

{

m_mapCanvas->setMapTool(m_toolPan);

}

void GisCtrl::slotZoomIn()

{

m_mapCanvas->setMapTool(m_toolZoomIn);

}

void GisCtrl::slotZoomOut()

{

m_mapCanvas->setMapTool(m_toolZoomOut);

}

示例2:鼠标点击画矩形。

自定义一个地图交互工具继承QgsMapToolIdentify

源码:

#pragma once

#include

#include

#include

#include

#include

#include

#include

class QgsMapToolSelectFeatures : public QgsMapToolIdentify

{

Q_OBJECT

public:

QgsMapToolSelectFeatures(QgsMapCanvas *mapCanvas);

protected:

//重写鼠标移动

void canvasMoveEvent(QgsMapMouseEvent *e) override;

//重写鼠标按下

void canvasPressEvent(QgsMapMouseEvent *e) override;

void initRubberBand();

private:

// 是否正在选择

bool mSelectionActive = false;

QScopedPointer mSelectionRubberBand;

QColor mFillColor = QColor(255, 255, 0, 63);

QColor mStrokeColor = QColor(255, 255, 0, 100);

QPoint mInitDragPos;

};

//cpp

#include "QgsMapToolSelectFeatures.h"

#include "QgsMapToolIdentify.h"

QgsMapToolSelectFeatures::QgsMapToolSelectFeatures(QgsMapCanvas *mapCanvas)

: QgsMapToolIdentify(mapCanvas)

{

}

void QgsMapToolSelectFeatures::canvasMoveEvent(QgsMapMouseEvent * e)

{

if (e->buttons() != Qt::LeftButton)

return;

QRect rect;

if (!mSelectionActive)

{

mSelectionActive = true;

rect = QRect(e->pos(), e->pos());

}

else

{

rect = QRect(e->pos(), mInitDragPos);

}

if (mSelectionRubberBand)

mSelectionRubberBand->setToCanvasRectangle(rect);

}

void QgsMapToolSelectFeatures::canvasPressEvent(QgsMapMouseEvent * e)

{

if (!mSelectionRubberBand)

initRubberBand();

mInitDragPos = e->pos();

}

void QgsMapToolSelectFeatures::initRubberBand()

{

mSelectionRubberBand.reset(new QgsRubberBand(mCanvas, QgsWkbTypes::PolygonGeometry));

mSelectionRubberBand->setFillColor(mFillColor);

mSelectionRubberBand->setStrokeColor(mStrokeColor);

}

使用

QgsMapToolSelectFeatures *m_tool = new QgsMapToolSelectFeatures(m_mapCanvas);

m_mapCanvas->setMapTool(m_tool);

示例3:右键弹出菜单标注地点。

#pragma once

#include

#include

#include

#include

#include

#include

#include

#include

#include

#include

class QgsRubberBand;

class QgsAnnotationPointTextItem;

class QgsMapToolAddItem : public QgsMapToolIdentify

{

Q_OBJECT

public:

QgsMapToolAddItem(QgsMapCanvas *mapCanvas);

typedef struct _mark

{

QgsRubberBand *rubberBand; //svg图标item

QgsGeometry geo; //区域

QgsAnnotationPointTextItem *text;//字体

QgsAnnotationLayer *layer;

}Mark;

protected:

//重写鼠标按下

void canvasPressEvent(QgsMapMouseEvent *e) override;

private slots:

void slotAdd();

void slotDel();

void slotShowScale(double scale);

void slotZoomLastStatusChanged(bool);

private:

// 是否正在选择

bool mSelectionActive = false;

QMenu *m_menu = nullptr;

QAction *m_add = nullptr;

QAction *m_del = nullptr;

QgsMapCanvas *m_canvas;

QList m_lstMark;

};

#include "QgsMapToolAddItem.h"

#include "QgsMapToolIdentify.h"

#include "qgsapplication.h"

#include "qgsvectorlayer.h"

#include

#include

#include

#include

#include

#include

#include "BaseFunc.h"

#include

#include

#pragma execution_character_set("utf-8")

extern bool g_is3857crs;

extern QList g_layers;

static QgsPointXY g_point;

static int g_index = -1;

QgsMapToolAddItem::QgsMapToolAddItem(QgsMapCanvas *mapCanvas)

: QgsMapToolIdentify(mapCanvas)

, m_canvas(mapCanvas)

{

this->setCursor(Qt::CrossCursor);

m_menu = new QMenu();

m_add = m_menu->addAction(QIcon(QPixmap(":/GisCtrl/image/add.png")),"添加");

m_del = m_menu->addAction(QIcon(QPixmap(":/GisCtrl/image/del.png")),"删除");

connect(m_add, &QAction::triggered, this, &QgsMapToolAddItem::slotAdd);

connect(m_del, &QAction::triggered, this, &QgsMapToolAddItem::slotDel);

connect(mapCanvas, &QgsMapCanvas::zoomLastStatusChanged,

this, &QgsMapToolAddItem::slotZoomLastStatusChanged);

}

void QgsMapToolAddItem::canvasPressEvent(QgsMapMouseEvent * e)

{

if (e->buttons() == Qt::RightButton)

{

g_point = e->mapPoint();

bool isHaveItem = false;

const QgsMapToPixel *mtransform = m_canvas->getCoordinateTransform();

for (int i = 0; i < m_lstMark.size(); i++)

{

Mark item = m_lstMark.at(i);

QgsVector qgsVector;

QgsPointXY p2 = item.geo.asPoint();

QgsPointXY curPoint = mtransform->transform(g_point.x(), g_point.y());

QgsPointXY itemPoint = mtransform->transform(p2.x(), p2.y());

qgsVector = curPoint - itemPoint;

if ((-10 < qgsVector.x() && qgsVector.x() < 15) &&

(-10 < qgsVector.y() && qgsVector.y() < 15))

{

isHaveItem = true;

g_index = i;

break;

}

}

if (!isHaveItem)

g_index = -1;

QPoint point = e->pos();

point.setY(point.y() + 80);

m_del->setVisible(isHaveItem);

m_menu->exec(point);

}

else

{

m_menu->hide();

}

}

void QgsMapToolAddItem::slotAdd()

{

//添加点

QgsRubberBand *rb = new QgsRubberBand(m_canvas, QgsWkbTypes::PointGeometry);

//rb->setOpacity(0.8);

rb->setIcon(QgsRubberBand::IconType::ICON_SVG); //设置图标类型

rb->setIconSize(5); //设置图标尺寸

rb->setSvgIcon(":/GisCtrl/image/water.svg", QPoint(-16, -16)); //设置图标文件路径和偏移

QgsGeometry geo = QgsGeometry::fromPointXY(g_point); //经纬度

rb->addGeometry(geo); //绘制

//添加文字

QgsCoordinateTransformContext coordinateTransformContext;

//先构造出一个能加注记的图层

QgsAnnotationLayer *textLayer = new QgsAnnotationLayer("annotationLayer",

QgsAnnotationLayer::LayerOptions(coordinateTransformContext));

double lon = 0, lat = 0;

BaseFunc::WebMercatorToWGS84(g_point.x(), g_point.y(), &lon, &lat);

//构造时传入地理坐标,有必要后期改成鼠标事件点击来创建QgsAnnotationMarkerItem

const QgsMapToPixel *mtransform = m_canvas->getCoordinateTransform();

//转换到屏幕坐标

QgsPointXY offsetPoint = mtransform->transform(g_point.x(), g_point.y());

int yOffset = 25;

offsetPoint.setY(offsetPoint.y() + yOffset);

//转回去到地图坐标

offsetPoint = mtransform->toMapCoordinates(offsetPoint.x(), offsetPoint.y());

QString showText = QString("%1,%2").arg(QString::number(lon, 'f', 6)).arg(QString::number(lat, 'f', 6));

QgsAnnotationPointTextItem* textItem = new QgsAnnotationPointTextItem(showText, QgsPoint(offsetPoint.x(), offsetPoint.y()));

textItem->setAlignment(Qt::AlignHCenter);

QgsTextFormat format;

QFont font;

font.setBold(true);

font.setPointSize(13);

format.setFont(font);

format.setColor(QColor(Qt::yellow));

textItem->setFormat(format);

textLayer->addItem(textItem);//画布添加Item

Mark mark;

mark.rubberBand = rb;

mark.geo = geo;

mark.text = textItem;

mark.layer = textLayer;

m_lstMark.append(mark);

g_layers.push_front(textLayer);

m_canvas->setLayers(g_layers);

m_canvas->refresh();

}

void QgsMapToolAddItem::slotDel()

{

if (g_index < 0)

return;

Mark mark = m_lstMark.at(g_index);

g_layers.removeOne(mark.layer);

delete mark.layer;

mark.rubberBand->reset();

delete mark.rubberBand;

m_lstMark.removeAt(g_index);

m_canvas->setLayers(g_layers);

m_canvas->refresh();

}

void QgsMapToolAddItem::slotShowScale(double scale)

{

qDebug() << "scale = " << scale;

}

void QgsMapToolAddItem::slotZoomLastStatusChanged(bool)

{

for (int i = 0; i < m_lstMark.size(); i++)

{

QgsPointXY xy = m_lstMark.at(i).geo.asPoint();

const QgsMapToPixel *mtransform = m_canvas->getCoordinateTransform();

//转换到屏幕坐标

QgsPointXY offsetPoint = mtransform->transform(xy.x(), xy.y());

int yOffset = 25;

offsetPoint.setY(offsetPoint.y() + yOffset);

//转回去到地图坐标

offsetPoint = mtransform->toMapCoordinates(offsetPoint.x(), offsetPoint.y());

m_lstMark.at(i).text->setPoint(QgsPoint(offsetPoint.x(), offsetPoint.y()));

}

}

4.更多参考

Qgis二次开发-QgsAnnotationItem(添加文字、图片标注(支持svg、png、jpg等常用图片格式))_Mr.codeee的博客-CSDN博客

Qgis二次开发-QgsMapCanvas画布简介_Mr.codeee的博客-CSDN博客 

Qgis二次开发-QgsRubberBand详解(画线、画多边形)_Mr.codeee的博客-CSDN博客 

Qgis二次开发-QgsAnnotationItem(添加文字、图片标注(支持svg、png、jpg等常用图片格式))_Mr.codeee的博客-CSDN博客 

相关文章

评论可见,请评论后查看内容,谢谢!!!
 您阅读本篇文章共花了: