開發環境:Win10 + VS2010 + Qt 4.8.6 + QGis 2.14.4html
其實本文實現的功能相似於QGis中「添加文本數據圖層」的一個簡化版,本文不會涉及到對話框的使用,不經過與用戶互交的方式建立要素,而是直接經過代碼方式添加點要素,起到一個拋磚引玉的做用。app
(一)先將整個流程大概梳理下:分佈式
一、首先建立一個臨時(memory)矢量圖層 ;ide
二、將建立的圖層添加到地圖畫布中 ;測試
三、建立幾何要素 ;ui
四、將幾何要素添加到矢量圖層中 ;編碼
五、更新圖層範圍並刷新畫布 .spa
(二)程序代碼:指針
// 測試代碼 /* "Point?crs=EPSG:4326&field=id:integer& * field=name:string(50)&index=yes& * memoryid={63152c31-9f38-4410-9983-fc9abe84973f}" */ QString layerProperties = "Point?"; // 幾何類型 layerProperties.append(QString( "crs=EPSG:4326&" )); // 參照座標系 layerProperties.append(QString( "field=id:integer&field=name:string(50)&" )); // 添加字段 layerProperties.append(QString( "index=yes&" )); // 建立索引 layerProperties.append(QString( // 臨時編碼 "memoryid=%1" ).arg( QUuid::createUuid().toString() )); QgsVectorLayer* newLayer = new QgsVectorLayer( layerProperties, QString( "臨時點層" ), QString( "memory" ) ); if (!newLayer->isValid()) { return false; } // 添加到地圖 QgsMapLayerRegistry::instance()->addMapLayer(newLayer); QgsVectorDataProvider* dateProvider = newLayer->dataProvider(); // 建立點 QgsFeature MyFeature; MyFeature.setGeometry( QgsGeometry::fromPoint(QgsPoint(102.4443, 32.2123)) ); MyFeature.setAttributes(QgsAttributes() << QVariant(1) << QVariant("test")); QgsFeature MyFeature1; MyFeature1.setGeometry( QgsGeometry::fromPoint(QgsPoint(102.4643, 32.2133)) ); MyFeature1.setAttributes(QgsAttributes() << QVariant(2) << QVariant("test1")); // 開始編輯 newLayer->startEditing(); // 添加要素 dateProvider->addFeatures(QgsFeatureList() << MyFeature << MyFeature1); // 保存 newLayer->commitChanges(); // 更新範圍 newLayer->updateExtents(); mMapCanvas->refresh(); return true;
(三)代碼分析:code
建立臨時圖層
第3-11行,這段代碼多是我與網上其餘的教程中比較不同的地方,這裏經過構造一種URL形式的字符串,經過上面的註釋你們應該都大概明白這個字符串的意思了,經過這種形式很簡潔方便的使咱們將要建立的圖層具有了多個條件,特別是簡化對於圖層字段的添加:
第7行 QString layerProperties = "Point?" 定義了咱們建立圖層的幾何類型,能夠是"Point"、"LineString"、"Polygon"、"MultiPoint"、"MultiLineString"、"MultiPolygon"其中之一;
第8行 QString( "crs=EPSG:4326&" ) 是圖層的參照座標系,定義一個正確的座標系是一個良好的習慣,若是須要必定靈活性能夠參照QGis的方式經過對話框選取,或是根據本身的需求來實現,須要改變的僅僅是"EPSG:4326" 而已;
第8行 QString( "field=id:integer&field=name:string(50)&" ) 是定義的圖層字段,這也是我以爲很方便的一個地方,多個字段用"&" 進行鏈接,完整形式爲 field=name:type(length,precision) ,從參數看不只能夠定義長度還能夠定義其精度;
第10行 QString( "index=yes&" ) 是定義空間索引,對於數據量較大的圖層頗有用;
第11行 QString( "memoryid=%1" ).arg( QUuid::createUuid().toString() ) 比較有趣,它經過QUuid建立了一個全局惟一標識符(UUID),Qt中解釋主要是用於分佈式計算環境中的實體標識,而此處是用於當咱們屢次建立臨時圖層時的惟一標識符;
第3-5行就是一個URL形式字符串的完整展現,包含上述的全部內容,最後{}中一串數字就是經過QUuid自動建立的標識。雖然我沒有嘗試過,可是應該除了幾何類型必需要定義之外,其餘的都是可選項,固然若是咱們採用這種方式確定不只僅是定義一個圖層的幾何類型而已。
上面準備工做說了不少,第13行才真正建立臨時圖層:
QgsVectorLayer* newLayer = new QgsVectorLayer( layerProperties, QString( "臨時點層" ), QString( "memory" ) );
QgsVectorLayer類有3個參數,第1個參數就是URL形式的字符串layerProperties,另外常常用的一種很簡單的方式就是直接定義其圖層的幾何類型便可,如"Point";第2個參數是圖層的名稱;第3個參數是建立圖層的類型,這裏傳入的"memory"表明建立的是一個臨時圖層。
將圖層添加到地圖畫布中
第2一、23行將才建立的圖層添加到地圖畫布中,而且得到一個QgsVectorDataProvider指針,該指針在後面會用到。
建立幾何要素
第25-32行建立了兩個點要素來展現結果,網上的不少例子爲了讓你們更清楚,是分開寫的,我這個比較省事:
MyFeature.setGeometry( QgsGeometry::fromPoint(QgsPoint(102.4443, 32.2123)) );
使用setGeometry()設置了要素的幾何體後,就繼續用setAttributes()寫入屬性,屬性類型、順序與上面咱們建立的是一致的,setAttributes()的參數是QgsAttributes對象,而QgsAttributes其實就是QVector<QVariant>,所用我下面代碼中是添加的QVariant對象。
MyFeature.setAttributes(QgsAttributes() << QVariant(1) << QVariant("test"));
經過上面的兩行代碼就成功建立了幾何要素並設置了它的屬性。
添加幾何要素到矢量圖層中
第34-41行咱們利用上面得到的QgsVectorDataProvider指針將幾何要素添加到了矢量圖層中,咱們先使用startEditing()來使圖層可編輯,而後使用commitChanges()來提交改變結果。
刷新
最後更新圖層範圍,並刷新畫布就OK了。
在這裏多說一句,若是你按照此方法運行後,在地圖畫布上不能正常顯示,檢查下畫布是否沒有解凍,就是:mapCanvas()->freeze( false ) ,我以前在這吃了虧,因爲才接觸QGis開發不久,我在程序的其餘地方將畫布凍結了,致使圖層不能正常顯示,本身搗鼓了不少次才發現。
(四)效果圖: