1. 程式人生 > 實用技巧 >QT學習:00 介紹

QT學習:00 介紹

--- title: framework-cpp-qt-00-介紹 date: 2020-04-08 15:41:54 categories: tags: - c/c++ - qt ---

介紹

Qt 是一個跨平臺的 C++ 框架(C++庫),目前最新的版本是 Qt5。Qt5 還包含了很多小版本,其中推薦 Qt5.9,即長期支援版本,Bug較少,相對穩定。

Qt 除了支援介面設計(GUI程式設計),還封裝了與網路程式設計、多執行緒、資料庫連線、視訊音訊等相關的功能。

從這一講開始,我們進行有關的學習。

開發平臺 引數
OS Windows-10
Qt Creator 4.10.0
Qt Core 5.13.1(MSVC 2017, 32bit)

我們這裡假設:

  • 讀者已經安裝好了QT-creator並且能夠正常地編譯一個空白例程。
  • 讀者具備基本的C++開發基礎。

術語介紹

在基於IDE(整合開發環境)的開發,我們需要了解常見的術語。

Project

Project 的中文翻譯是“專案”或者“工程”,這裡的專案是指為實現某個相對獨立功能的程式程式碼合集,這些程式碼不單單是放在一塊,而是有相互之間的關聯性,並且有專門負責管理該專案的專案檔案,比如:

  • Qt 使用 .pro 檔案管理專案;
  • VC++ 則使用 .vcproj 作為專案檔案。

整合開發環境通常都是依據專案檔案(.pro/.vcproj)管理和構建專案。 即生成指令碼,雖然可以直接呼叫編譯器如 g++ 編譯程式,但是如果專案裡的程式碼檔案變多了,哪些程式碼檔案更新了需要重新編譯,哪些程式碼沒有改不需要重新編譯等等,靠程式設計師自己記憶去處理是比較麻煩的事,還有哪些程式碼需要預處理或是連結哪些庫檔案, 這些都是繁雜的過程。為了規範程式的編譯生成過程,產生了規範化的生成指令碼,就是 Makefile,生成器 make 可以依據規範的 Makefile 自動生成目標程式或庫檔案。

Debug 和 Release

Debug 即除錯,Release 即發行。程式碼編寫之後,生成的目標程式或庫檔案通常不會絕對正確,或多或少有些毛病(bug), 因此需要進行糾錯除錯(Debug)。除錯過程中需要原始碼和二進位制目標程式之間一一對應的關係, 這樣才能定位到錯誤程式碼,所以 Debug 版本的程式是臃腫而不進行優化的。

  • Debug 版本程式通常連結的也是 Debug 版本的庫檔案,比如 libQt5Guid.a/Qt5Guid.dll,庫檔案的簡短名(不含副檔名)都是以 d 結尾的,Debug 庫通常都比較大 。
  • Release 版本程式連結的通常就是 Release 版本的庫檔案,Release 版本庫檔名字比 Debug 版本庫檔案少一個字母 d ,如 libQt5Gui.a/Qt5Gui.dll,而且 Release 版本庫一般都比 Debug 版本小很多,執行效率也高很多。

C++11 標準

時代在變化,C++ 標準也在前進。C++ 正式公佈標準有 C++98、C++03、C++11。最新的 C++11 標準是2011年8月12日公佈的,在公佈之前該標準原名為 C++0x 。這是一次較大的修訂和擴充,建議讀者專門學一下。

Qt 從 4.8 版本就開始用 C++11 新特性了。編譯器裡面開始支援 C++11 的版本是 MSVC 2010、GCC 4.5、Clang 3.1,這之後版本的編譯器都在逐步完善對 C++11 的支援,現在新版本編譯器對新標準的支援都比較全面了。

MSVC 編譯器預設開啟 C++11 特性,GCC(g++命令)則需要自己新增選項 -std=c++0x ,上面 CXXFLAGS 就是為 GCC 編譯器(g++命令)新增 -std=c++0x 選項。

Qt 官方在編譯 Qt5 庫的時候都是開啟 C++11 特性的,如果我們要在自己專案程式碼啟用新標準,需要在 .pro 檔案裡面新增一行: CONFIG += c++11

庫連結

Dynamic Link 即動態連結,Static Link 即靜態連結。

動態連結庫

目標程式通常都不是獨立個體,生成程式時都需要連結其他的庫,要用到其他庫的程式碼。對於多個程式同時執行而言,記憶體中就可能有同一個庫的多個副本,佔用了太多記憶體而乾的活差不多。

為了優化記憶體運用效率,引入了動態連結庫(Dynamic Link Library),或叫共享庫(Shared Object)。使用動態連結庫時,記憶體中只需要一份該庫檔案,其他程式要使用該庫檔案時,只要連結過來就行了。由於動態庫檔案外接,連結到動態庫的目標程式相對比較小,因為剝離了大量庫程式碼,而只需要一些連結指標。

使用動態庫,也意味著程式需要連結到如 *.dll 或 *.so 檔案,得提前裝好動態庫檔案,然後目標程式才能正常執行。

靜態連結庫

靜態庫就是將連結庫的程式碼和自己編寫的程式碼都編譯連結到一塊,連結到靜態庫的程式通常比較大,但好處是執行時依賴的庫檔案很少,因為目標程式自己內部集成了很多庫程式碼。

庫檔案字尾

Linux/Unix 系統裡靜態庫副檔名一般是 .a,動態庫副檔名一般是 .so 。Windows 系統裡 VC 編譯器用的靜態庫副檔名一般是 .lib,動態庫副檔名一般是 .dll 。

顯式連結 和 隱式連結

顯式連結(Explicit Linking),隱式連結(Implicit Linking, 預設),這兩種都是動態連結庫的使用方式。

動態連結庫通常都有其匯出函式列表, 告知其他可執行程式可以使用它的哪些函式。可執行程式使用這些匯出函式有兩種方式:一是在執行時使用主動載入動態庫的函式,Linux 裡比如用 dlopen 函式開啟並載入動態庫,Windows 裡一般用 LoadLibrary 開啟並載入動態庫,只有當程式程式碼執行到這些函式時,其引數裡的動態庫才會被載入,這就是顯式連結。顯式連結方式是在執行時載入動態庫,其程式啟動時並不檢查這些動態庫是否存在。

隱式連結是最為常見的,所有的編譯環境預設都是採用隱式連結的方式使用動態庫。隱式連結會在連結生成可執行程式時就確立依賴關係,在該程式啟動時,作業系統自動會檢查它依賴的動態庫,並一一載入到該程式的記憶體空間,程式設計師就不需要操心什麼時候載入動態庫了。比如 VC 編譯環境,連結時使用動態庫對應的 .lib 檔案(包含動態庫的匯出函式宣告,但沒有實際功能程式碼),在 .exe 程式執行前系統會檢查依賴的 .dll

MinGW 是將動態庫的匯出函式宣告放在了 .a 檔案裡,程式執行依賴的動態庫也是 .dll

請注意,VC 連結器使用的 .lib 檔案分兩類,一種是完整的靜態庫,體積比較大,另一種是動態庫的匯出宣告,體積比較小。MinGW 連結器使用的 .a 檔案也是類似的,Qt 官方庫都是按照動態庫釋出的,靜態庫只有自己編譯才會有。

Qt Creator 的使用

Qt Creator 的介面很簡潔。上方是主選單欄,左側是主工具欄,視窗的中間部分是工作區。根據設計內容不同,工作區會顯示不同的內容。

  • 單擊“Projects(專案)”按鈕後,工作區顯示新建專案按鈕和最近開啟專案的列表。
  • 單擊“Examples(示例)”按鈕後,工作區顯示 Qt 自帶的大量例項,選擇某個例項就可以在 Qt Creator 中開啟該專案源程式。
  • 單擊“Tutorials(教程)”按鈕後,工作區顯示各種視訊教程,檢視視訊教程需要聯網並使用瀏覽器開啟。
  • 單擊“Get Started Now”按鈕,工作區顯示“Qt Creator Manual”幫助主題內容。

