QWidget 類代表一般的窗口,其他窗口類都是從 QWidget 類繼承出來的。而 QWidget 類則同時繼承了 QObject 類 和 QPaintDevice 類,也就是說,窗口類都是 Qt 對象類。這里的 QPaintDevice 類則是所有可繪制的對象的基類。
常用窗口類的繼承關系如圖所示:
構造
QWidget 類的構造函數如下:
- QWidget(QWidget *parent = 0, Qt::WindowFlags f = 0);
QWidget(QWidget *parent = 0, Qt::WindowFlags f = 0);
其中參數 parent 指向父窗口,如果這個參數為 0,則窗口就成為一個頂級窗口
參數 f 是構造窗口的標志,主要用於控制窗口的類型和外觀等,有以下常用值。
1)Qt::FramelessWindowHint:沒有邊框的窗口。
2)Qt::WindowStaysOnTopHint:總是最上面的窗口。
3)Qt::CustomizeWindowHint:自定義窗口標題欄,以下標志必須與這個標志一起使用才有效,否則窗口將有默認的標題欄。
4)Qt::WindowTitleHint:顯示窗口標題欄。
5)Qt::WindowSystemMenuHint:顯示系統菜單。
6)Qt::WindowMinimizeButtonHint:顯示最小化按鈕。
7)Qt::WindowMaximizeButtonHint:顯示最大化按鈕。
8)Qt::WindowMinMaxbuttonHint:顯示最小化按鈕和最大化按鈕。
9)Qt::WindowCloseButtonHint:顯示關閉按鈕。
獨立窗口
窗口構造的時候如果有 Qt::Window 標志,那么它就是一個獨立窗口,否則就是一個依附於其他獨立窗口的窗口部件。頂級窗口一定是獨立窗口,但獨立窗口不一定是頂級的,它可以有父窗口,當父窗口被析構時它也會隨之被析構。獨立窗口一般有自己的外邊框和標題欄,可以有移動、改變大小等操作。
一個窗口是否為獨立窗口可用下面的成員函數來判斷:
- bool isWindow() const; // 判斷是否為獨立窗口
bool isWindow() const; // 判斷是否為獨立窗口
下面這個函數可以得到窗口部件所在的獨立窗口。
- QWidget *window() const; // 所得所在的獨立窗口
QWidget *window() const; // 所得所在的獨立窗口
當然,如果窗口本身就是獨立窗口,那么得到的就是自己。
而下面這個函數可以得到窗口的父窗口:
- QWidget *parentWidget() const; // 得到父窗口
QWidget *parentWidget() const; // 得到父窗口
窗口標題
WindowTitle 屬性表示窗口的標題,與之相關的成員函數如下:
- QString windowTitle() const; // 獲得窗口標題
- void setWindowTitle(const QString &text); // 設置窗口標題為 text
QString windowTitle() const; // 獲得窗口標題 void setWindowTitle(const QString &text); // 設置窗口標題為 text
幾何參數
這里的幾何參數指的是窗口的大小和位置。一個窗口有兩套幾何參數,一套是窗口外邊框所占的矩形區域,另一套是窗口客戶區所占的矩形區域。所謂窗口客戶區就是窗口中去除邊框和標題欄用來顯示內容的區域。
這兩套幾何參數分別由兩個 QRect 型的屬性代表,相關的成員函數如下:
- const QRect &geometry() const; // 獲取客戶區幾何參數
- void setGeometry(int x, int y, int w, int h); // 設置客戶取幾何參數
- void setGeometry(const QRect &rect); // 設置客戶區幾何參數
- QRect frameGeometry() const; // 獲取外邊框幾何參數
const QRect &geometry() const; // 獲取客戶區幾何參數 void setGeometry(int x, int y, int w, int h); // 設置客戶取幾何參數 void setGeometry(const QRect &rect); // 設置客戶區幾何參數 QRect frameGeometry() const; // 獲取外邊框幾何參數
這里雖然沒有直接設置外邊框幾何參數的函數,但客戶區幾何參數變化之后,外邊框的幾何參數也會隨之變化。設置幾何參數可能會使窗口的位置及大小發生變化,這時會發送窗口移動事件 QMoveEvent,如果大小有變化,還會發送窗口改變大小事件 QResizeEvent,事件的處理函數分別是 moveEvent 和 resizeEvent。注意這里的坐標都是相對於父窗口的,因此移動一個窗口並不導致它的所有部件都接收到移動事件。
注意:不要在 moveEvent 或 resizeEvent 兩個事件處理函數中設置幾何參數,否則將導致無限循環。
窗口的幾何參數也可以由用戶的操作改變,這時也會發送相應的事件。
為了方便使用,與幾何參數相關的成員函數還有以下這些:
- QPoint pos() const; // 獲得窗口左上角的坐標(外邊框幾何參數)
- QSize size() const; // 窗口大小 (客戶區幾何參數)
- int x() const; // 窗口左上角橫坐標 (外邊框幾何參數)
- int y() const; // 窗口左上角縱坐標 (外邊框幾何參數)
- int height() const; // 窗口高度 (客戶區幾何參數)
- int width() const; // 窗口寬度 (客戶區幾何參數)
QPoint pos() const; // 獲得窗口左上角的坐標(外邊框幾何參數) QSize size() const; // 窗口大小 (客戶區幾何參數) int x() const; // 窗口左上角橫坐標 (外邊框幾何參數) int y() const; // 窗口左上角縱坐標 (外邊框幾何參數) int height() const; // 窗口高度 (客戶區幾何參數) int width() const; // 窗口寬度 (客戶區幾何參數)
可以看出,坐標全部是外邊框幾何參數,而大小全部是客戶區幾何參數。要獲得外邊框的大小需要用下面這個成員函數:
- QSize frameSize() const; // 窗口大小 (外邊框幾何參數)
QSize frameSize() const; // 窗口大小 (外邊框幾何參數)
改變這些屬性可以用下面這些成員函數:
- void move(int x, int y); // 將窗口左上角移動到坐標(x, y)處;
- void move(const QPoint &pos); // 將窗口左上角移動到 pos 處;
- void resize(int w, int h); // 將窗口的寬度改為 w, 高度改為 h
- void resize(const QSize &size); // 將窗口的大小改為 size
void move(int x, int y); // 將窗口左上角移動到坐標(x, y)處; void move(const QPoint &pos); // 將窗口左上角移動到 pos 處; void resize(int w, int h); // 將窗口的寬度改為 w, 高度改為 h void resize(const QSize &size); // 將窗口的大小改為 size
同樣,這里 move 函數用的是外邊框幾何參數,而 resize 函數用的是客戶區幾何參數。
還有一個屬性比較特殊,相關的成員函數如下:
- QRect rect() const; // 獲取窗口區域
QRect rect() const; // 獲取窗口區域
它獲得的坐標都是相對於窗口自己的客戶區的,也就是說橫縱坐標永遠為 0。
注意: 對於一個窗口部件來說,它的兩套幾何參數是一致的。
可見性與隱藏
可見性指的是窗口是否顯示在屏幕上的屬性。被其他窗口暫時遮擋住的窗口也屬於可見的。可見性由窗口的 visible 屬性表示,與之相關的成員函數如下:
- bool isVisible() const; // 判斷窗口是否可見
- bool isHidden() const; // 判斷窗口是否隱藏
- virtual void setVisible(bool visible); // 設置窗口是否隱藏
- void setHidden(bool hidden); // 等價於 setvisible(!hidedn);
bool isVisible() const; // 判斷窗口是否可見 bool isHidden() const; // 判斷窗口是否隱藏 virtual void setVisible(bool visible); // 設置窗口是否隱藏 void setHidden(bool hidden); // 等價於 setvisible(!hidedn);
visible 屬性為 true 時表示窗口可見,為 false 時表示窗口不可見。這里要注意的是,setVisible 函數實際上設置的是窗口是否隱藏,而不是可見性。可見性與隱藏有如下關系。
1)隱藏的窗口一定是不可見的。
2)非隱藏的窗口在它的父窗口可見的情況下也是可見的。
3)非隱藏的頂級窗口是可見的。
setVisible 和 setHidden 同時也是槽,它們一般並不直接使用,而是使用以下幾個槽:
- void show(); // 顯示窗口,等價於 setVisible(true);
- void hide(); // 隱藏窗口,等價於 setHidden(true);
void show(); // 顯示窗口,等價於 setVisible(true); void hide(); // 隱藏窗口,等價於 setHidden(true);
當窗口顯示時,將發送 QShowEvent 事件;當窗口隱藏時,將發送 QHideEvent 事件。事件的處理函數分別是 showEvent 和 hideEvent。
窗口狀態
獨立窗口有正常、全屏、最大化、最小化幾種狀態,與之相關的成員函數如下:
- bool isMinimized() const; // 判斷窗口是否為最小化
- bool isMaximized() const; // 判斷窗口是否為最大化
- bool isFullScreen() const; // 判斷窗口是否為全屏
- void showMinimized(); // 以最小化方式顯示窗口,這是一個槽
- void showMaximized(); // 以最大化方式顯示窗口,這是一個槽
- void showFullScreen(); // 以全屏方式顯示窗口,這是一個槽
- void showNormal(); // 以正常方式顯示窗口,這是一個槽
bool isMinimized() const; // 判斷窗口是否為最小化 bool isMaximized() const; // 判斷窗口是否為最大化 bool isFullScreen() const; // 判斷窗口是否為全屏 void showMinimized(); // 以最小化方式顯示窗口,這是一個槽 void showMaximized(); // 以最大化方式顯示窗口,這是一個槽 void showFullScreen(); // 以全屏方式顯示窗口,這是一個槽 void showNormal(); // 以正常方式顯示窗口,這是一個槽
注意后 4 個函數同時也是槽。全屏方式與最大化的區別在於:全屏方式下窗口的邊框和標題欄消失,客戶區占據整個屏幕。窗口的各種狀態僅對獨立窗口有效,對窗口部件來說沒有意義。
另外還有一個 windowState 屬性和窗口狀態有關,相關的成員函數如下:
- Qt::WindowStates windowState() const; // 獲取窗口狀態
- void setWindowState(Qt::WindowStates windowState); // 設置窗口狀態
Qt::WindowStates windowState() const; // 獲取窗口狀態 void setWindowState(Qt::WindowStates windowState); // 設置窗口狀態
這里的 Qt::WindowStates 類型有以下幾個取值。
1)Qt::WindowNoState:無標志,正常狀態。
2)Qt::WindowMinimized:最小化狀態。
3)Qt::WindowMaxmized:最大化狀態。
4)Qt::WindowFullScreen:全屏狀態。
5)Qt::WindowActive:激活狀態。
這里取值可以用 “按位或” 的方式組合起來使用。
需要注意的是,調用 setWindowState 函數將使窗口變為隱藏狀態。
使能
處於使能狀態的窗口才能處理鍵盤和鼠標等輸入事件,反之,處於禁用狀態的窗口不能處理這些事件。窗口是否處於使能狀態由屬性 enabled 表示,相關成員函數如下:
- bool isEnabled() const; // 獲得窗口的使能裝態
- void setEnabled(bool enable); // 設置窗口的使能狀態,這是一個槽
- void setDisabled(bool disabled); // 等價於 setEnabled(!disable),這是一個槽
bool isEnabled() const; // 獲得窗口的使能裝態 void setEnabled(bool enable); // 設置窗口的使能狀態,這是一個槽 void setDisabled(bool disabled); // 等價於 setEnabled(!disable),這是一個槽
其中兩個設置屬性的函數同時也是槽。窗口的使能狀態也可能影響外觀,比如處於禁用狀態的按鈕文本本身為灰色。
使能狀態和窗口的可見性有相似的邏輯:禁用一個窗口同 時會使它的所有子窗口成為禁用狀態。
激活狀態
當有多個獨立窗口同時存在時,只有一個窗口能夠處於激活狀態。系統產生的鍵盤、鼠標等輸入事件將被發送給處於激活狀態的窗口。一般來說,這樣的窗口會被提升到堆疊層次的最上面,除非其他窗口有總在最上面的屬性。與激活狀態相關的成員函數如下:
- bool isActiveWindow() const; // 判斷窗口所在的獨立窗口是否激活
- void activateWindow(); // 設置窗口所在的獨立窗口為激活狀態
bool isActiveWindow() const; // 判斷窗口所在的獨立窗口是否激活 void activateWindow(); // 設置窗口所在的獨立窗口為激活狀態
注意:這里操作的其實不是窗口本身,而是窗口所在的獨立窗口,因為窗口部件時沒有激活狀態的概念的。
焦點
焦點用來控制同一個獨立窗口內哪一個部件可以接受鍵盤事件,同一時刻只能有一個部件獲得焦點。與焦點有關的成員函數如下:
- bool hasFocus() const; // 判斷窗口是否獲得焦點
- void setFocus(); // 使窗口獲得焦點,這是一個槽
- void clearFocus(); // 使窗口失去焦點
- QWidget *focusWidget() const; // 得到窗口內獲得焦點的子窗口
bool hasFocus() const; // 判斷窗口是否獲得焦點 void setFocus(); // 使窗口獲得焦點,這是一個槽 void clearFocus(); // 使窗口失去焦點 QWidget *focusWidget() const; // 得到窗口內獲得焦點的子窗口
setFocus 函數同時又是一個槽。窗口部件得到焦點以后,別忘了還需要它所在的獨立窗口處於激活狀態才能得到鍵盤事件。
一個窗口獲得焦點,同時意味着另一個窗口失去焦點。當窗口獲得或失去焦點時,將發送 QFocusEvent 事件,它有兩個處理函數:forceInEvent 和 focusOutEvent,分別對應獲得焦點和失去焦點。
值得一提的是 editFocus 屬性,這是一個專門用於嵌入式系統的屬性。因為嵌入式系統通常鍵盤較小,沒有專門用於切換焦點的 Tab 鍵,所以上下方向鍵被用來切換焦點。如果一個窗口部件設置 editFocus 屬性為 true,則上下方向鍵就不再用於切換焦點,而是發送給這個窗口。與這個屬性相關的成員函數如下:
- bool hasEditfocus() const; // 判斷窗口是否有 editFocus 屬性
- void QWidget::setEditFocus(bool enable); // 設置窗口的 editFocus 屬性
bool hasEditfocus() const; // 判斷窗口是否有 editFocus 屬性 void QWidget::setEditFocus(bool enable); // 設置窗口的 editFocus 屬性
捕獲鍵盤和鼠標事件
窗口部件即使獲得焦點,也不一定能獲得按鍵事件,因為其他窗口可能會捕獲鍵盤事件。捕獲了鍵盤事件的窗口將得到所有鍵盤事件,而其他窗口將完全得到不到鍵盤事件,直到捕獲了鍵盤事件的窗口釋放鍵盤事件。與鍵盤事件捕獲相關的成員函數如下:
- void grabKeyboard(); // 捕獲鍵盤事件
- void releaseKeyboard(); // 釋放鍵盤事件
void grabKeyboard(); // 捕獲鍵盤事件 void releaseKeyboard(); // 釋放鍵盤事件
類似的還有鼠標事件的捕獲和釋放,其成員函數如下:
- void grabMouse(); // 捕獲鼠標事件
- void releaseMouse(); // 釋放鼠標事件
void grabMouse(); // 捕獲鼠標事件 void releaseMouse(); // 釋放鼠標事件
對鍵盤事件和鼠標事件的捕獲是相互獨立的。這里要注意兩點:一是如果有另外一個窗口進行了捕獲操作,則當前處於捕獲狀態的窗口將失去對事件的捕獲;二是只有可見的窗口才能進行輸入事件捕獲。
以下的成員函數能夠得到應用程序中正在捕獲鍵盤或鼠標事件的窗口:
- QWidget *keyboardGrabber(); // 得到正在捕獲鍵盤事件的窗口
- QWidget *mouseGrabber(); // 得到正在捕獲鼠標事件的窗口
QWidget *keyboardGrabber(); // 得到正在捕獲鍵盤事件的窗口 QWidget *mouseGrabber(); // 得到正在捕獲鼠標事件的窗口
這兩個函數是靜態函數。
布局
屬性 layout 代表窗口的頂級布局,相關的成員函數如下:
- QLayout *layout() const; // 獲得頂級布局
- void setLayout(QLayout *layout); // 設置頂級布局
QLayout *layout() const; // 獲得頂級布局 void setLayout(QLayout *layout); // 設置頂級布局
字體
font 屬性表示所用的字體,相關的成員函數如下:
- const QFont &font() const; // 獲得字體
- void setFont(const QFont &); // 設置字體
const QFont &font() const; // 獲得字體 void setFont(const QFont &); // 設置字體
如果沒有為窗口設置字體,則窗口自動使用父窗口的字體,頂級窗口則使用應用程序的默認字體。
信號
當窗口要被析構時會發射以下信號:
- void destoryed(QObject *obj = 0);
void destoryed(QObject *obj = 0);
這是一個從 QOjbect 類繼承過來的信號。QObject 對象析構時,先發射這個信號,然后才析構它的所有子對象。
槽
在前面的介紹中已經提及了 QWidget 類的許多槽,這里將介紹其他常用的槽。
下面的槽可以關閉窗口:
- bool close();
bool close();
當這個槽被調用時,首先向這個窗口發送一個關閉事件,如果事件被接受,則窗口隱藏,如果被拒絕,則什么也不做。如果窗口設置了 Qt::WA_QuitOnClose 屬性,則窗口對象會被析構,大多數類型的窗口都默認設置了這個屬性。
這個槽的返回值表示關閉事件是否被接受,也就是窗口是否真的被關閉了。
下面的槽可以提升或降低窗口所在的堆疊層次:
- void lower(); // 降低窗口到最下面
- void raise(); // 提升窗口到最上面
void lower(); // 降低窗口到最下面 void raise(); // 提升窗口到最上面
事件
QWidget 類能夠處理類型豐富的事件,這里將介紹一些常用的事件處理函數。
窗口事件:
- virtual void closeEvent(QCloseEvent *event); // 關閉
- virtual void showEvent(QShowEvent *event); // 顯示
- virtual void hideEvent(QHideEvent *event); // 隱藏
- virtual void moveEvent(QMoveEvent *evnet); // 移動
- virtual void resizeEvent(QResizeEvent *event); // 改變大小
virtual void closeEvent(QCloseEvent *event); // 關閉 virtual void showEvent(QShowEvent *event); // 顯示 virtual void hideEvent(QHideEvent *event); // 隱藏 virtual void moveEvent(QMoveEvent *evnet); // 移動 virtual void resizeEvent(QResizeEvent *event); // 改變大小
這里通過 QMoveEvent 類的以下成員函數可以獲得窗口的舊坐標和新坐標:
- const QPoint &oldPos() const; // 舊坐標
- const QPoint &newPos() constl // 新坐標
const QPoint &oldPos() const; // 舊坐標 const QPoint &newPos() constl // 新坐標
通過 QResizeEvent 類的以下成員函數可以獲得窗口的舊大小和新大小:
- const QSize &oldSize() const; // 舊大小
- const QSize &newSize() const; // 新大小
const QSize &oldSize() const; // 舊大小 const QSize &newSize() const; // 新大小
鍵盤事件:
- virtual void keyPressEvent(QKeyEvent *event); // 鍵按下
- virtual void keyReleaseEvent(QKeyEvent *event); // 鍵松開
virtual void keyPressEvent(QKeyEvent *event); // 鍵按下 virtual void keyReleaseEvent(QKeyEvent *event); // 鍵松開
這里通過 QKeyEvent 類的成員函數可以獲得關於按鍵的一些信息,如:
- int key() const; // 得到鍵值
int key() const; // 得到鍵值
鼠標事件:
- virtual void mousePressEvent(QMouseEvent *event); // 鼠標鍵按下
- virtual void mouseReleaseEvent(QMouseEvent *event); // 鼠標鍵松開
- virtual void mouseDoubleCllckEvent(QMouseEvent *event); // 鼠標鍵雙擊
- virtual void mouseMoveEvent(QMouseEvent *event); // 鼠標移動
- virtual void enterEvent(QEvent *event); // 鼠標進入窗口
- virtual void leaveEvent(QEvent *event); // 鼠標離開窗口
- virtual void wheelEvent(QWheelEvent *event); // 鼠標滾輪移動
virtual void mousePressEvent(QMouseEvent *event); // 鼠標鍵按下 virtual void mouseReleaseEvent(QMouseEvent *event); // 鼠標鍵松開 virtual void mouseDoubleCllckEvent(QMouseEvent *event); // 鼠標鍵雙擊 virtual void mouseMoveEvent(QMouseEvent *event); // 鼠標移動 virtual void enterEvent(QEvent *event); // 鼠標進入窗口 virtual void leaveEvent(QEvent *event); // 鼠標離開窗口 virtual void wheelEvent(QWheelEvent *event); // 鼠標滾輪移動
這里通過 QMouseEvent 事件的成員函數可獲得關於鼠標的信息,如:
- const QPoint &pos() const; // 得到鼠標坐標(相對於接收事件的窗口)
- int x() const; // 得到鼠標橫坐標(相對於接收事件的窗口)
- int y() const; // 得到鼠標縱坐標(相對於接收事件的窗口)
- const QPoint &globalPos() const; // 得到鼠標坐標(全局坐標)
- int globalX() const; // 得到鼠標橫坐標 (全局坐標)
- int globalY() const; // 得到鼠標縱坐標 (全局坐標)
- Qt::MouseButton button() const; // 得到引起事件的鼠標鍵
- Qt::MouseButtons buttons() const; // 得到事件發生時的鼠標鍵狀態
const QPoint &pos() const; // 得到鼠標坐標(相對於接收事件的窗口) int x() const; // 得到鼠標橫坐標(相對於接收事件的窗口) int y() const; // 得到鼠標縱坐標(相對於接收事件的窗口) const QPoint &globalPos() const; // 得到鼠標坐標(全局坐標) int globalX() const; // 得到鼠標橫坐標 (全局坐標) int globalY() const; // 得到鼠標縱坐標 (全局坐標) Qt::MouseButton button() const; // 得到引起事件的鼠標鍵 Qt::MouseButtons buttons() const; // 得到事件發生時的鼠標鍵狀態
其中,Qt::MouseButton 是一個枚舉類型,有以下常用取值。
1)Qt::NoButton:無鍵。
2)Qt::LeftButton:左鍵。
3)Qt::RightButton:右鍵。
4)Qt::MidButton:中鍵。
注意,對於鼠標移動事件 QMouseEvent 和 button 函數總是返回 Qt::NoButton,而 buttons 函數返回值則是 Qt::MouseButton 類型的 “按位或” 組合,它能反映事件發生時鼠標鍵的按下狀態。
QWheelEvent 類代表滾輪事件,它有一套與 QMountEvent 類幾乎相同的成員函數,但少一個 button 函數,多以下兩個函數:
- int delta() const; // 獲得滾輪轉動的角度
- Qt::Orientation orientationI() const; // 獲得滾輪轉動的方向
int delta() const; // 獲得滾輪轉動的角度 Qt::Orientation orientationI() const; // 獲得滾輪轉動的方向
其中 Qt::Orientation 是一個枚舉類型,它有以下取值。
1)Qt::Horizontal:橫向。
2)Qt::Vertical:縱向。
焦點事件:
- virtual void focusInEvent(QFocusEvent *event); // 獲得焦點
- virtual void focusOutEvent(QFocusEvent *event); // 時取焦點
virtual void focusInEvent(QFocusEvent *event); // 獲得焦點 virtual void focusOutEvent(QFocusEvent *event); // 時取焦點
這些事件處理函數都沒有返回值,因此如果要接受或拒絕和一個事件要調用 QEvent 類的成員函數,如:
- event->accept(); // 接受事件
- event->ignore(); // 拒絕事件
event->accept(); // 接受事件 event->ignore(); // 拒絕事件
事件被拒絕后的結果視具體情況而定,比如關閉事件被拒絕后,窗口將不會被關閉,而鍵盤、鼠標等輸入事件被拒絕后會向上傳播到父窗口。