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

一直在忙别的事情,有很长一段时间没有做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_OBJECT

public:
    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,或者对什么功能感兴趣可以留言,共同交流,谢谢阅读。

© 版权声明
THE END
喜欢就支持一下吧
点赞669 分享
评论 抢沙发
头像
欢迎您留下宝贵的见解!
提交
头像

昵称

取消
昵称表情代码图片

    暂无评论内容