效果
功能说明
本次开发的功能是基于上一版本 “QGis二次开发 —— 3、程序加载栅格tif与矢量shp文件可进行切换控制,可进行导出/导入工程(附源码)” 基础上继续制作的。
本次软件增加了对画布地图图层进行平移、缩放、自适应图层画面控制操作。
源码
main.cpp
#include "QtWidgetsApplication1.h"
#include <QtWidgets/QApplication>
#include <qgsapplication.h>
int main(int argc, char *argv[])
{
// 参数三: 如果需要GUI应用程序,则设置为true;对于仅控制台应用程序,设置false
QgsApplication a(argc, argv, true);
QgsApplication::setPrefixPath("D:/Software/QGis-OSGeo4W/install/apps/qgis-ltr", true); // 设置qgis路径
QgsApplication::setPluginPath("D:/Software/QGis-OSGeo4W/install/apps/qgis-ltr/plugins"); // 设置插件路径
QgsApplication::initQgis(); // 初始化QGis
QtWidgetsApplication1 w;
w.show();
return a.exec();
}
QtWidgetsApplication1.h
#pragma once
#include <QtWidgets/QMainWindow>
#include "ui_QtWidgetsApplication1.h"
#include <QtMath>
#include <qgsmapcanvas.h>
#include <qgsmaptoolpan.h>
#include <qgsmaptoolzoom.h>
class QtWidgetsApplication1 : public QMainWindow
{
Q_OBJECT
public:
QtWidgetsApplication1(QWidget *parent = nullptr);
~QtWidgetsApplication1();
protected:
// 将画布放在ui的Widget上,供显示
void initQgsMapCanvas();
// 加载本地.tif、.shp文件
bool loadLocalFile(const QString &RasterFileName, const QString &VectorFileName);
// 删除画布上所有图层并更新画布
void removeMapLayers();
protected slots:
// 切换显示画布上的矢量、栅格图层
void sltQgsShowFile(int);
/***************************** UI *****************************/
// 通过按钮驱动进行加载本地文件
void on_btn_qgsLoadFile_clicked();
// 保存QGIS工程项目
void on_btn_SaveQgisProject_clicked();
// 导入QGIS工程项目
void on_btn_LoadQgisProject_clicked();
// 关闭QGIS工程项目
void on_btn_CloseQgisProject_clicked();
// 自适应完全画面
void on_btn_entireScreen_clicked();
// 平移画布地图
void on_btn_move_clicked();
// 平移缩小地图
void on_btn_scaleMin_clicked();
// 平移缩小地图
void on_btn_scaleMax_clicked();
/**************************************************************/
private:
Ui::QtWidgetsApplication1Class ui;
// 画布
QgsMapCanvas *qMapCanvas = nullptr;
// 图层列表: qMapLayerList为真实使用,qVirtualMapLayerList为虚拟使用。真实使用时会增删、虚拟使用则仅在函数内增加后则不再增删。
QList<QgsMapLayer*> qMapLayerList, qVirtualMapLayerList;
// 地图工具 - 鼠标平移地图工具
QgsMapToolPan *qMapToolPan = nullptr;
// 地图工具 - 鼠标缩放地图工具
QgsMapToolZoom *qMapToolZoom_In = nullptr, *qMapToolZoom_Out = nullptr;
};
QtWidgetsApplication1.cpp
#include "QtWidgetsApplication1.h"
#include <QMessageBox>
#include <QComboBox>
#include <QGridLayout>
#include <qgsrasterlayer.h>
#include <qgsvectorlayer.h>
#include <qgsproject.h>
const QString QGisProjectFileName = "qgs_project.qgs";
QtWidgetsApplication1::QtWidgetsApplication1(QWidget *parent) : QMainWindow(parent)
{
ui.setupUi(this);
initQgsMapCanvas();
}
QtWidgetsApplication1::~QtWidgetsApplication1()
{
removeMapLayers();
QLayout *GridLayout = ui.qgsMapCanvasWidget->layout();
if (GridLayout)
{
GridLayout->removeWidget(qMapCanvas);
delete GridLayout;
}GridLayout = nullptr;
if (qMapCanvas)
{
qMapCanvas->unsetMapTool(qMapToolPan);
delete qMapCanvas;
}qMapCanvas = nullptr;
}
void QtWidgetsApplication1::initQgsMapCanvas()
{
// 创建地图画布对象
qMapCanvas = new QgsMapCanvas(this);
QGridLayout *GridLayout = new QGridLayout;
GridLayout->addWidget(qMapCanvas);
ui.qgsMapCanvasWidget->setLayout(GridLayout);
// 创建地图平移对象
qMapToolPan = new QgsMapToolPan(qMapCanvas);
// 创建地图缩放对象
qMapToolZoom_In = new QgsMapToolZoom(qMapCanvas, true);
qMapToolZoom_Out = new QgsMapToolZoom(qMapCanvas, false);
}
bool QtWidgetsApplication1::loadLocalFile(const QString &RasterFileName, const QString &VectorFileName)
{
// 创建矢量图层对象并加入本地文件
QgsVectorLayer *qVectorLayer = new QgsVectorLayer(VectorFileName, "shp");
if (!qVectorLayer->isValid()) { return false; }
qMapLayerList << qVectorLayer;
qVirtualMapLayerList << qVectorLayer;
ui.cb_qgsShowFile->addItem("shp", 0); // 1为qVectorLayer所在qMapLayerList的序号
// 创建光栅图层对象加入本地文件
QgsRasterLayer *qRasterLayer = new QgsRasterLayer(RasterFileName, "tif");
if (!qRasterLayer->isValid()) { return false; }
// 设置对比度增强(主要用于栅格图像;矢量图像不需要)。参数1算法:线性直方图、参数2界限范围:实际最小最大值
qRasterLayer->setContrastEnhancement(QgsContrastEnhancement::StretchToMinimumMaximum, QgsRasterMinMaxOrigin::MinMax);
qMapLayerList << qRasterLayer;
qVirtualMapLayerList << qRasterLayer;
ui.cb_qgsShowFile->addItem("tif",1); // 0为qRasterLayer所在qMapLayerList的序号
// 画布设置
qMapCanvas->setLayers(qMapLayerList); // 设置应在画布中显示的图层列表
qMapCanvas->setDestinationCrs(qMapLayerList[0]->crs()); // 设置目标坐标参照系为输入光栅图层的坐标系
qMapCanvas->setExtent(qMapLayerList[0]->extent()); // 设置画布范围为输入光栅图层的范围
qMapCanvas->setCurrentLayer(qMapLayerList[0]); // 设置画布当前图层为输入光栅图层
qMapCanvas->refresh(); // 刷新画布
// 将图层列表添加到已加载图层的映射中
QgsProject::instance()->addMapLayers(qMapLayerList);
return true;
}
void QtWidgetsApplication1::removeMapLayers()
{
if (!qMapLayerList.isEmpty())
{
qMapLayerList.clear();
qVirtualMapLayerList.clear();
}
qMapCanvas->setLayers(QList<QgsMapLayer*>());
qMapCanvas->refresh();
}
void QtWidgetsApplication1::on_btn_qgsLoadFile_clicked()
{
loadLocalFile("./world.tif", "./china.shp");
ui.btn_SaveQgisProject->setEnabled(true);
ui.btn_CloseQgisProject->setEnabled(true);
ui.cb_qgsShowFile->setEnabled(true);
ui.btn_qgsLoadFile->setEnabled(false);
connect(ui.cb_qgsShowFile, QOverload<int>::of(&QComboBox::currentIndexChanged), this, &QtWidgetsApplication1::sltQgsShowFile);
ui.btn_entireScreen->setEnabled(true);
ui.btn_move->setEnabled(true);
ui.btn_scaleMin->setEnabled(true);
ui.btn_scaleMax->setEnabled(true);
}
void QtWidgetsApplication1::on_btn_SaveQgisProject_clicked()
{
// 工程文件扩展名为: .qgz、.qgs
QgsProject::instance()->setFileName(QGisProjectFileName);
QgsProject::instance()->write();
}
void QtWidgetsApplication1::on_btn_LoadQgisProject_clicked()
{
/*****************************************************************/
int aaa = QgsProject::instance()->count();
int aaa1 = qMapCanvas->layerCount();
// 加载前先将之前的画布、画布上的图层清空
removeMapLayers();
int ccc = QgsProject::instance()->count();
int ccc2 = qMapCanvas->layerCount();
/* 重要: 以上测试说明当qMapLayerList删除,那么对应画布的layer与工程实例的mapLayer也会自动清空! */
/*****************************************************************/
if (!QgsProject::instance()->read(QGisProjectFileName))
{
QMessageBox::critical(this, "ERROR", "load QGIS Project fail!", QMessageBox::Yes);
return;
}
qMapLayerList = qVirtualMapLayerList = QgsProject::instance()->mapLayers().values();
qMapCanvas->setLayers(qMapLayerList); // 设置画布当前图层为输入光栅图层
qMapCanvas->setDestinationCrs(qMapLayerList[0]->crs()); // 设置目标坐标参照系为输入光栅图层的坐标系
qMapCanvas->setExtent(qMapLayerList[0]->extent()); // 设置画布范围为输入光栅图层的范围
qMapCanvas->setCurrentLayer(qMapLayerList[0]); // 设置画布当前图层为输入光栅图层
qMapCanvas->refresh(); // 刷新画布
ui.cb_qgsShowFile->addItem("shp", 0); // 1为qVectorLayer所在qMapLayerList的序号
ui.cb_qgsShowFile->addItem("tif", 1); // 0为qRasterLayer所在qMapLayerList的序号
ui.cb_qgsShowFile->setEnabled(true);
ui.btn_qgsLoadFile->setEnabled(false);
connect(ui.cb_qgsShowFile, QOverload<int>::of(&QComboBox::currentIndexChanged), this, &QtWidgetsApplication1::sltQgsShowFile);
ui.btn_entireScreen->setEnabled(true);
ui.btn_move->setEnabled(true);
ui.btn_scaleMin->setEnabled(true);
ui.btn_scaleMax->setEnabled(true);
ui.btn_CloseQgisProject->setEnabled(true);
ui.btn_SaveQgisProject->setEnabled(true);
qDebug() << "AA:" << QgsProject::instance()->count() << " " << QgsProject::instance()->mapLayers().count() << " " << qMapCanvas->layerCount() << " " << qMapLayerList.size() << " " << qVirtualMapLayerList.size();
}
void QtWidgetsApplication1::on_btn_CloseQgisProject_clicked()
{
// 加载前先将之前的画布、画布上的图层清空
removeMapLayers();
ui.btn_CloseQgisProject->setEnabled(false);
ui.btn_SaveQgisProject->setEnabled(false);
ui.btn_entireScreen->setEnabled(false);
ui.btn_move->setEnabled(false);
ui.btn_scaleMin->setEnabled(false);
ui.btn_scaleMax->setEnabled(false);
disconnect(ui.cb_qgsShowFile, QOverload<int>::of(&QComboBox::currentIndexChanged), this, &QtWidgetsApplication1::sltQgsShowFile);
ui.cb_qgsShowFile->setEnabled(false);
ui.btn_LoadQgisProject->setEnabled(true);
ui.btn_qgsLoadFile->setEnabled(true);
ui.cb_qgsShowFile->clear();
qDebug() << "BB:" << QgsProject::instance()->count() << " " << QgsProject::instance()->mapLayers().count() << " " << qMapCanvas->layerCount() << " " << qMapLayerList.size() << " " << qVirtualMapLayerList.size();
qMapCanvas->unsetMapTool(qMapCanvas->mapTool());
QgsProject::instance()->clear();
qDebug() << "CC:" << QgsProject::instance()->count() << " " << QgsProject::instance()->mapLayers().count() << " " << qMapCanvas->layerCount() << " " << qMapLayerList.size() << " " << qVirtualMapLayerList.size();
}
void QtWidgetsApplication1::on_btn_entireScreen_clicked()
{
if (qMapCanvas)
{
// 卸载画布地图工具
qMapCanvas->unsetMapTool(qMapCanvas->mapTool());
// 缩放到所有层的全部范围
qMapCanvas->zoomToFullExtent();
}
}
void QtWidgetsApplication1::on_btn_move_clicked()
{
// 画布加入地图平移工具
qMapCanvas->setMapTool(qMapToolPan);
}
void QtWidgetsApplication1::on_btn_scaleMin_clicked()
{
// 画布加入地图缩小工具
qMapCanvas->setMapTool(qMapToolZoom_In);
}
void QtWidgetsApplication1::on_btn_scaleMax_clicked()
{
// 画布加入地图放大工具
qMapCanvas->setMapTool(qMapToolZoom_Out);
}
void QtWidgetsApplication1::sltQgsShowFile(int index)
{
/* 重要: 以下操作说明qMapLayerList变化,那么对应画布的layer与工程实例的mapLayer也会自动变化! */
if (qVirtualMapLayerList.size() > index)
{
qMapLayerList.clear();
qMapLayerList << qVirtualMapLayerList[index];
qMapCanvas->setLayers(qMapLayerList); // 设置画布当前图层为输入光栅图层
qMapCanvas->setDestinationCrs(qMapLayerList[0]->crs()); // 设置目标坐标参照系为输入光栅图层的坐标系
qMapCanvas->setExtent(qMapLayerList[0]->extent()); // 设置画布范围为输入光栅图层的范围
qMapCanvas->refresh(); // 刷新画布
}
}
QtWidgetsApplication1.ui
关注
笔者 - jxd