開發環境:Win10 + VS2010 + Qt 4.8.6 + QGis 2.14.4
簡單介紹下如何用C++方式實現QGis中圖層分類顯示的方法。
要實現圖層的分類顯示主要會用到QgsCategorizedSymbolRendererV2類,這個類是一個簡單的符號分類渲染器,該類是從QgsFeatureRendererV2繼承而來,大家可以看下幫助文檔中的截圖:
QgsCategorizedSymbolRendererV2是其中一個子類,其他還有幾個類似的子類,而這些子類的渲染方式就是對應的QGis中的幾種不同的分類方式:
所以如果掌握了其中一種分類方式的用法,其他幾種都是大同小異。下面要介紹的就是上圖中的第3種方式,用法簡單,但是也是平時用得最多的一種方式。
1、先說下如何簡單的根據指定圖層字段創建分類。先上一小段代碼,再來慢慢說:
1 QgsCategoryList cats; 2 QgsFeature f; 3 QgsFeatureIterator it = mLayer->getFeatures(); 4 while (it.nextFeature(f)) 5 6 cats << QgsRendererCategoryV2(f.attribute("編號"), 7 unlinkedSymbolV2(), f.attribute("編號").toString()); 8 } 9 10 mLayer->setRendererV2( new QgsCategorizedSymbolRendererV2("編號", cats) );
說明下mLyaer是准備處理的一個有效的QgsVectorLayer對象。
先看最后一句,通過圖層的setRendererV2(QgsFeatureRendererV2*)便可以修改該圖層的渲染方式,我們的目的就達到了,不過要詳細說下傳遞的參數,要傳遞的參數就是上面提到的從QgsFeatureRendererV2繼承而來的渲染器子類,我是直接通過兩個參數來new了一個QgsCategorizedSymbolRendererV2對象:
第一個參數是圖層中已有的字段名稱,這里我使用矢量圖層中叫”編號”的字段來進行分類;
第二個參數是一個QgsCategoryList對象,它其實是一個別名,本質上是QList<QgsRendererCategoryV2>,這個列表里保存的是與字段內容相對應的對象。QgsRendererCategoryV2是用於管理每個分類對象符號的類,通過一個圖來看比較好理解,下圖中顯示了3種分類,每個分類就是一個單獨的QgsRendererCategoryV2,它所顯示的名稱、顏色、符號等等都是通過QgsRendererCategoryV2來管理的。
接着看上面在while循環中我通過遍歷圖層中的要素,創建QgsRendererCategoryV2對象,並保存到List中,第一個參數是設置對象的值,直接返回圖層中“編號”字段的值來填充;第三個參數是設置一個顯示的標簽,我直接就使用與第一個參數相同的值來設置;第二個參數是一個指向QgsSymbolV2的對象,該類主要用於管理符號,顯示的顏色、符號、透明度這些就是通過這個參數來設置,這里我是同過一個單獨的函數來返回這個對象,這個unlinkedSymbolV2()函數內容如下:
1 QgsSymbolV2* unlinkedSymbolV2() 2 { 3 QgsSymbolV2* mUnlinkedSymbolV2; 4 5 // 獲得缺省的符號 6 mUnlinkedSymbolV2 = QgsSymbolV2::defaultSymbol(mLayer->geometryType()); 7 8 // 設置透明度與顏色 9 mUnlinkedSymbolV2->setAlpha(0.5); 10 mUnlinkedSymbolV2->setColor(cUnlinked); 11 12 return mLinkedSymbolV2->clone(); 13 } 14
這個符號類提供一個靜態defaultSymbol函數可返回一個默認的符號對象,傳入一個幾何類型以返回對應的幾何類型符號,然后通過setAlpha及setColor修改下符號的透明度及顏色,最后返回一個符號類指針的副本。
這是處理前的截圖:
這是處理后的截圖:
2、最后再說下已經像上面分類好了,怎么進行更新。
1 // 獲得目前圖層的分類樣式符號渲染器 2 QgsCategorizedSymbolRendererV2* cRenderer; 3 cRenderer = dynamic_cast< QgsCategorizedSymbolRendererV2* > 4 ( mLayer->rendererV2() ); 5 if (!cRenderer) 6 { 7 return; 8 } 9 // 在渲染器中查找是否有對應的編號 10 int index = cRenderer->categoryIndexForValue(QVariant("1")); 11 12 // 更新 13 if (-1 != index) 14 { 15 cRenderer->deleteCategory(index); 16 cRenderer->addCategory(QgsRendererCategoryV2 17 (QVariant("1"), linkedSymbolV2(), "1")); 18 }
首先獲得圖層的渲染器類,如果之前圖層沒有進行過分類,將會得到一個空指針。
之前我們在構造QgsRendererCategoryV2對象時不是用“編號”字段的內容設置了它的值嗎,現在就可以通過categoryIndexForValue函數來返回索引,找到正確的索引后先刪除原來記錄,再通過addCategory添加一個新的對象進去,這里我同樣通過調用一個linkedSymbolV2()返回符號,和unlinkedSymbolV2()不同的地方就是顏色改變了,所以就不貼代碼了。
更新完后還會有個小問題,會發現新添加的分類符號都顯示在最后,顯示順序和之前不一樣了,可以用下面這個方法按值重新排序。
1 cRenderer->sortByValue();
關於圖層分類顯示基本上就這樣了,其實涉及代碼不多,應該還是好理解,其他幾種分類渲染方式都大同小異。