昨天我們用 Qt Creator 的專案創建精靈(俗稱的下一步下一步)開了一個新的 Qt Widget Application 專案。
今天我們詳細檢視一下這個精靈替我們做了什麼。
先來看一下專案結構:
跟之前幾天的專案比較起來,只有一些些差異。
有一個 Qt 專案檔 ImageViewr.pro
,搭配三個原始碼檔案,main.cpp
、mainwindow.h
以及 mainwindow.cpp
。
我們來看一下 ImageViewer.pro
:
QT += core gui
greaterThan(QT_MAJOR_VERSION, 4): QT += widgets
CONFIG += c++17
# You can make your code fail to compile if it uses deprecated APIs.
# In order to do so, uncomment the following line.
#DEFINES += QT_DISABLE_DEPRECATED_BEFORE=0x060000 # disables all the APIs deprecated before Qt 6.0.0
SOURCES += \
main.cpp \
mainwindow.cpp
HEADERS += \
mainwindow.h
# Default rules for deployment.
qnx: target.path = /tmp/$${TARGET}/bin
else: unix:!android: target.path = /opt/$${TARGET}/bin
!isEmpty(target.path): INSTALLS += target
這個專案檔的內容看似多了好多東西,很複雜,但是別擔心,但實際上只有幾個重要的點。
一、導入必要的 Qt 模組:core, gui, widgets。
widget 是在 Qt4 -> Qt5 的版本演進過程中切割出來的新模組,所以才有 greaterThan(QT_MAJOR_VERSION, 4)
這個條件。我們已經在寫 Qt6 了,這個條件等於沒有作用。
二、CONFIG += c++17
啟用 C++17 語言標準。Qt6 事實上已經默認使用 C++17 開發,所以等同廢話。
三、再來有幾行註解文字,主要是關於 QT_DISABLE_DEPRECATED_BEFORE
定義,這是針對 Qt5 開發者,用於提前告知他們哪些API在Qt6已經被廢棄。但是由於我們已經在寫 Qt6,所以可以不用理會。
四、接著是重點:SOURCES
原始碼檔案清單和 HEADERS
標頭檔清單,這裡必須列出所有的.h/.cpp檔案。需要注意的是,反斜線\
表示延續上一行,所以行尾有反斜線,意思是該行還未結束,下一行繼續。
最後一段 Default rules for deployment. 跟我們目前的開發無關,可以忽略。
接著我們前往程式的入口點 main.cpp,也就是所有程式魔法的原點。
跟前幾天的範例相比,這次的入口 main() 簡單許多:只建立了一個 MainWindow 物件。
#include "mainwindow.h"
#include <QApplication>
int main(int argc, char *argv[])
{
QApplication a(argc, argv);
MainWindow w;
w.show();
return a.exec();
}
而這個 MainWindow 物件則定義在 mainwindow.h
和 mainwindow.cpp
兩個檔案中。顯然,主角就是這位 MainWindow,讓我們往裡面看看:
首先來看標頭檔 mainwindow.h
#ifndef MAINWINDOW_H
#define MAINWINDOW_H
#include <QMainWindow>
class MainWindow : public QMainWindow
{
Q_OBJECT
public:
MainWindow(QWidget* parent = nullptr);
~MainWindow();
};
#endif // MAINWINDOW_H
第一、我們發現這個 MainWindow 繼承自 QMainWindow。
根據官方文件說明,QMainWindow 是一個基本的大視窗框架,在 QMainWindow 的基礎上,可以添加選單列、工具列、狀態列、左右側邊欄等等。
在 QMainWindow 這個地基上蓋房子的標準慣例作法,就是繼承 QMainWindow。
第二、在 class 定義內的第一行有一個 Q_OBJECT
巨集。這個巨集是為了 Qt 最著名的「信號槽 signal/slot」系統而存在。事實上,Qt 為了讓信號槽機制正常運作,在編譯時會多做一個預處理的動作,解析標頭檔。而只有標上Q_OBJECT
巨集的類別,才會被預處理。
第三、MainWindow 的建構子 MainWindow(QWidget *parent = nullptr);
有一個參數,給你設定親子關係中的爸爸物件。MainWindow 在整個物件親子階層中,通常是最頂層的那一位,所以這裡我們留空。
接著我們看 maindinwo.cpp
#include "mainwindow.h"
MainWindow::MainWindow(QWidget* parent) : QMainWindow(parent)
{
}
MainWindow::~MainWindow()
{
}
相較於標頭檔,這個CPP檔顯的空蕩蕩的。只有一個空的建構子和解構子。明天開始,我們就會往裡面加東西啦!
明天我們會實現看圖軟體的第一個,也是最重要的功能:顯示一張圖片。