您的位置:首页 > 其它

qgis二次开发之开发环境搭建

2015-01-30 23:01 281 查看
首先是qgis的文档地址:http://docs.qgis.org/2.6/en/docs/user_manual/working_with_vector/vector_properties.html

qgis2的开发和qgsi1的开发的api有很大的差别,例如网上的浏览量很大的博客http://blog.csdn.net/kkk328/article/details/7720119 我试过,按照他的方法来进行开发,无法实现。必须推到重新来看代码进行开发。

这篇博客的目标是在地图上显示两个个gps点。首先看一下效果:



1.把上篇博客生成的dll文件、lib文件、include文件放到一个固定的目录中。

2.建立一个qt aplication工程。

3.首先运行一下,看看qt是否正确。我的工程在没有做任何改动的情况下,运行界面如下:



3.配置工程的include、lib路径。





4.添加附加依赖库:

qgis_analysis.lib

qgis_core.lib

qgis_gui.lib

5.开始编写代码。

由于qgs有些宏在Windows平台上没有定义,所以要在预定义一些宏:

GUI_EXPORT=__declspec(dllimport)
ANALYSIS_EXPORT=__declspec(dllimport)
CORE_EXPORT=__declspec(dllimport)


1》在qgistest_showdot_1.h文件中定义一个地图画布类成员变量m_pMapCanvas和一个QList<QgsMapCanvasLayer> m_LayerSet;  //地图画布图层集。

m_pMapCanvase用来渲染地图,显示地图用的。m_pLayerSet用来盛放图层集的,因为一般来说,地图不会一个图层的。

2>首先应该初始化qgis的环境,这里初始化首先应该是初始化qgis的provider,provider的功能包括:协议、数据库驱动。如果没有找到provider,qgis将不能加载vector layer的数据,在vectorlayer的构造函数中会调用provider,provider会调用这些dll文件。

QString myPluginsDir;

myPluginsDir=QCoreApplication::applicationDirPath()+"/plugins";//这是plugin的存放路径,我的plugin放在exe所在的/plugins目录下,
/*使用mypluginsdir加载dll。下面是得到一个实例,在实例中主要是加载各种的proder .
如果程序查找目录下没有dll文件存在,就会出现“No vector layers can be loaded. Check your QGIS installation”的警告信息,
在创建图层的时候就会失败。在刚刚开始做qgis二次开发的时候,很容易在这里出错。
*/
QgsProviderRegistry *provider = QgsProviderRegistry::instance(myPluginsDir);

下面是qgsproviderregistry的构造函数的注释

