QT視窗類

checha發表於2024-07-11

1 視窗基類

我們在透過Qt嚮導視窗基於視窗的應用程式的專案過程中倒數第二步讓我們選擇跟隨專案建立的第一個視窗的基類, 下拉選單中有三個選項, 分別為: QMainWindow、QDialog、QWidget如下圖:

image

常用的視窗類有3個
在建立Qt視窗的時候, 需要讓自己的視窗類繼承上述三個視窗類的其中一個
QWidget
所有視窗類的基類
Qt中的控制元件(按鈕, 輸入框, 單選框…)也屬於視窗, 基類都是QWidget
可以內嵌到其他視窗中: 沒有邊框
可以不內嵌單獨顯示: 獨立的視窗, 有邊框
QDialog
對話方塊類, 後邊的章節會具體介紹這個視窗
不能內嵌到其他視窗中
QMainWindow
有工具欄, 狀態列, 選單欄, 後邊的章節會具體介紹這個視窗
不能內嵌到其他視窗中

2 視窗的顯示

內嵌視窗
依附於某一個大的視窗, 作為了大視窗的一部分
大視窗就是這個內嵌視窗的父視窗
父視窗顯示的時候, 內嵌的視窗也就被顯示出來了
不內嵌視窗
這類視窗有邊框, 有標題欄
需要呼叫函式才可以顯示

// QWidget是所有視窗類的基類, 呼叫這個提供的 show() 方法就可以顯示將任何視窗顯示出來
// 非模態顯示
void QWidget::show();	// 顯示當前視窗和它的子視窗

// 對話方塊視窗的非模態顯示: 還是呼叫show() 方法
// 對話方塊視窗的模態顯示
[virtual slot] int QDialog::exec();

3 座標體系

在Qt關於視窗的顯示是需要指定位置的,這個位置是透過座標來確定的,所有座標的選取又都是基於座標原點來確定的,關於這些細節的確定,下面依次給大家進行講解。

3.1 視窗的座標原點

所有座標的確定都需要先找到座標原點, Qt的座標原點在視窗的左上角
x軸向右遞增
y軸向下遞增

image

3.2 視窗的相對座標

在一個Qt視窗中一般都有很多子視窗內嵌到這個父視窗中,其中每個視窗都有自己的座標原點,子視窗的位置也就是其使用的座標點就是它的父視窗座標體系中的座標點。
image
在Qt的某一個視窗中有可能有若干個控制元件, 這個控制元件都是巢狀的關係

A視窗包含B視窗, B視窗包含C視窗
每個視窗都有座標原點, 在左上角

子視窗的位置是基於父視窗的座標體系來確定的, 也就是說透過父視窗左上角的座標點來確定自己的位置
Qt中視窗顯示的時候使用的相對座標, 相對於自己的父視窗

將子視窗移動到父視窗的某個位置

// 所有視窗類的基類: QWidget
// QWidget中提供了移動視窗的 API函式
// 引數 x, y是要移動的視窗的左上角的點, 視窗的左上角移動到這個座標點
void QWidget::move(int x, int y);
void QWidget::move(const QPoint &);

4 記憶體回收

在Qt中建立物件的時候會提供一個 Parent物件指標(可以檢視類的建構函式),下面來解釋這個parent到底是幹什麼的。

QObject是以物件樹的形式組織起來的。當你建立一個QObject物件時,會看到QObject的建構函式接收一個QObject指標作為引數,這個引數就是 parent,也就是父物件指標。這相當於,在建立QObject物件時,可以提供一個其父物件,我們建立的這個QObject物件會自動新增到其父物件的children()列表。當父物件析構的時候,這個列表中的所有物件也會被析構。(注意,這裡的父物件並不是繼承意義上的父類!)

QWidget是能夠在螢幕上顯示的一切元件的父類。QWidget繼承自QObject,因此也繼承了這種物件樹關係。一個孩子自動地成為父元件的一個子元件。因此,它會顯示在父元件的座標系統中,被父元件的邊界剪裁。例如,當使用者關閉一個對話方塊的時候,應用程式將其刪除,那麼,我們希望屬於這個對話方塊的按鈕、圖示等應該一起被刪除。事實就是如此,因為這些都是對話方塊的子元件。

Qt 引入物件樹的概念,在一定程度上解決了記憶體問題。

當一個QObject物件在堆上建立的時候,Qt 會同時為其建立一個物件樹。不過,物件樹中物件的順序是沒有定義的。這意味著,銷燬這些物件的順序也是未定義的。

任何物件樹中的 QObject物件 delete 的時候,如果這個物件有 parent,則自動將其從 parent 的children()列表中刪除;如果有孩子,則自動 delete 每一個孩子。Qt 保證沒有QObject會被 delete 兩次,這是由析構順序決定的。

image
綜上所述, 我們可以得到一個結論: Qt中有記憶體回收機制, 但是不是所有被new出的物件被自動回收, 滿足條件才可以回收, 如果想要在Qt中實現記憶體的自動回收, 需要滿足以下兩個條件:

建立的物件必須是QObject類的子類(間接子類也可以)

QObject類是沒有父類的, Qt中有很大一部分類都是從這個類派生出去的

Qt中使用頻率很高的視窗類和控制元件都是 QObject 的直接或間接的子類
其他的類可以自己查閱Qt幫助文件
建立出的類物件, 必須要指定其父物件是誰, 一般情況下有兩種操作方式:

// 方式1: 透過建構函式
// parent: 當前視窗的父物件, 找建構函式中的 parent 引數即可
QWidget::QWidget(QWidget *parent = Q_NULLPTR, Qt::WindowFlags f = Qt::WindowFlags());
QTimer::QTimer(QObject *parent = nullptr);

// 方式2: 透過setParent()方法
// 假設這個控制元件沒有在構造的時候指定符物件, 可以呼叫QWidget的api指定父視窗物件
void QWidget::setParent(QWidget *parent);
void QObject::setParent(QObject *parent);

相關文章