先說明一下,本水文老周僅討論新版的 Qt 6,舊版的 Qt 不討論。
儘管 Qt 有自己的開發環境,但老周必須說句不裝逼的話:真的不好用。說起寫程式碼,當然了,用記事本也能寫。但是,有個高逼格的工具,寫起來不僅效率高,而且舒服。
Qt 應用程式本質上就是 C++ 開發的程式碼,所以,不用官方工具是沒有問題的。老周第一個想到的,不用猜,必是 VS。在 Windows 上,用 VS 也是沒問題的。
安裝的時候,工作負載可以選「使用C++的桌面開發」,這個其實不選也可以的,老周已做過實驗,不選這個也能編譯。所以,可以在單個元件中安裝以下各項:
1、C++核心功能;
2、C++ 2022 可再發行程式更新包;
3、MSBuild(這個裝上好一點,不裝也沒報錯);
4、MSVC 143 C++ 生成工具(這個是重點,要裝,要裝);
5、用於 Windows 的 CMake 工具(這個也必須裝上);
6、Windows SDK 任選一個版本,建議越新越好(自己編譯原始碼時必須)。
7、其他的元件自己看心情。
如果你不用 VS,但在 Windows 上也要裝 MSVC 生成工具。在 Windows 上還是建議用微軟的編譯器,不容易出現莫名其妙的錯誤。老周實驗過,用 Windows 版的 g++ 編譯失敗。
當然本文講的 VS Code,但如果是 Windows 平臺,也要裝 VS 生成工具的。
-----------------------------------------------------------------------------------------------------------------------
Qt 現在也開始裝X了,編譯好的內褲只支援線上安裝,十有八九慢到你要裝幾天才能裝好,而且體積比 VS 還要大幾倍。想離線安裝只能下載原始碼自己編譯。
編譯原始碼需要以下工具:
1、Windows SDK,否則會找不到相關 .lib 檔案而出錯。
2、Python,3.x 後隨便找個版本。可以下載嵌入版,不用安裝,解壓後,把Python可執行檔案所在的目錄路徑新增到 PATH 變數中。
3、Perl。可以下載綠色版壓縮包,解壓到某目錄,將包含 perl.exe 的目錄新增到 PATH 環境變數中,一般位於 <解壓後目錄>\Perl\perl\bin。
下載原始碼可以用國內映象,如清華大學的:Index of /qt/archive/qt/ | 清華大學開源軟體映象站 | Tsinghua Open Source Mirror
最新的是 6.3,進去之後,不要下載整個原始碼包,而是找到 submodules 目錄。核心元件是 qtbase-everywhere-6.xxx。
qtbase 是基礎包,只編譯這個模組的程式碼也能寫 Qt 程式。解壓之後,放在一個路徑無空格無特殊符號的目錄下,如 E:\SDK\Qt。然後執行一下 configure 指令碼,Windows 上是有字尾 .bat 的,Linux 指令碼無字尾。
命令列引數可參考幫助檔案,實際上我們只關心一個引數 -prefix。這個引數指定在編譯成功後,複製(安裝)動態庫的目錄。因為編譯時會產生許多後期沒用的檔案,所以才要指定這個路徑。操作方法:
開啟 「Visual Studio 2022」 -- "x64 Native Tools Command Prompt for VS 2022"。
不要用 Developer Command Prompt for VS 2022,因為用這個你要指定 CPU 架構,若不指定預設編譯出來的庫是 32 位的。
【注意:下面輸入命令這一大段,你先彆著急跟著輸入。請你先看完了再輸入。因為這 Qt 6 在編譯前的設定有些雷區。即在「+++++++++++」與「+++++++++++」之間這一大段內容】
++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
先看最保險的操作,全按官方檔案的來,基本保持預設。
開啟 x64 Native Tools Command Prompt for VS 2022 工具的命令提示視窗,輸入:
cd <原始碼路徑>
configure -prefix F:\Qt6\Libs
這樣設定之後,將來在執行安裝時會把生成的 .dll 複製到這個目錄下。這廝好像重複執行會報錯。老週一般是懶得去找錯誤,有時候就算找到錯誤在哪個 cmake 檔案也解決不了問題,最直接有效的方法是全刪掉,再從下載的壓縮包裡重新解壓。官方檔案說刪除 CMakeCache.txt 檔案可以,但老周嘗試過,也是會報錯的。
一切順利之後,直接交給 CMake 解決。編譯:
cmake --build .
. 是原始碼所在目錄,因為上面我們已經 cd 到原始碼目錄了,所以這裡用個「.」表示當前目錄。
運氣好的話,一次通過。這時候電腦的 CPU 風扇會發瘋,請做好心理準備。因為只編譯一個基礎模組,所以花的時間會少一些。
編譯成功後,還要執行一下安裝操作:
cmake --install .
後面的「.」依然指的是當前目錄(原始碼目錄),編譯後的二進位制檔案(重點是那些 .dll)會複製到你剛才用 -prefix 引數設定的路徑下。如剛才設定的是 F:\Qt6\Libs。
上面的方案是保證出錯概率最低的做法,但是,生成檔案會和原始碼混在一起,想手動清理它們估計會累死人。如果想三個基本目錄相互隔離,就要用接下來的方法。這三個目錄是:
1、原始碼。
2、build 輸出目錄。
3、安裝目錄。
我們來假設一下:
1、原始碼:G:\Kits\Qt6\src\qtbase
2、build 輸出目錄:G:\Kits\Qt6\build
3、安裝目錄:G:\Kits\Qt6\installed
其實,這些目錄都在 G:\Kits\Qt6 下面。
廢話一下,我現在的想法是:保留原始碼目錄不變,想留著將來重複用;把生成/編譯輸出的東東放在 build 目錄,編譯好後的二進位制檔案安裝到 installed 目錄。下面開始操作。
【警告:以下操作出現靈異事件的概率大,請鼓起勇氣嘗試。世事難料,各自珍重】
首先,開啟 x64 Native Tools Command Prompt fo VS 20XX,定位到 G:\Kits\Qt6\build,這個路徑要根據你實際的路徑寫。
cd /d G:\kits\Qt6\build
命令工具視窗當前目錄一般是 C 盤,要跨分割區 CD 的話,要加上 /d 引數。
保持 build 目錄為當前目錄不要改變,在 build 目錄中執行 configure 指令碼。
..\src\qtbase\configure -prefix ..\installed
老周這裡用的是相對路徑,你也可以用絕對路徑。注意 -prefix 引數是一個短橫線的,不能寫成 --prefix,會出錯。如果看到下面這一行,說明你運氣好,第一關算是過了,接下來的編譯成功率很高。
Build files have been written to: G:/Kits/Qt6/build
接下來的操作就和前面的一樣了。保持當前目錄在 build 不變,依次執行:
cmake --build .
cmake --install .
++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
大約會編譯 1700 多個目標。這過程中很有可能會出錯退出。可以嘗試重新執行 cmake --build . ,一般會成功的。 在 installed\bin 目錄下你會看到許多 .dll,這說明一切順利。
編譯預設是生成動態庫的,所以在 configure 時我們不用改。建議用動態庫,若編譯為靜態庫,做專案時會涉及授權問題,也就是說你要購買。
編譯完畢後,就是設定 VS Code 了,其實就是安裝外掛罷了。這幾個外掛少不了:
1、C/C++(微軟官方的)
2、CMake Tools(也是微軟官方的)
3、CMake Language Support(有了這個,寫CMake時有智慧提示)
有以上這幾個就夠玩了。另外,微軟有個集合包,叫做 C/C++ Extension Pack,會一次安裝一堆 C++ 有關的外掛。覺得有必要可以裝裝,覺得沒必要就當它透明。
開啟 VS Code 的設定頁,找到擴充套件中的 CMake Tools,捲動到 Environment,點「新增項」設定一個環境變數。
PATH = G:\Kits\Qt6\installed;G:\Kits\Qt6\installed\bin;%PATH%
【鍵】是「PATH」,【值】是 = 後面那串。路徑就是你剛才 Qt6 安裝的目錄,包括安裝目錄,以及安裝目錄下的 bin。
儲存退出,收工。
如果上面各步驟都成功,我們現在可以開寫玩了。
在 VS Code 中開啟一個目錄作為工作區。然後按 【ctl + shift + P】,輸入「cmake」,找到「CMake 設定」命令,執行。
編譯器選擇 amd64 的,如果你要 32 位的就選 x86。
【注】如果你要寫 32 位的,那前面在編譯原始碼時也要編譯一份 32 位的動態庫。這個你懂的,32 位和 64 位的二進位制檔案是不同混用的。
這時,提示還沒建立 CMakeLists.txt ,那就點建立唄。但是,生成的 CMakeLists.txt 檔案中的東東很多不是我們所需要的。凡是有 enable_testing,CTest 什麼的,全部幹掉。
大致內容如下:
cmake_minimum_required(VERSION 3.15.0) # 專案名稱 project(testApp LANGUAGES CXX) # 設定變數 set(CMAKE_CXX_STANDARD 17) set(CMAKE_CXX_STANDARD_REQUIRED ON) set(CMAKE_AUTOMOC ON) set(CMAKE_AUTOUIC ON) # 參照需要的庫 find_package(Qt6 REQUIRED COMPONENTS Core Widgets Gui) # 新增原始碼檔案 add_executable(testApp WIN32 main.cpp) # 與相關的庫連結 target_link_libraries(testApp PRIVATE Qt6::Widgets Qt6::Core Qt6::Gui)
1
3:設定變數。
CMAKE_CXX_STANDARD = 17 C++版本號 ,不要低於17。
CMAKE_CXX_STANDARD_REQUIRED = on 或 yes 或 1,和上面一起,必須符合C++版本。
CMAKE_AUTOMOC = on 或 yes 或 1,這個在Qt 專案裡一般要開啟,允許一些獨特語法轉譯為C++程式碼。說白了就是 Qt 裡面的訊號和槽,用到特定的語法(其實這些語法是用宏定義的)。
CMAKE_AUTOUIC = on 或 yes 或 1,這個如果用到了 uic 資源時才會開啟,沒用到就可以不寫。
4:引入要使用的庫,Qt6 中使用 find_package 命令,格式都是固定,官方檔案中有,可以照著抄。
5:新增原始碼檔案。
第一個是目標名,一般和專案名稱相同,你可以自己取名。接著 WIN32 不能少(僅限於 Windows),否則視窗出不來,只出來控制檯。main.cpp是程式碼檔案,有多個程式碼檔案也要寫上,比如 a.cpp b.cpp c.cpp,如果寫漏了就導致有的檔案沒有被編譯,那你的程式能執行起來才怪呢。
6:連結。把目標(上面 add_executable 就是為目標加了原始檔)和庫連結起來。
這個格式也是固定的,照著檔案抄就行了。請看上面 find_package 的截圖。
----------------------------------------------------------------------------------------------------------------------------------
下面是 main.cpp 中的程式碼,我們來試試前面的設定是否正確。 ,
#include <QApplication> #include <QWidget> #include <QHBoxLayout> #include <QPushButton>
int main(int argc, char** argv)
{ // 這個 App 和 Widgets 在程式碼上不直接參照 // 但它是必須的,它會開啟主訊息迴圈 QApplication app(argc, argv); // 準備主視窗 QWidget window; // 視窗標題 window.setWindowTitle("窮屌絲應用程式"); // 設定視窗大小 window.resize(400, 300); // 控制元件 QPushButton *btn1 = new QPushButton("第一個按鈕"); QPushButton *btn2 = new QPushButton("第二個按鈕"); // 佈局 QHBoxLayout *layout = new QHBoxLayout(&window); // 將控制元件放入佈局中 layout -> addWidget(btn1, 2); layout -> addWidget(btn2, 1); // 顯示視窗 window.show(); // 別忘了這一行,正式啟動程式 return app.exec(); // 呼叫靜態的也行 //return QApplication::exec(); }
QApplication 類用於啟動應用程式的主訊息迴圈,它不需要顯式參照 Widget 物件。呼叫 exec 方法正式開始訊息迴圈。這個方法會一直迴圈,直到應用程式退出(主視窗/根 Widget 被關閉)才會返回。若無錯誤,就返回 0 ,這個返回值可以直接沿著 main 函數返回。
注意,所有初始化(建立視窗,放置控制元件等)程式碼必須在 exec 方法之前呼叫。exec 方法一旦呼叫,除非應用程式退出,否則是不會返回的。所以不要在 exec 之後寫任何程式碼(清理程式碼除外)。
QWidget 是眾多 UI 元素/控制元件的基礎類別,直接使用它可以作為應用程式的視窗——就是一個空白視窗。setWindowTitle 方法用來設定視窗標題列上的文字;resize 方法調整視窗的大小;show 方法顯示視窗。
QHBoxLayout 是一個佈局類,用來佈局視窗中控制元件的位置。它指的是 UI 元素沿水平方向排列。這個 Layout 類似於 WPF 中的 StackPanel。嗯,相信你也猜到,要垂直佈局,就用 QVBoxLayout 類。如果想向 StackPanel 那樣,可以通過設定來控制水平或垂直方向,可以用 QBoxLayout,通過 setDirection 方法可以設定:從左到右、從右到左、從上到下、從下到上。
QPushButton 就是常見的按鈕。
在 Qt 應用程式中,new 出來的指標不一定要 delete / free 的。因為它有個參照樹的概念,會自動釋放指標所參照的東西。前提是這些物件是連線到 QObject 上的。比如視窗是 QWidget ,放在視窗內的控制元件元素如果以視窗為父物件,就像上面那個例子,裡面的 QHBoxLayout、QPushButton 等,是連線到 QWidget 上的,所以不需要 delete 指標,它會自動釋放。
我們 build 一下這個專案,然後執行它。
注意看 VS Code 底部的狀態列,你能找到這兩個按鈕。
如果沒有問題,就能看到應用程式視窗了。
在 Linux 上的編譯和設定與 Windows 上差不多的。注意先安裝 g++,選這個編譯的話可避免各種靈異事件。老周在 Ubuntu 上試驗時,曾經遇到過一次靈異事件,至今無法解釋。編譯 Qt6 原始碼順利完成,寫一個 app 試了下也能執行起來。但是,系統重啟後就進不了系統了,除了 root 帳戶外,所有帳戶都無許可權登入。切換到 init 2 登入也不行,一登入就會被彈出來。就是除 root 外所有使用者都沒有任何許可權,連登入的許可權都沒有。這現象無法解釋,因為那次老周成功登入系統後只編譯了 Qt6 原始碼,寫了個測試 app,也沒做別的事,重啟後就掛了。