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

首先是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

  • 0
    点赞
  • 9
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值