QgsProviderRegistry::QgsProviderRegistry( QString pluginPath )//provider的注册类的构造函数
{
// At startup, examine the libs in the qgis/lib dir and store those that
// are a provider shared lib
// check all libs in the current plugin directory and get name and descriptions
//TODO figure out how to register and identify data source plugin for a specific
//TODO layer type
#if 0//if0,自然废弃了。
char **argv = qApp->argv();
QString appDir = argv[0];
int bin = appDir.findRev( "/bin", -1, false );
QString baseDir = appDir.left( bin );
QString mLibraryDirectory = baseDir + "/lib";
#endif
mLibraryDirectory = pluginPath;//搜索的路径。
mLibraryDirectory.setSorting( QDir::Name | QDir::IgnoreCase );
mLibraryDirectory.setFilter( QDir::Files | QDir::NoSymLinks );

#if defined(WIN32) || defined(__CYGWIN__)
mLibraryDirectory.setNameFilters( QStringList( "*.dll" ) );
#elif ANDROID
mLibraryDirectory.setNameFilters( QStringList( "*provider.so" ) );
#else
mLibraryDirectory.setNameFilters( QStringList( "*.so" ) );
#endif

QgsDebugMsg( QString( "Checking %1 for provider plugins" ).arg( mLibraryDirectory.path() ) );

if ( mLibraryDirectory.count() == 0 )
{
QString msg = QObject::tr( "No QGIS data provider plugins found in:\n%1\n" ).arg( mLibraryDirectory.path() );
msg += QObject::tr( "No vector layers can be loaded. Check your QGIS installation" );

QgsMessageOutput* output = QgsMessageOutput::createMessageOutput();
output->setTitle( QObject::tr( "No Data Providers" ) );
output->setMessage( msg, QgsMessageOutput::MessageText );
output->showMessage();
return;
}

QListIterator<QFileInfo> it( mLibraryDirectory.entryInfoList() );//得到目录中所有的文件列表。
while ( it.hasNext() )
{
QFileInfo fi( it.next() );

QLibrary myLib( fi.filePath() );//加载成为Qlibrary;
if ( !myLib.load() )//加载失败的话,直接continue。
{
QgsDebugMsg( QString( "Checking %1: ...invalid (lib not loadable): %2" ).arg( myLib.fileName() ).arg( myLib.errorString() ) );
continue;
}

//MH: Added a further test to detect non-provider plugins linked to provider plugins.
//Only pure provider plugins have 'type' not defined
isprovider_t *hasType = ( isprovider_t * ) cast_to_fptr( myLib.resolve( "type" ) );
if ( hasType )
{
QgsDebugMsg( QString( "Checking %1: ...invalid (has type method)" ).arg( myLib.fileName() ) );
continue;
}

// get the description and the key for the provider plugin
isprovider_t *isProvider = ( isprovider_t * ) cast_to_fptr( myLib.resolve( "isProvider" ) );
if ( !isProvider )//rruguo如果不是provider类型的就输出调试信息,
{
QgsDebugMsg( QString( "Checking %1: ...invalid (no isProvider method)" ).arg( myLib.fileName() ) );
continue;
}

// check to see if this is a provider plugin
if ( !isProvider() )//这个if是多余的,目的就是为了输出调试信息。
{
QgsDebugMsg( QString( "Checking %1: ...invalid (not a provider)" ).arg( myLib.fileName() ) );
continue;
}

// looks like a provider. get the key and description,得到描述
description_t *pDesc = ( description_t * ) cast_to_fptr( myLib.resolve( "description" ) );
if ( !pDesc )//
{
QgsDebugMsg( QString( "Checking %1: ...invalid (no description method)" ).arg( myLib.fileName() ) );
continue;
}
//得到provider 的key
providerkey_t *pKey = ( providerkey_t * ) cast_to_fptr( myLib.resolve( "providerKey" ) );
if ( !pKey )
{
QgsDebugMsg( QString( "Checking %1: ...invalid (no providerKey method)" ).arg( myLib.fileName() ) );
continue;
}

// add this provider to the provider map
mProviders[pKey()] = new QgsProviderMetadata( pKey(), pDesc(), myLib.fileName() );

// load database drivers,加载driver
databaseDrivers_t *pDatabaseDrivers = ( databaseDrivers_t * ) cast_to_fptr( myLib.resolve( "databaseDrivers" ) );
if ( pDatabaseDrivers )
{
mDatabaseDrivers = pDatabaseDrivers();
}

// load directory drivers
directoryDrivers_t *pDirectoryDrivers = ( directoryDrivers_t * ) cast_to_fptr( myLib.resolve( "directoryDrivers" ) );
if ( pDirectoryDrivers )
{
mDirectoryDrivers = pDirectoryDrivers();
}

// load protocol drivers加载协议驱动
protocolDrivers_t *pProtocolDrivers = ( protocolDrivers_t * ) cast_to_fptr( myLib.resolve( "protocolDrivers" ) );
if ( pProtocolDrivers )
{
mProtocolDrivers = pProtocolDrivers();
}

// now get vector file filters, if any
fileVectorFilters_t *pFileVectorFilters = ( fileVectorFilters_t * ) cast_to_fptr( myLib.resolve( "fileVectorFilters" ) );
if ( pFileVectorFilters )
{
QString fileVectorFilters = pFileVectorFilters();

if ( !fileVectorFilters.isEmpty() )
mVectorFileFilters += fileVectorFilters;

QgsDebugMsg( QString( "Checking %1: ...loaded ok (%2 file filters)" ).arg( myLib.fileName() ).arg( fileVectorFilters.split( ";;" ).count() ) );
}

// now get raster file filters, if any
// this replaces deprecated QgsRasterLayer::buildSupportedRasterFileFilter
buildsupportedrasterfilefilter_t *pBuild =
( buildsupportedrasterfilefilter_t * ) cast_to_fptr( myLib.resolve( "buildSupportedRasterFileFilter" ) );
if ( pBuild )
{
QString fileRasterFilters;
pBuild( fileRasterFilters );

QgsDebugMsg( "raster filters: " + fileRasterFilters );
if ( !fileRasterFilters.isEmpty() )
mRasterFileFilters += fileRasterFilters;

QgsDebugMsg( QString( "Checking %1: ...loaded ok (%2 file filters)" ).arg( myLib.fileName() ).arg( fileRasterFilters.split( ";;" ).count() ) );
}
}
} // QgsProviderRegistry ctor