主視窗左側是主工具欄,主工具欄提供了專案檔案編輯、窗體設計、程式除錯、專案設定等各種功能按鈕。

使用 Qt Creator 新建專案

點選選單

單擊 Qt Creator 的選單項檔案->新建檔案或專案,出現一個對話方塊。在這個對話方塊裡選擇需要建立的專案或檔案的模板。

Qt Creator 可以建立多種專案,在最左側的列表框中單擊“Application”,中間的列表框中列出了可以建立的應用程式的模板,各類應用程式如下:

  • Qt Widgets Application,支援桌面平臺的有圖形使用者介面(Graphic User Interface,GUI) 介面的應用程式。GUI 的設計完全基於 C++ 語言,採用 Qt 提供的一套 C++ 類庫。
  • Qt Console Application,控制檯應用程式,無 GUI 介面,一般用於學習 C/C++ 語言,只需要簡單的輸入輸出操作時可建立此類專案。
  • Qt Quick Application,建立可部署的 Qt Quick 2 應用程式。Qt Quick 是 Qt 支援的一套 GUI 開發架構,其介面設計採用 QML 語言,程式架構採用 C++ 語言。利用 Qt Quick 可以設計非常炫的使用者介面,一般用於移動裝置或嵌入式裝置上無邊框的應用程式的設計。
  • Qt Quick Controls 2 Application,建立基於 Qt Quick Controls 2 元件的可部署的 Qt Quick 2 應用程式。Qt Quick Controls 2 元件只有 Qt 5.7 及以後版本才有。
  • Qt Canvas 3D Application,建立 Qt Canvas 3D QML 專案,也是基於 QML 語言的介面設計,支援 3D 畫布。

我們選擇Qt Widgets Application後, 單擊Choose…按鈕。

設定專案

設定好專案名稱以及儲存位置以後,單擊Next按鈕。

選擇工具鏈

勾選合適的工具鏈,點選Next按鈕。

選擇介面的基類

選擇需要建立介面的基類(base class)。有 3 種基類可以選擇:

  • QMainWindow 是主視窗類,主視窗具有主選單欄、工具欄和狀態列,類似於一般的應用程式的主視窗。
  • QWidget 是所有具有可視介面類的基類,選擇 QWidget 建立的介面對各種介面元件都可以支援。
  • QDialog 是對話方塊類,可建立一個基於對話方塊的介面。

選擇 QMainWindow 作為基類,自動更改的各個檔名不用手動去修改。

實際上我更推薦使用QWidget ,因為可以與一些教程相容。

勾選“建立介面(Generate form)”複選框。

勾選,就會由 Qt Creator 建立使用者介面檔案。

否則,需要自己程式設計手工建立介面。新手勾選

專案管理與檔案編輯介面

視窗左側有上下兩個子視窗,上方的目錄樹顯示了專案內檔案的組織結構,顯示當前專案。

預設情況下,上方的子視窗顯示了專案的檔案目錄樹,下方顯示開啟的檔案列表。

上下兩個子視窗的顯示內容可以通過其上方的一個下拉列表框進行選擇,可以選擇的顯示內容包括專案、開啟文件、書籤、檔案系統、類檢視、大綱等。

可以在下方選擇顯示類檢視,這樣下方則顯示專案內所有的類的結構,便於程式瀏覽和快速切換到需要的程式碼位置。

專案的名稱構成目錄樹的一個根節點,Qt Creator 可以開啟多個專案,但是隻有一個活動專案,活動專案的專案名稱節點用粗體字體表示。

在專案名稱節點下面,分組管理著專案內的各種原始檔,幾個檔案及分組分別為以下幾項:

  • xx.pro 是專案管理檔案,包括一些對專案的設定項。
  • Headers 分組,該節點下是專案內的所有標頭檔案(.h),專案有一個頭檔案 mainwindow.h,是主視窗類的標頭檔案。
  • Sources 分組:該節點下是專案內的所有 C++原始檔(.cpp),專案有兩個 C++ 原始檔,mainwindow.cpp 是主視窗類的實現檔案,與 mainwindow.h 檔案對應。main.cpp 是主函式檔案,也是應用程式的入口。
  • Forms 分組:該節點下是專案內的所有介面檔案(.ui)。專案有一個介面檔案mainwindow.ui,是主視窗的介面檔案。介面檔案是文字檔案,使用 XML 語言描述介面的組成。(雙擊它可以進行介面設計)

