Shapefile 为 OGR 所支持的最重要的数据格式之一,自然可以被 QGIS 加载。那么该如何显示Shapefile呢?
一、先上代码
cpp
#include <qgsapplication.h>
#include <qgsproviderregistry.h>
#include <qgsmapcanvas.h>
#include <qgsvectorlayer.h>
int main(int argc, char **argv)
{
// 创建 QgsApplication 实例
QgsApplication app(argc, argv, true);
// 设置并检查数据插件目录
QgsProviderRegistry::instance("D:/OSGeo4W/apps/qgis-ltr/plugins");
// 控制台打印已载入的插件目录
qDebug() << "QGIS data providers loaded:" << QgsProviderRegistry::instance()->providerList();
// 设置 GDAL 数据目录环境变量
qputenv("GDAL_DATA", "D:\\OSGeo4W\\apps\\gdal\\share\\gdal");
// 创建 QgsCanvas 画布实例
QgsMapCanvas c;
// 从磁盘 .shp 文件创建矢量图层
QgsVectorLayer* pVectorLayer = new QgsVectorLayer(u8"E:\\TestImage\\全国省界\\全国省界.shp", u8"省界");
// 确认图层是否创建成功
qDebug() << "Is layer valid:" << pVectorLayer->isValid();
// 将图层添加到画布上
c.setLayers(QList<QgsMapLayer*>() << pVectorLayer);
// 设置画布窗体标题并显示画布
// 画布本身是 QWidget 的子类,因此可以承担 QWidget 的所有操作
c.setWindowTitle(u8"QGIS 二次开发:画布");
c.show();
// 缩放到图层的空间范围
c.zoomToFullExtent();
// 启动 QgsApplication 实例
return app.exec();
}
二、效果图
三、代码讲解
(一)
cpp
// 创建 QgsApplication 实例
QgsApplication app(argc, argv, true);
需要头文件<qgsapplication.h>
参见QGIS API Documentation: QgsApplication Class Reference
该类继承自QApplication,提供对QGIS特定资源(如主题路径、数据库路径等)的访问。
构造函数接受 5 个参数。其中 3 个是必备参数。前两个参数传入 main
函数的两个参数即可,第三个参数表示是否激活图形界面 GUI,一般设置为 true
,除非你想做一个命令行的程序,如单纯用于数据处理,无需界面的程序。这里我们设置为 true
。
(二)
cpp
// 设置并检查数据插件目录
QgsProviderRegistry::instance("D:/OSGeo4W/apps/qgis-ltr/plugins");
需要头文件<qgsproviderregistry.h>
官方文档QGIS API Documentation: QgsProviderRegistry Class Reference
参数如下,pluginPath为数据插件的路径
cpp
QgsProviderRegistry * QgsProviderRegistry::instance(const QString & pluginPath = QString())
数据驱动插件为一系列的动态链接库文件,存放于 QGIS 开发包的 plugins 目录下
cpp
// 控制台打印已载入的插件目录
qDebug()<<"QGIS data providers loaded:"<<QgsProviderRegistry::instance()->providerList();
调用 QgsProviderRegistry
的成员函数 providerList()
可以返回一个存放所有支持的数据驱动插件的 QStringList
字符串列表,可以用于 debug。
参见QGIS API Documentation: QgsProviderRegistry Class Reference
(三)
cpp
// 设置 GDAL 数据目录环境变量
qputenv("GDAL_DATA", "D:\\OSGeo4W\\apps\\gdal\\share\\gdal");
随后程序会检测 GDAL 的环境变量 GDAL_DATA
是否设置。该环境变量为一个目录,存放 GDAL 所需的资源和数据文件等。利用 Qt 提供的全局函数 qputenv()
可以方便的设置环境变量而无需修改操作系统设置,该环境变量仅在当前程序中生效。
参见官方文档 https://doc.qt.io/qt-5/qtglobal.html#qputenv
(四)
cpp
// 创建 QgsCanvas 画布实例
QgsMapCanvas c;
头文件<qgsmapcanvas.h>
它是 Qt 用于描述图形场景的 QGraphicsView
的子类,用于显示GIS类型的数据。
官方文档 QGIS API Documentation: QgsMapCanvas Class Reference
(五)
cpp
// 从磁盘 .shp 文件创建矢量图层
QgsVectorLayer* pVectorLayer = new QgsVectorLayer(u8"E:\\TestImage\\全国省界\\全国省界.shp", u8"省界");
头文件<qgsvectorlayer.h>
创建 QgsVectorLayer
的实例。该类在 QGIS 中描绘一个矢量图层,是 QgsMapLayer
的子类。
继承关系如下
构造函数原型为
cpp
QgsVectorLayer::QgsVectorLayer (
const QString & path = QString(),
const QString & baseName = QString(),
const QString & providerLib = "ogr",
const QgsVectorLayer::LayerOptions & options = QgsVectorLayer::LayerOptions()
)
path为参数的路径或url,baseName为在图例中展示的图层名称,
参见QGIS API Documentation: QgsVectorLayer Class Reference
图层创建完成后,可调用 isValid()
方法查看是否创建成功。
cpp
// 确认图层是否创建成功
qDebug() << "Is layer valid:" << pVectorLayer->isValid();
该方法位于QgsVectorLayer的父类QgsMapLayer中,返回图层的状态,创建成功则返回True,否则返回False。如果返回False,则可以通过QgsMapLayer的error()方法进步查看错误详情。
(六)
cpp
// 将图层添加到画布上
c.setLayers(QList<QgsMapLayer*>() << pVectorLayer);
图层创建成功后,将其添加到画布。调用画布类 QgsMapCanvas
的 setLayers()
方法即可,该方法会设置一个将在画布上面显示的图层列表。
函数原型如下,参见 QGIS API Documentation: QgsMapCanvas Class Reference
cpp
void QgsMapCanvas::setLayers(const QList< QgsMapLayer * > & layers)
该方法接受一个图层基类 QgsMapLayer
指针的列表。通常情况下,图层越位于列表前面(即下标越小),绘制顺序越靠后(即越靠近观察者)。
(七)
cpp
// 设置画布窗体标题并显示画布
// 画布本身是 QWidget 的子类,因此可以承担 QWidget 的所有操作
c.setWindowTitle(u8"QGIS 二次开发:画布");
c.show();
在 Qt 中,只要是 QWidget
及其子类都可以作为单独的程序窗体处理。QgsMapCanvas
作为 QGraphicsView
的子类,当然也是QWidget的子类,我们可以使用QWidget的公共槽函数setWindowTitle()为其设置窗口标题,然后使用show()让其像普通的窗口一样显示出来。
(八)
cpp
// 缩放到图层的空间范围
c.zoomToFullExtent();
调用QgsMapCanvas的zoomToFullExtent(),这一步操作会让 QgsMapCanvas 缩放到内部所有可见图层的完整范围,就是让所有可见图层都完整地显示出来。
参见 QGIS API Documentation: QgsMapCanvas Class Reference
(九)
cpp
// 启动 QgsApplication 实例
return app.exec();
最后,启动 QgsApplication (即 QApplication)。exec()
方法位于QgsApplication的父类QApplication中,目的是让程序进入主循环。主循环被打断后(如所有窗口关闭),程序结束。