QGis 二次开发基础 -- 显示数据

来源:互联网 发布:淘宝漏洞q币充值的网站 编辑:程序博客网 时间:2024/05/16 18:21

一直在忙别的事情,有很长一段时间没有做QGis。(忙着毕业,老师还要我写SCI,着实不容易。)在QGis的QQ群中很多初学者同学提出的一些问题,也没有怎么帮到大家,在这里讲一声抱歉了。(顺带宣传一下,QGis二次开发交流QQ群:68016799。)我也仅仅是刚入门而已,希望能够跟共同喜欢探索、喜欢开发的同学共交流。

写在前面,QGis源码编译请看这里 – QGis2.9.0源码编译及二次开发包下载, 二次开发环境配置请看这里 – qgis二次开发环境配置


今天正好有空,就想写一个非常基础的二次开发教程给大家。这篇博文,是为了解决大家在QGis二次开发学习过程中的一个非常基础的问题 – “显示数据”(没错,就是这么基础,任性!)。这里面涉及的东西确实是非常基础、非常简单的,但正是这么简单的东西也难倒了好一些同学,确实因为QGis的资料太少,现有的又大多比较陈旧、不适用。很多同学好不容易终于成功编译了QGis的源代码,然后就不知道怎么办了,找不到教程或者找到的教程都不能用。我在群里看到很多同学刚加进来就是为了要问一下“显示数据”的问题,可见这个问题虽然基础,但有一个可用的教程,总好过没有,能省去大家一点点时间纠结,也算是一种贡献吧。
进入正题。
首先,新建一个Qt Application工程,随便取个名字,就叫“qgis_dev”吧。
新建工程

配置工程,见下图:
配置工程
配置工程2

建立好工程之后,应该是这个样子的
工程面板

有一个.ui的文件,是主界面,qgis_dev.h 和qgis_dev.cpp是控制这个主界面的Qt类。
这个时候需要配置QGis的开发环境,这个我在之前的博客中讲过了,步骤是一致的,就不赘述了。不清楚的同学可以参见这里–qgis二次开发环境配置。
双击那个 qgis_dev.ui 的文件,会打开Qt Designer,进行界面的设计。这里我们主要关注菜单的设计就行了,毕竟这部分都是Qt的知识,我想大家应该是比较清楚的吧。我主要添加了两个Action,分别是Vector菜单下的Add Vector 功能,以及Raster菜单下的Add Raster功能。今天也就只说这两个的功能的实现问题。
这里写图片描述
这里写图片描述

保存好这个UI,然后关闭Qt Designer,回到VS环境中。
打开qgis_dev.h将代码修改如下。(先贴源码,后面再详细分析源码中的语句)

#ifndef QGIS_DEV_H#define QGIS_DEV_H#include <QtGui/QMainWindow>#include "ui_qgis_dev.h"#include <QList>// QGis include#include <qgsmapcanvas.h>#include <qgsmaplayer.h>class qgis_dev : public QMainWindow{    Q_OBJECTpublic:    qgis_dev( QWidget *parent = 0, Qt::WFlags flags = 0 );    ~qgis_dev();public slots:    /**     *  添加矢量图层     *     * @return void -    **/    void addVectorLayers();    /**     * 添加栅格图层     *     * @return void -    **/    void addRasterLayers();private:    Ui::qgis_devClass ui;    QgsMapCanvas* mapCanvas; // 地图画布    QList<QgsMapCanvasLayer> mapCanvasLayerSet; // 地图画布所用的图层集合};#endif // QGIS_DEV_H

然后是qgis_dev.cpp文件

#include "qgis_dev.h"#include <QDialog>#include <QFileDialog>#include <QMessageBox>// QGis include#include <qgsvectorlayer.h>#include <qgsmaplayerregistry.h>#include <qgsrasterlayer.h>qgis_dev::qgis_dev( QWidget *parent, Qt::WFlags flags )    : QMainWindow( parent, flags ){    ui.setupUi( this );    mapCanvas = new QgsMapCanvas( );    this->setCentralWidget( mapCanvas );    mapCanvas->enableAntiAliasing( true );    mapCanvas->setCanvasColor( QColor( 255, 255, 255 ) );    mapCanvas->setVisible( true );    // connections    connect( ui.actionAdd_Vector, SIGNAL( triggered() ), this, SLOT( addVectorLayers() ) );    connect( ui.actionAdd_Raster, SIGNAL( triggered() ), this, SLOT( addRasterLayers() ) );}qgis_dev::~qgis_dev(){}void qgis_dev::addVectorLayers(){    QString filename = QFileDialog::getOpenFileName( this, tr( "open vector" ), "", "*.shp" );    QStringList temp = filename.split( QDir::separator() );    QString basename = temp.at( temp.size() - 1 );    QgsVectorLayer* vecLayer = new QgsVectorLayer( filename, basename, "ogr", false );    if ( !vecLayer->isValid() )    {        QMessageBox::critical( this, "error", "layer is invalid" );        return;    }    QgsMapLayerRegistry::instance()->addMapLayer( vecLayer );    mapCanvasLayerSet.append( vecLayer );    mapCanvas->setExtent( vecLayer->extent() );    mapCanvas->setLayerSet( mapCanvasLayerSet );    mapCanvas->setVisible( true );    mapCanvas->freeze( false );    mapCanvas->refresh();}void qgis_dev::addRasterLayers(){    QString filename = QFileDialog::getOpenFileName( this, tr( "open vector" ), "", "*.tif" );    QStringList temp = filename.split( QDir::separator() );    QString basename = temp.at( temp.size() - 1 );    QgsRasterLayer* rasterLayer = new QgsRasterLayer( filename, basename, "gdal", false );    if ( !rasterLayer->isValid() )    {        QMessageBox::critical( this, "error", "layer is invalid" );        return;    }    QgsMapLayerRegistry::instance()->addMapLayer( rasterLayer );    mapCanvasLayerSet.append( rasterLayer );    mapCanvas->setExtent( rasterLayer->extent() );    mapCanvas->setLayerSet( mapCanvasLayerSet );    mapCanvas->setVisible( true );    mapCanvas->freeze( false );    mapCanvas->refresh();}

最后是main.cpp文件

#include<QtGui/QApplication>#include<qgsapplication.h>#include<QApplication>#include "qgis_dev.h"int main( int argc, char *argv[] ){    QgsApplication myApp( argc, argv, true );    QgsApplication::setPrefixPath( "C:/Program Files/qgis2.9.0", true ); // 注意:把这里的路径改成你电脑上Qgis的路径!!!    QgsApplication::initQgis();    qgis_dev* myQgis = new qgis_dev();    myQgis->show();    return myApp.exec();}

OK,讲完了,直接运行应该就可以了,如果debug模式报错,试试release模式,有些同学用的QGis二次开发包不同,所以区分debug和release的。不过记住切换模式的时候,项目的开发属性需要重新配置。

现在分析下里面的核心代码以及比较容易出错的地方。
首先是main函数中的前三句

 QgsApplication myApp( argc, argv, true ); QgsApplication::setPrefixPath( "C:/Program Files/qgis2.9.0", true ); // 注意:把这里的路径改成你电脑上Qgis的路径!!! QgsApplication::initQgis();

这个是QGis2.0版本以后的启动方式,其中setPrefixPath这个方法里面的路径是QGis的文件夹路径,这个函数的作用在QGis源代码中是这样的
这里写图片描述

可见这个路径是为了加载一些QGis文件夹中的路径,这里我们主要关注上图中标红的那句,也就是我们的plugin文件夹路径,加载数据必须加载的ogrprovider.dll以及gdalprovider.dll这两个文件都是在plugin文件夹下,因此这个路径没有配置正确,会存在加载数据失败的问题。
然后是QgsApplication::initQgis() 这个方法,源代码中的定义如下
这里写图片描述
也就是通过上面设置的插件路径来加载插件了。

在显示数据的部分,我们主要关心qgis_dev.cpp的addVectorLayers()这个方法,其中
QgsVectorLayer* vecLayer = new QgsVectorLayer( filename, basename, “ogr”, false );
这一句新建矢量图层,filename是矢量文件绝对路径,basename是名称。建立了图层以后,需要在图层管理中注册,也就是
QgsMapLayerRegistry::instance()->addMapLayer( vecLayer );
而要显示,则要加入到地图画布的图层集合中,这里的图层集合是由QList mapCanvasLayerSet;定义的,因此后面这句就比较明确了
mapCanvasLayerSet.append( vecLayer );
之后,就是将这个图层集合与地图画布关联起来,并设置相应的属性,刷新就能显示了

mapCanvas->setExtent( vecLayer->extent() );mapCanvas->setLayerSet( mapCanvasLayerSet );mapCanvas->setVisible( true );mapCanvas->freeze( false );mapCanvas->refresh();

后面的Raster图层的添加方式与这个类似,大家看代码应该就明白了。
最后,贴上工程的显示效果吧,支持漫游哦。
这里写图片描述

OK,先这样吧,放一个框架在这里,有空的话再把这个例子深入下去。大家有什么问题可以加QQ群:68016799,或者对什么功能感兴趣可以留言,共同交流,谢谢阅读。

0 0
原创粉丝点击