介面設計

雙擊檔案目錄樹中的檔案mainwindow.ui,可以來到窗體設計介面。

這個介面實際上是 整合的Qt Designer。視窗左側是分組的元件面板,中間是設計的窗體。

在元件面板的 Display Widgets 分組裡,將一個Label元件拖放到設計的窗體上面。雙擊剛剛放置的 Label 元件,可以編輯其文字內容,將文字內容更改為“Hello, World!”。還可以在視窗右下方的屬性編輯器裡編輯標籤的 Font 屬性,Point Size(點大小)更改為 12,勾選粗體。

專案的編譯、除錯與執行

單擊主視窗左側工具欄上的“專案”按鈕,出現專案編譯設定介面。

介面左側一欄的“Build & Run”下面顯示了本專案中可用的編譯器工具,要使用哪一個編譯器用於專案編譯,單擊其名稱即可,選擇的編譯器名稱會用粗體字表示。

每個編譯器又有 BuildRun 兩個設定介面。在 Build 設定介面上,有一個“Shadow build” 複選框。如果勾選此項,編譯後將在專案的同級目錄下建立一個編譯後的檔案目錄,目錄名稱包含編譯器資訊,這種方式一般用於使用不同編譯器建立不同版本的可執行檔案。如果不勾選此項,編譯後將在專案的目錄下建立“Debug”和“Release”子目錄用於存放編譯後的檔案。

在設計完 mainwindow.ui 檔案,並設定好編譯工具之後,就可以對專案進行編譯、除錯或執行。

主視窗左側工具欄下方有 4 個按鈕:

  • 小電腦: 彈出選單選擇編譯工具和編譯模式,如 Debug或 Release模式
  • 綠色三角形(Ctrl+R): 直接執行程式,如果修改後未編譯,會先進行編譯。即使在程式中設定了斷點,此方式執行的程式也無法除錯。
  • 綠色三角形+小蟲子(F5): 專案需要以Debug模式編譯,點此按鈕開始除錯執行,可以在程式中設定斷點。若是以 Release模式編譯,點此按鈕也無法進行除錯。
  • 小鐵錘(Ctrl+B): 編譯當前專案。

執行新建的專案

建立完成以後,我們在右下角可以看到綠色的三角形按鈕,點選即可。

關於相對路徑的補充說明

相對路徑和絕對路徑在開發中是比較常見的普通問題。為了避免初學者在Qt學習中因為路徑的問題受阻礙,經常抱怨開啟某個相對路徑的檔案打不開,形如:

  • QPixmap("xx.png");// 載入圖片不成功
  • QFile("xx.txt"); // 開啟檔案失敗

為了解決這個問題,我們需要知道,在QT中的相對路徑,是相對哪個目錄的:

  • 明確一個概念:程序的"工作目錄 "與程式所在的目錄 ,是不同的。
  • 在Qt中,當程式是以Qt Creator 啟動時,相對路徑是以構建目錄作為當前目錄來相對的。當開啟了shadow build以後,構建目錄就以shadow build作為構建目錄。

shadow build:將原始碼路徑和構建路徑分開(也就是工程生成的檔案都不放到原始碼路徑),以此來保證原始碼路徑的清潔。從cmake的時候就已經有了這個概念。

相對路徑轉絕對路徑:

QDir temDir("./dir1/2.swf");
QString absDir = temDir.absolutePath();

得到的路徑是例如E:/aa/bb/cc.txt 格式的路徑,但實際有些使用路徑的函式中需要的路徑格式為E:\\aa\\bb\\cc.txt這種格式,所以需要對格式進行簡單的轉換,QString中有個replace函式可以幫我們完成。

absDir.replace(QString("/"),QString("\\\\")); // 後面之所以四個 ` \`是因為包含了兩個轉義字元