3》初始化画布。

地图显示最重要的一个部分,这一步在qgis中很简单。主要就是new一个,然后设置它的高宽就ok了。

//位于gui模块。它继承自QGraphicsView,是显示的容器。
m_pMapCanvas = new QgsMapCanvas(this);
//设置为可以见。
m_pMapCanvas->show();
//设置宽度和高度,这是调用的qt的接口。
m_pMapCanvas->setFixedHeight(this->height());
m_pMapCanvas->setFixedWidth(this->width());


4》初始化图层-vectorLayer。

/*
qgsvectorLayer的构造函数:
QgsVectorLayer::QgsVectorLayer	(	QString 	path = QString::null,
QString 	baseName = QString::null,
QString 	providerLib = QString::null,
bool 	loadDefaultStyleFlag = true
)
参数介绍:1.path是数据的提供的路径。应该和providerLib参数混合使用。
2.baseName这个参数,是用来标示这个图层的名字。可以任意命名。(我没有使用中文命名过)
3.providerLib是数据的提供者的标示:qgis2.4支持的数据提供者是:
(1)Memory data providerType内存数据提供者。标示符是: "memory",如果想使用内存数据,那么providerLib="memory"。
对应的path可以有:"point", "linestring", "polygon", "multipoint","multilinestring","multipolygon"
(2)OGR data provider (ogr)
(3)Spatialite data provider (spatialite).sqlite数据库的改进版,以适用于存储gis数据。可以使用 QgsDataSourceURI类来产生对应的path
(4)Postgresql data provider (postgres)可以使用QgsDataSourceURI 类来产生path
(5)Microsoft SQL server data provider (mssql)可以使用QgsDataSourceURI 类来产生path
(6)SQL Anywhere data provider (sqlanywhere)可以使用QgsDataSourceURI 类来产生path
(7)Delimited text file data provider (delimitedtext)
(8)GPX data provider (gpx)
(9)Grass data provider (grass)
4.最后一个参数是是否使用默认的style。
*/
QgsVectorLayer *pGeneralPointLayer = new QgsVectorLayer("Point", "MemoryTestMap", "memory");

//返回值是:"Memory storage"说明创建成功了。
QString storageName = pGeneralPointLayer->storageType();

//这个layer的功能,例如cap的返回值是:
//"Add Features, Delete Features, Change Attribute Values, Add Attributes, Delete Attributes, Create Spatial Index, Fast Access to Features at ID, Change Geometries"
QString cap = pGeneralPointLayer->capabilitiesString();
/*
检验创建出的图层是否可以使用
*/
if(!pGeneralPointLayer->isValid())//new出来的图层无效
Q_ASSERT(false);

上面的代码就把图层初始化完毕了。

5.把图层和画布关联

//创建画布图层对象,使图层与画布图层相关联
QgsMapCanvasLayer canVasLayer(pGeneralPointLayer);
m_LayerSet.append(canVasLayer);
//设置画布图层对象set
m_pMapCanvas->setLayerSet(m_LayerSet);

6.
//设置图层绘制器
QgsMapLayerRegistry::instance()->addMapLayer(pGeneralPointLayer);

7.向图层中添加点。
//添加2个点
pGeneralPointLayer->startEditing();
QgsPoint point(5,5);
QgsFeature f =QgsFeature(pGeneralPointLayer->pendingFields(),0);
QgsGeometry *pGeom=QgsGeometry::fromPoint(point);

f.setGeometry(pGeom);
pGeneralPointLayer->addFeature(f);
point.setX(4);
point.setY(4);
pGeom = QgsGeometry::fromPoint(point);
f.setGeometry(pGeom);
pGeneralPointLayer->addFeature(f);
pGeneralPointLayer->commitChanges();

8.对画布进行缩放,更新
m_pMapCanvas->setExtent(pGeneralPointLayer->extent());
m_pMapCanvas->zoomOut();
m_pMapCanvas->refresh();

完毕2015.2.11
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: