一直在忙别的事情,有很长一段时间没有做QGis。(忙着毕业,老师还要我写SCI,着实不容易。)在QGis的QQ群中很多初学者同学提出的一些问题,也没有怎么帮到大家,在这里讲一声抱歉了。(顺带宣传一下,QGis二次开发交流QQ群:68016799。)我也仅仅是刚入门而已,希望能够跟共同喜欢探索、喜欢开发的同学共交流。
写在前面,QGis源码编译请看这里 – QGis2.9.0源码编译及二次开发包下载, 二次开发环境配置请看这里 – qgis二次开发环境配置
今天正好有空,就想写一个非常基础的二次开发教程给大家。这篇博文,是为了解决大家在QGis二次开发学习过程中的一个非常基础的问题 – “显示数据”(没错,就是这么基础,任性!)。这里面涉及的东西确实是非常基础、非常简单的,但正是这么简单的东西也难倒了好一些同学,确实因为QGis的资料太少,现有的又大多比较陈旧、不适用。很多同学好不容易终于成功编译了QGis的源代码,然后就不知道怎么办了,找不到教程或者找到的教程都不能用。我在群里看到很多同学刚加进来就是为了要问一下“显示数据”的问题,可见这个问题虽然基础,但有一个可用的教程,总好过没有,能省去大家一点点时间纠结,也算是一种贡献吧。
进入正题。
首先,新建一个Qt Application工程,随便取个名字,就叫“qgis_dev”吧。
配置工程,见下图:
建立好工程之后,应该是这个样子的
有一个.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,或者对什么功能感兴趣可以留言,共同交流,谢谢阅读。
暂无评论内容