1. 程式人生 > 其它 >QGis外掛編寫-GeocodeCN

QGis外掛編寫-GeocodeCN

 

以前寫的外掛記錄,我把它搬到部落格園上來,程式碼已更新許多,以最新為準。

該工具目的是地址轉為座標點(地理編碼),剛開始只是一小段Python指令碼,批量請求百度地圖開放介面進行編碼,這確實滿足了我的需求,不過每次編碼都需要生成csv檔案後再匯入GSI軟體生成向量點圖層檢視,還是不夠簡單高效,於是萌生將其整合到QGis的想法。QGis現存地理編碼外掛,我所知道的,一般是請求開放街道地圖(OSM)的服務,總所周知,OSM作為國外地理資料提供者,可能會存在關於我國領土邊界的問題,所以決定自行寫一個。

1.目標

  • 批量獲取感興趣地址點的百度座標。
  • 自動生成點圖層。

2.準備

在開始編寫之前需要做如下準備:

2.1 安裝外掛

構造外掛——PluginBuildet,過載外掛——PluginReloader

上述兩個外掛在官方外掛倉庫裡沒有獲取到,只能在官網上以將其下載下來,然後以離線方式安裝,地址:https://plugins.qgis.org/

2.2 配置UI工具

UI工具可以是QtCreator或者QtDesigner,後邊要修改UI頁面檔案,我使用的Qgis版本為3.22.0,已經自帶QtDesigner,沒必要再單獨配置。

3.過程

3.1 生成外掛模板

開啟安裝好的PluginBuilder外掛,按照提示把相關資訊填寫好

最後選擇儲存檔案位置,生成相關模板檔案。

3.2 外掛結構

這是官網展示的外掛結構圖,每一個外掛都包含下面所列的檔案,關於每一個檔案的意義也作了說明。

下圖為PluginBuilder生成的模板,它包含了官網所列的必要檔案,如果該外掛移到Qgis外掛目錄下,重啟後就能看到被載入到qgis裡。

3.3 設計UI及編譯資源

啟動QtDesigner,開啟GeocodeCn_dialog_base.ui檔案,根據需求設計介面元素。原始介面只包含【確認】和【取消】按鈕,下圖已設計好。

GeocodeCN_dialog.py檔案會自動將UI檔案編譯為python類,不建議修改UI檔名稱、以及GeocodeCN_dialog的程式碼,除非清楚如何修復它。

新設計一個格式為.png的圖示檔案,替換模板中的icon.png,它是外掛的圖示。

原始圖示 新圖示

圖示經過編譯為.py檔案之後,才能引用,感覺資源編譯這一塊問題出得比較多,因為網上蠻多人在問,目前所知的方法如下:

  • 使用pb_tool1:這是PluginBuilder作者gsherman提供的編譯工具

                1
    pb_tool compile --config config_file.cfg
       
  • 使用pyqt5ac,使用詳情見2

  • 使用pyrcc5

前兩個模組提供有命令列編譯,執行會報錯,看起來不是用的QGis自帶的直譯器,而是本機的預設直譯器,我檔案移動到一個先前建好的虛擬環境裡(前提是安裝PyQt5),執行無問題。

我的編譯方法是藉助pyrcc,在PyCharm中使用pyrcc需要提前配置,具體步驟為:前往 Settings --> Tools --> External Tools

  • Program為pyrcc.exe所在路徑,一般在scripts路徑下
  • Arguments:設定為FileName -o FileNameWithoutExtension_rc.py
  • Working Directory:FileDir

配置完成後,可以一鍵編譯。

下圖是編譯好的外掛圖示在QGis的顯示效果。

3.4 環境配置

完成UI介面,準備編寫邏輯程式碼,由於外掛是在QGis自帶Python直譯器裡執行,所以開始前先配置環境,便於引入相關依賴,此處參考知乎使用者【才華橫溢吳道簡】3的文章。

進入Python控制檯,輸入如下程式碼,可以看到python直譯器所在路徑

            1
QStandardPaths.standardLocations(QStandardPaths.AppDataLocation)
   

在PycCharm中開啟模板所在資料夾,選擇 Settings --> Project --> Project Interpreter

設定路徑為bin資料夾下的【python-qgis.bat],該批處理檔案把QGIS的Python環境都配置好,只要把它設定為直譯器,就不需要再配置別的環境變數。

3.5 程式碼編寫

完整程式碼可訪問獲取:https://gitee.com/ShihanW/geocode-cn

遇到的問題如下:

  • QThread: Destroyed while thread is still running

類似程式碼如下:

原因是在cerate_thread方法內,th作為一個區域性變數,在方法結束之後就結束期生命週期,但是執行緒仍在執行,可以修改th作為類屬性成員。

參考:


1 http://g-sherman.github.io/plugin_build_tool/ 2 https://pypi.org/project/pyqt5ac/ 3 https://zhuanlan.zhihu.com/p/344965380