VS2019、Qt5.12及QGis3.16開發常見問題匯總


       在C++、Qt軟件開發過程中,常常遇到一些編譯錯誤或警告;本文將VS2019、Qt5.12.10和QGis3.16.10的二次開發過程常見的問題做了整理,供大家參考,也便於日后查閱。該內容分為四部分:VS+Qt環境搭配、VS編譯常見問題、Qt常見問題、QGis二次開發常見問題。(轉載請注明出處:https://www.cnblogs.com/1024bytes/p/15464404.html)


一、VS創建Qt項目
      1、安裝VS2019或VS2017,編譯器原則上是越新越好(此貼發布時VS2022測試版已經發布,沒試過有啥新功能),VS選擇需要的組件和編譯器,不用全選。
      2、Qt用5.12版中最新的,我用的是Qt5.12.10(Qt5.15是向Qt6過渡的產品),組件也是根據需求選擇。
      3、VS中要安裝Qt Visual Studio Tools,菜單欄依次選擇“擴展”-“管理擴展”-“聯機”-“Visual Studio Marketplace”,在右側搜索“Qt”,選擇“Qt Visual Studio Tools”,點擊下載,安裝界面彈出后,關閉VS,安裝完成。重啟VS,可在該菜單欄看到菜單“Qt VS Tools”。在該菜單下選擇“Qt Versions”配置Qt路徑;創建界面可由此菜單選擇“Luanch Qt Designer”。
      4、新建項目->Visual C++/跨平台->Qt,選擇Qt Widgets Application。

二、VS編譯常見問題
Q: “M_PI”: 未聲明的標識符
A: 程序中頭文件的選擇,要選擇math.h頭文件,在cmath文件中是沒有對M_PI 的定義的(現在的cmath中對M_PI好像已有定義)。選擇“項目”——>”XXX屬性"——>配置屬性——>C/C++——>預處理器——>預處理器定義,將“_USE_MATH_DEFINES”添加進去。

Q: 源代碼字符編碼問題: Warning C4819 該文件包含不能在當前代碼頁(936)中表示的字符,請將該文件保存為 Unicode 格式以防止數據丟失
A: 光標定位到該文件,選擇菜單里的高級保存選項utf-8 with signature,帶簽名的65001,高級保存選項添加方式見https://www.cnblogs.com/daxueba-ITdaren/p/7272210.html

Q: Warning MSB8004: Output Directory does not end with a trailing slash
A: 設置的目錄參數不是以反斜杠結束的目錄名稱,屬性→General→Output Direction里加上反斜杠。

Q: 不允許指針指向不完整的類類型
A: 添加該類類型的頭文件,如QStatusBar

Q: LNK1169 找到一個或多個多重定義的符號
A: 多次引用頭文件,比如所處位置為.h里,改到.cpp里。哪個文件需要,放在哪個文件里,不需要的不要放在.h里

Q: 引用頭文件后遇到無法解析的外部符號
A: link里加入lib,目錄要添加lib所在目錄

Q: Error LNK2019: unresolved external symbol WinMain referenced in function "int _cdecl invoke_main(void)"
A: 右鍵點擊項目,屬性→linker→System,修改subsystem。函數入口為main的,選擇console;另一種解決辦法見QGis二次開發常見問題。

三、Qt常見問題
Q:無法打開包括文件: “QDomDocument”、“QSvgRenderer”之類的問題: No such file or directory
A:C++的包含目錄要包含問題模塊所處的路徑,如QtXml、QtSvg,打印支持還要添加QtPrintSupport、網絡QtNetwork

Q: svg的圖片為什么在工具欄不顯示、編譯成功運行不起來?
A: 復制Qt的plugins目錄下的imageformats文件夾到程序運行目錄;依賴的Qt的dll也要拷到運行目錄里(windeployqt了解一下)。


Q:This applicationfailed to start because no Qt platform plugin could be initialized
A: 復制Qt的plugins目錄下的platform文件夾到程序運行目錄;依賴的Qt的dll也要拷到運行目錄里(windeployqt了解一下)。

Q: 信號SIGNAL和槽SLOT如何連接?
A: 如果一個信號不多個槽相聯系的話,那么,當這個信號被發射時,與之相關的槽被激活的順序將是隨機的。當點擊菜單時,動作觸發了多次,這跟connect有關,手動和內部自動重復。connect的幾種寫法如下:

QMenu* fileMenu = new QMenu;
fileMenu = this->menuBar()->addMenu("File");
actionOpenFile = new QAction("Open", this);
// connect 方式一:SLOT參數傳actionOpenFile的默認觸發槽函數on_openFileAction_triggered()
connect(actionOpenFile, SIGNAL(triggered(bool)), this, SLOT(on_openFileAction_triggered()));

/**
* connect 方式二:手動設置object name, 然后再顯式調用connectSlotsByName()。
* 若由designer自動創建的連接,代碼加了connectSlotsByName則會觸發兩次,因此不要在代碼里再連接信號槽。
* 代碼創建的部件,可以自定義槽函數void on_<窗口部件名稱>_<信號名稱>_(<信號參數>),用下面方法連接
* actionOpenFile->setObjectName("actionOpenFile");
* QMetaObject::connectSlotsByName(this);
**/

QgsLayerTreeViewDefaultActions* actions = QgisDemo::instance()->layerTreeView()->defaultActions();
connect(actions->actionRemoveGroupOrLayer(), SIGNAL(triggered(bool)), QgisDemo::instance(), SLOT(slot_updateAppTile()));//connect用法1
//connect(actions->actionRemoveGroupOrLayer(), &QAction::triggered, QgisDemo::instance(), &QgisDemo::slot_updateAppTile);//connect用法2
View Code

 

Q: 一個信號和兩個或多個槽函數連接時,由於先后順序隨機性,如何作調整?
A: 將其中一個槽函數里寫入非阻塞的延遲處理,調用processEvents會讓Qt繼續處理線程所在的消息隊列中未處理的消息,直到消息隊列中沒有消息可以處理。當進行長時間的操作的時候可以調用此函數(比方說拷貝文件)。這個函數可能和我們要使用msleep的本意有差別,但是使用它可以在svalue時間內處理events,從而達到類似sleep的目的。可參考https://www.cnblogs.com/bokeyuan-dlam/articles/6794911.html,代碼如下:

Time dieTime = QTime::currentTime().addMSecs(svalue);
while( QTime::currentTime() < dieTime )
QCoreApplication::processEvents(QEventLoop::AllEvents, 100);
View Code

 

Q: QwtPlot是qwt6的繪圖類,第三方庫,如何用?
A: linker里添加qwt.lib,C++包含目錄里加入對應的include文件qwt6。

Q: Uic'ing xxx.ui系統找不到指定的路徑
A: 問題原因是工程引用了環境變量”QTDIR”,但是用戶安裝QT后沒有配置該環境變量。方法一:在系統環境變量里添加QTDIR,重新啟動VS。方法二:右鍵點擊xxx.ui文件,選擇屬性,將命令行和附加依賴項的uic.exe的路徑改成qt目錄的絕對路徑。注意生成的ui_xxx.h路徑,可在C/C++附加目錄中添加進去,否則頭文件找不到。

四、QGis二次開發常見問題
注意:QGis3.16是基於Qt5.11.2編譯的,如果開發用Qt5.12版本,庫也需要同樣版本重新編譯一下。

Q: 若用Qt Creator作二次開發構建,如何配置庫引用?
A: 在pro文件中加入以下代碼:

INCLUDEPATH += "C:/OSGeo4W64/apps/qgis/include"
INCLUDEPATH += "C:/OSGeo4W64/include"

LIBS += -L"C:/OSGeo4W64/apps/qgis/lib" -lqgis_core -lqgis_gui
LIBS += -L"C:/OSGeo4W64/lib" -lgdal_i

DEFINES += CORE_EXPORT=__declspec(dllimport)
DEFINES += GUI_EXPORT=__declspec(dllimport)
View Code

 

Q: VS提示LNK1104: 無法打開文件“qgis_core.lib”
A: 將依賴庫拷到運行目錄


Q:VS構建需要的依賴庫
A:(1)C/C++常規->附加包含目錄:
D:\QGIS\OSGeo4W64\include
D:\QGIS\OSGeo4W64\apps\qgis-ltr\include
D:\Qt5\5.12.10\msvc2017_64\include\QtXml
     (2)鏈接器->常規—>附加庫目錄:
D:\QGIS\OSGeo4W64\apps\qgis-ltr\lib
D:\Qt5\5.12.10\msvc2017_64\lib
     (3)鏈接器->輸入->附加依賴項:qgis_core.lib qgis_gui.lib qgis_analysis.lib(根據需求添加,如果app里需要的部分頭文件和源文件拷貝過來的話,qgis_app.lib不需要;否則也要加上)

Q: 2.x版本的一些示例中的類在3.x中找不到頭文件
A: 參考官網資料,3.x版本作了一些刪改與合並,比如QgsProject替代qgsmaplayerregistry,3.x前后API變動記錄詳見https://qgis.org/api/api_break.html

Q: 如何取消地圖工具狀態?
A: 切換回到原來的無地圖工具狀態,解決思路就有了。先獲取到當前的地圖工具,然后 unset 掉它,並不設置新的工具,就可以了。代碼如下:

QgsMapTool *lastMapTool = m_mapCanvas->mapTool();
m_mapCanvas->unsetMapTool( lastMapTool );

 

Q: qgis_gui項目中出現未定義的標識符 "QWebElement"
A: 附件目錄添加D:\QGIS\OSGeo4W64\apps\Qt5\include\QtWebKit;但是由於Qt5.6起棄用這個類,變換了新類,因此要么從源碼解決這個問題,要么cmake在build源碼時取消WITH_QTWEBKIT;要么注釋掉報錯函數關於QWebElemen類的內容,並在qgismaptip.cpp文件開頭注釋掉WITH_QTWEBKIT:

//#if WITH_QTWEBKIT
//#endif

 

Q: error LNK2019: 無法解析的外部符號 WinMain,MSVCRT.lib
A: 方法一:見上方的“VS常見問題”;方法二:由於QGis新建項目是控制台應用程序,而程序通過的是WinMian(及windows入口函數),因此需要作下處理:在“qgis_core項目”->“屬性”->“連接器”->“輸入”附加依賴項中,debug版本添加D:\Qt\Qt5.12.10\msvc2017_64\qtmaind.lib,release版本則添加qtmain.lib。


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM