常用的窗體基類是 QWidget、QDialog 和 QMainWindow,在創建 GUI 應用程序時選擇窗體基類就是從這 3 個類中選擇。
QWidget 直接繼承於 QObject,是 QDialog 和 QMainWindow 的父類,其他繼承於 QWidget 的窗體類還有 QSplashScreen、QMdiSubWindow 和 QDesktopWidget。另外還有一個類 QWindow,它同時從 QObject 和 QSurface 繼承。這些類的繼承關系如圖 1 所示。
圖 1 幾個窗體類的繼承關系
這些窗體類的主要特點和用途如下:
這段代碼就用到了兩個設置函數——setAttribute() 和 setWindowFlags(),它們可以設置窗體的顯示特性和運行特性。
下面介紹 QWidget 類中用於窗體屬性設置的幾個主要函數的功能。
另外一個函數 setWindowFlag() 用於一次設置一個標記,其函數原型為:
Qt::Widget、Qt::Window 等表示窗體類型的常量可以使窗體具有缺省的外觀設置,如果設置為 Qt::Dialog 類型,則窗體具有對話框的缺省外觀,例如標題欄沒有最小化、最大化按鈕。
控制窗體顯示效果和外觀的設置項可定制窗體的外觀,例如設置一個窗體只有最小化最大化按鈕,沒有關閉按鈕。
圖 6 實例samp6_3的主窗口
程序的主窗口類是 QWMainWindow,從 QMainWindow 繼承。主窗口有一個工具欄,4 個創建窗體的按鈕以不同方式創建和使用窗體。主窗體工作區繪制一個背景圖片,有一個 tabWidget 組件,作為創建窗體的父窗體。沒有子窗體時,tabWidget 不顯示。
下面是 QWMainWindow 的構造函數和繪制背景圖片的代碼:
在構造函數中,將 tabWidget 組件設置為不可見,並且頁面可關閉,這樣每個頁面標題部分都會出現一個關閉按鈕,單擊可以關閉頁面。
背景圖片繪制使用窗體的 paintEvent() 事件,獲取主窗口的畫筆之后,將資源文件里的一個圖片繪制在主窗口的工作區。繪圖的內容在后續章節中詳細介紹。
實例除了主窗口之外,還有兩個窗口和兩個對話框:
在 QFormDoc 的窗口上只放置一個 QPlainTextEdit 組件。由於 QFormDoc 是從 QWidget 繼承而來的,在 UI 設計器里不能直接為 QFormDoc 設計工具欄,但是可以創建 Action,然后在窗體創建時用代碼創建工具欄。
圖 7 QFormDoc 窗口設計的 Action
圖 7 是設計的 Action 除了 actOpen 和 actFont 之外,其他編輯操作的 Action 都和 QPlainTextEdit 相關槽函數關聯,actClose 與窗口的 close() 槽函數關聯。
這段代碼動態創建一個 QFormDoc 類對象 formDoc,並設置其為關閉時刪除。然后使用 QTabWidget 的 addTab() 函數,為主窗口上的 tabWidget 新建一個頁面,作為 formDoc 的父窗體組件,formDoc 就在新建的頁面里顯示,我們稱這種窗體顯示方式為“嵌入式”。
主窗口工具欄上的“獨立 Widget 窗口”按鈕響應代碼如下:
這里在創建 formDoc 對象時,並沒有指定父窗口,創建窗口的代碼是:
如果創建 formDoc 時指定主窗口為父窗口,即:
圖 8 是嵌入式和獨立的 QFormDoc 窗體的顯示效果,在創建獨立的顯示窗口時,還可以嘗試使用 setWindowFlag() 函數設置不同的屬性,觀察這些屬性的控制效果。
圖 8 嵌入式和獨立的 QFormDoc 窗體顯示效果
該窗口的具體設計不詳細介紹了,只是為了觀察窗口刪除的時機,在析構函數里增加一個信息顯示對話框:
代碼功能是創建一個 QFormTable 對象 formTable,並在主窗口的 tabWidget 組件里新增一個頁面,將 formTable 顯示在新增頁面里。所以,即使是從 QMainWindow 繼承的窗口類,也是可以在其他界面組件里嵌入式顯示的。
主窗口工具欄上的“獨立 MainWindow 窗口”按鈕響應代碼如下:
這樣創建的 formTable 以獨立窗口顯示,關閉時自動刪除。它指定了主窗口為父窗口,主窗口關閉時,所有 QFormTable 類窗口自動刪除。
無論是嵌入式的,還是獨立的 QFormTable 窗口,都可以調用 QWDialogSize 和 QWDialogHeaders 對話框進行表格大小和表頭文字設置,對話框的調用方法在前面章節己有介紹。創建 QFormTable 嵌入式窗體和獨立窗口的運行效果如圖 9 所示。
圖 9 嵌入式和獨立的QFormDoc窗體顯示效果
為此,需要對 tabWidget 的兩個信號編寫槽函數,tabCloseRequested() 和 currentChanged() 信號的槽函數代碼如下:
tabCloseRequested() 信號在單擊分頁的關閉圖標時發射,傳遞來的參數 index 表示頁面的編號。QTabWidget::widget() 返回 TabWidget 組件中某個頁面的窗體組件。獲取頁面的 QWidget 組件后,調用 close() 函數關閉窗體。
刪除一個分頁或切換頁面時,會發射 currentChanged() 信號,在此信號的槽函數里判斷分頁個數是否為零,以控制 tabWidget 是否可見。
QWidget 直接繼承於 QObject,是 QDialog 和 QMainWindow 的父類,其他繼承於 QWidget 的窗體類還有 QSplashScreen、QMdiSubWindow 和 QDesktopWidget。另外還有一個類 QWindow,它同時從 QObject 和 QSurface 繼承。這些類的繼承關系如圖 1 所示。

圖 1 幾個窗體類的繼承關系
這些窗體類的主要特點和用途如下:
- QWidget:在沒有指定父容器時可作為獨立的窗口,指定父容器后可以作為容器的內部組件。
- QDialog:用於設計對話框,以獨立窗口顯示。
- QMainWindow:用於設計帶有菜單欄、工具欄、狀態欄的主窗口,一般以獨立窗口顯示。
- QSplashScreen:用作應用程序啟動時的splash窗口,沒有邊框。
- QMdiSubWindow:用於為 QMdiArea 提供一個子窗體,用於MDI(多文檔)應用程序的設計。
- QDesktopWidget:具有多個顯卡和多個顯示器的系統具有多個桌面,這個類提供用戶桌面信息,如屏幕個數、每個屏幕的大小等。
- QWindow:通過底層的窗口系統表示一個窗口的類,一般作為一個父容器的嵌入式窗體,不作為獨立窗體。
窗體類重要特性的設置
窗體顯示或運行的一些特性可以通過 QWidget 的一些函數設置,如在前面章節中,介紹對話框的創建和使用時,有如下的代碼:- dlgLocate = new QWDialogLocate(this);
- dlgLocate->setAttribute(Qt::WA_DeleteOnClose);
- Qt::WindowFlags flags=dlgLocate->windowFlags();
- dlgLocate->setWindowFlags(flags | Qt::WindowStaysOnTopHint);
下面介紹 QWidget 類中用於窗體屬性設置的幾個主要函數的功能。
setAttribute()函數
setAttribute() 函數用於設置窗體的一些屬性,其函數原型為:void QWidget::setAttribute(Qt::WidgetAttribute attribute, bool on = true)
枚舉類型 Qt::WidgetAttribute 定義了窗體的一些屬性,可以打開或關閉這些屬性。枚舉類型 Qt::WidgetAttribute 常用的常量及其意義見表 2。常量 | 意義 |
---|---|
Qt:: WA_AcceptDrops | 允許窗體接收拖放來的組件 |
Qt::WA_DeleteOnClose | 窗體關閉時刪除自己,釋放內存 |
Qt::WA_Hover | 鼠標進入或移出窗體時產生paint事件 |
Qt:: WAAcceptTouchEvents | 窗體是否接受觸屏事件 |
setWindowFlags()函數
setWindowFlags() 函數用於設置窗體標記,其函數原型是:void QWidget::setWindowFlags(Qt::WindowFlags type)
參數 type 是枚舉類型 Qt::WindowType 的值的組合,用於同時設置多個標記。另外一個函數 setWindowFlag() 用於一次設置一個標記,其函數原型為:
void QWidget::setWindowFlag(Qt::WindowType flag, bool on = true)
可單獨打開或關閉某個屬性。枚舉類型 Qt::WindowType 常用的常量值見表 3。常量 | 意義 |
---|---|
表示窗體類型的常量 | |
Qt::Widget | 這是 QWidget 類的缺省類型。這種類型的窗體,如果它有父窗體,就作為父窗 體的子窗體;否則就作為一個獨立的窗口 |
Qt::Window | 表明這個窗體是一個窗口,通常具有窗口的邊框、標題欄,而不管它是否有父窗體 |
Qt::Dialog | 表明這個窗體是一個窗口,並且要顯示為對話框(例如在標題欄沒有最小化、 最大化按鈕)。這是 QDialog 類的缺省類型 |
Qt::Popup | 表明這個窗體是用作彈出式菜單的窗體 |
Qt::Tool | 表明這個窗體是工具窗體,具有更小的標題欄和關閉按鈕,通常作為工具欄的 窗體 |
Qt::ToolTip | 表明這是用於 Tooltip 消息提示的窗體 |
Qt::SplashScreen | 表明窗體是splash屏幕,是 QSplashScreen 類的缺省類型 |
Qt::Desktop | 表明窗體是桌面,這是 QDesktopWidget 類的類型 |
Qt::SubWindow | 表明窗體是子窗體,例如 QMdiSubWindow 就是這種類型 |
控制窗體顯示效果的常量 | |
Qt::MSWindowsFixedSizeDialogHint | 在 Windows 平台上,使窗口具有更窄的邊框,用於固定大小的對話框 |
Qt::FramelessWindowHint | 創建無邊框窗口 |
WindowHint要定義窗體外觀定制窗體外觀的常量,需要先設置 Qt::Customize | |
Qt::CustomizeWindowHint | 關閉缺省的窗口標題欄 |
Qt::WindowTitleHint | 窗口有標題欄 |
Qt::WindowSystemMenuHint | 有窗口系統菜單 |
Qt::WindowMinimizeButtonHint | 有最小化按鈕 |
Qt::WindowMaximizeButtonHint | 有最大化按鈕 |
Qt::WindowMinMaxButtonsHint | 有最小化、最大化按鈕 |
Qt::WindowCloseButtonHint | 有關閉按鈕 |
Qt::Windo wContextHelpButtonHint | 有上下文幫助按鈕 |
Qt::WindowStaysOnTopHint | 窗口總是處於最上層 |
Qt::WindowStaysOnBottomHint | 窗口總是處於最下層 |
Qt::WindowTransparentForlnput | 窗口只作為輸出,不接受輸入 |
Qt::Widget、Qt::Window 等表示窗體類型的常量可以使窗體具有缺省的外觀設置,如果設置為 Qt::Dialog 類型,則窗體具有對話框的缺省外觀,例如標題欄沒有最小化、最大化按鈕。
控制窗體顯示效果和外觀的設置項可定制窗體的外觀,例如設置一個窗體只有最小化最大化按鈕,沒有關閉按鈕。
setWindowState()函數
setWindowState() 函數使窗口處於最小化、最大化等狀態,其函數原型是:void QWidget::setWindowState(Qt::WindowStates windowstate)
枚舉類型 Qt::WindowState 表示了窗體的狀態,其取值見表 4。常量 | 意義 |
---|---|
Qt: :WindowNoState | 正常狀態 |
Qt: :WindowMinimized | 窗口最小化 |
Qt:: WindowMaximized | 窗口最大化 |
Qt::WindowFullScreen | 窗口填充整個屏幕,而且沒有邊框 |
Qt:: Window Active | 變為活動的窗口,例如可以接收鍵盤輸入 |
setWindowModality()函數
setWindowModality() 函數用於設置窗口的模態,只對窗口類型有用。其函數原型為:void setWindowModality(Qt::WindowModality windowModality)
枚舉類型 Qt::WindowModality 的取值意義見表 5。常量 | 意義 |
---|---|
Qt::NonModal | 無模態,不會阻止其他窗口的輸入 |
Qt::WindowModal | 窗口對於其父窗口、所有的上級父窗口都是模態的 |
Qt::ApplicationModal | 窗口對整個應用程序是模態的,阻止所有窗口的輸入 |
setWindowOpacity()函數
setWindowOpacity() 函數用於設置窗口的透明度,其函數原型如下:void QWidget::setWindowOpacity(qreal level)
參數 level 是 1.0(完全不透明)至 0.0(完全透明)之間的數。窗口透明度缺省值是 1.0,即完全不透明。多窗口應用程序的設計
主窗口設計
本節以實例 samp6_3 演示多窗口應用程序的設計,實例主窗口如圖 6 所示。
圖 6 實例samp6_3的主窗口
程序的主窗口類是 QWMainWindow,從 QMainWindow 繼承。主窗口有一個工具欄,4 個創建窗體的按鈕以不同方式創建和使用窗體。主窗體工作區繪制一個背景圖片,有一個 tabWidget 組件,作為創建窗體的父窗體。沒有子窗體時,tabWidget 不顯示。
下面是 QWMainWindow 的構造函數和繪制背景圖片的代碼:
- QWMainWindow::QWMainWindow(QWidget *parent) :
- QMainWindow(parent),
- ui(new Ui::QWMainWindow)
- {
- ui->setupUi(this);
- ui->tabWidget->setVisible(false);
- ui->tabWidget->clear();//清除所有頁面
- ui->tabWidget->tabsClosable(); //Page有關閉按鈕,可被關閉
- this->setCentralWidget(ui->tabWidget);
- this->setWindowState(Qt::WindowMaximized); //窗口最大化顯示
- this->setAutoFillBackground(true);
- }
- void QWMainWindow::paintEvent(QPaintEvent *event)
- { //繪制窗口背景圖片
- Q_UNUSED(event);
- QPainter painter(this);
- painter.drawPixmap(0,ui->mainToolBar->height(),this->width(),this->height()-ui->mainToolBar->height()-ui->statusBar->height(),QPixmap(":/images/images/back2.jpg"));
- }
背景圖片繪制使用窗體的 paintEvent() 事件,獲取主窗口的畫筆之后,將資源文件里的一個圖片繪制在主窗口的工作區。繪圖的內容在后續章節中詳細介紹。
實例除了主窗口之外,還有兩個窗口和兩個對話框:
- QFormDoc:是繼承於 QWidget 可視化設計的窗體,主窗口工具欄上的“嵌入式 Widget”和“獨立 Widget 窗口”按鈕將以兩種方式使用 QFormDoc 類。
- QFormTable:是繼承於 QMainWindow 可視化設計的窗體,其界面功能與實例 samp6_2 的主窗口類似,主窗口工具欄上的“嵌入式 MainWindow”和“獨立 MainWindow 窗口”按鈕將以兩種方式使用 QFormTable 類。
- QWDialogSize 和 QWDialogHeaders 就是實例 samp6_2 中設計的對話框類,由 QFormTable 調用進行表格組件設置。
QFormDoc類的設計
在 Qt Creator 單擊File->New File or Project
菜單項,在出現的對話框里選擇創建
Qt Designer Form Class
,並且在向導中選擇基類為 QWidget,將創建的新類命名為 QFormDoc。
在 QFormDoc 的窗口上只放置一個 QPlainTextEdit 組件。由於 QFormDoc 是從 QWidget 繼承而來的,在 UI 設計器里不能直接為 QFormDoc 設計工具欄,但是可以創建 Action,然后在窗體創建時用代碼創建工具欄。

圖 7 QFormDoc 窗口設計的 Action
圖 7 是設計的 Action 除了 actOpen 和 actFont 之外,其他編輯操作的 Action 都和 QPlainTextEdit 相關槽函數關聯,actClose 與窗口的 close() 槽函數關聯。
actOpen 用於打開文件,actFont 用於設置文檔字體,這些功能在前面的例子里都遇到過,不是本實例的重點,不再介紹其實現代碼。
在 QFormDoc 的構造函數里用代碼創建工具欄和布局,也可以在析構函數里增加一個消息顯示的對話框,以便觀察窗體是何時被刪除的。代碼如下:- QFormDoc::QFormDoc(QWidget *parent) :
- QWidget(parent),
- ui(new Ui::QFormDoc)
- {
- ui->setupUi(this);
- //使用UI設計的Actions設計工具欄
- QToolBar* locToolBar = new QToolBar(tr("文檔"),this); //創建工具欄
- locToolBar->addAction(ui->actOpen);
- locToolBar->addAction(ui->actFont);
- locToolBar->addSeparator();
- locToolBar->addAction(ui->actCut);
- locToolBar->addAction(ui->actCopy);
- locToolBar->addAction(ui->actPaste);
- locToolBar->addAction(ui->actUndo);
- locToolBar->addAction(ui->actRedo);
- locToolBar->addSeparator();
- locToolBar->addAction(ui->actClose);
- locToolBar->setToolButtonStyle(Qt::ToolButtonTextBesideIcon);
- QVBoxLayout *Layout = new QVBoxLayout();
- Layout->addWidget(locToolBar); //設置工具欄和編輯器上下布局
- Layout->addWidget(ui->plainTextEdit);
- Layout->setContentsMargins(2,2,2,2); //減小邊框的寬度
- Layout->setSpacing(2);
- this->setLayout(Layout); //設置布局
- }
- QFormDoc::~QFormDoc()
- {
- QMessageBox::information(this, "消息", "QFormDoc對象被刪除和釋放");
- delete ui;
- }
QFormDoc類的使用
主窗口工具欄上的“嵌入式 Widget”按鈕的響應代碼如下:- void QWMainWindow::on_actWidgetInsite_triggered()
- {
- //創建QFormDoc窗體,並在tabWidget中顯示
- QFormDoc *formDoc = new QFormDoc(this);
- formDoc->setAttribute (Qt: : WA_DeleteOnClose) ; //關閉時自動刪除
- int cur=ui->tabWidget->addTab(formDoc,QString::asprintf("Doc %d",ui->tabWidget->count()));
- ui->tabWidget->setCurrentIndex(cur);
- ui->tabWidget->setVisible(true);
- }
主窗口工具欄上的“獨立 Widget 窗口”按鈕響應代碼如下:
- void QWMainWindow::on_actWidget_triggered()
- {
- QFormDoc *formDoc = new QFormDoc(); //不指定父窗口,用show()顯示
- formDoc->setAttribute(Qt::WA_DeleteOnClose); //關閉時自動刪除
- formDoc->setWindowTitle("基於QWidget的窗體,無父窗口,關閉時刪除");
- formDoc->setWindowFlag(Qt::Window,true);
- //formDoc->setWindowFlag(Qt::CustomizeWindowHint,true);
- //formDoc->setWindowFlag(Qt::WindowMinMaxButtonsHint,true);
- //formDoc->setWindowFlag(Qt::WindowCloseButtonHint,true);
- //formDoc->setWindowFlag(Qt::WindowStaysOnTopHint,true);
- //formDoc->setWindowState(Qt::WindowMaximized);
- formDoc->setWindowOpacity(0.9);
- //formDoc->setWindowModality(Qt::WindowModal);
- formDoc->show(); //在單獨的窗口中顯示
- }
QFormDoc *formDoc = new QFormDoc();
使用 setWindowFlag() 函數,設置其為 Qt::Window 類型,並用 show() 函數顯不窗口。這樣創建的是一個單獨顯示的窗口,並且在 windows 的任務欄上會有顯示。若有文檔窗口打開,則關閉主窗口,而文檔窗口依然存在,實際上這時候主窗口是隱藏了。若關閉所有文檔窗口,主窗口自動刪除並釋放,才完全關閉應用程序。如果創建 formDoc 時指定主窗口為父窗口,即:
QFormDoc *formDoc = new QFormDoc(this);
則 formDoc 不會在 windows 的任務欄上顯示,關閉主窗口時,所有文檔窗口自動刪除。圖 8 是嵌入式和獨立的 QFormDoc 窗體的顯示效果,在創建獨立的顯示窗口時,還可以嘗試使用 setWindowFlag() 函數設置不同的屬性,觀察這些屬性的控制效果。

圖 8 嵌入式和獨立的 QFormDoc 窗體顯示效果
QFormTable類的設計
表格窗口類 QFormTable 是基於 QMainWindow 的可視窗口類,其功能與實例 samp6_2 主窗口類似,使用 QStandardltemModel 模型和 QTableView 組件構成 Model/View 結構的表格數據編輯器,並且可以調用 QWDialogSize 和 QWDialogHeaders 對話框進行表格大小設置和表頭設置。該窗口的具體設計不詳細介紹了,只是為了觀察窗口刪除的時機,在析構函數里增加一個信息顯示對話框:
- QFormTable::〜QFormTable()
- {
- QMessageBox::information (this, "消息","FormTable 窗口被刪除和釋放"); delete ui;
- }
QFormTable類的使用
主窗口工具欄上的“嵌入式 MainWindow”按鈕的響應代碼如下:- void QWMainWindow::on_actWindowInsite_triggered()
- {
- QFormTable *formTable = new QFormTable(this);
- formTable->setAttribute(Qt::WA_DeleteOnClose); //關閉時自動刪除
- int cur=ui->tabWidget->addTab(formTable,QString::asprintf("Table %d",ui->tabWidget->count()));
- ui->tabWidget->setCurrentIndex(cur);
- ui->tabWidget->setVisible(true);
- }
主窗口工具欄上的“獨立 MainWindow 窗口”按鈕響應代碼如下:
- void QWMainWindow::on_actWindow_triggered()
- {
- QFormTable* formTable = new QFormTable(this);
- formTable->setAttribute(Qt::WA_Delete〇nClose);
- formTable->setWindowTitle ("基於 QMainWindow 的窗口,指定父窗口,關閉時刪除");
- formTable->show();
- }
無論是嵌入式的,還是獨立的 QFormTable 窗口,都可以調用 QWDialogSize 和 QWDialogHeaders 對話框進行表格大小和表頭文字設置,對話框的調用方法在前面章節己有介紹。創建 QFormTable 嵌入式窗體和獨立窗口的運行效果如圖 9 所示。

圖 9 嵌入式和獨立的QFormDoc窗體顯示效果
QTabWidget類的控制
現在,單擊 tabWidget 中嵌入的 QFormDoc 或 QFormTable 窗體工具欄上的“關閉”按鈕,都可以關閉窗體並且刪除分頁。但是單擊分頁上的關閉圖標,並不能關閉窗口。而且,關閉所有分頁后,tabWidget 並沒有隱藏,無法顯示背景圖片。為此,需要對 tabWidget 的兩個信號編寫槽函數,tabCloseRequested() 和 currentChanged() 信號的槽函數代碼如下:
- void QWMainWindow::on_tabWidget_tabCloseRequested(int index)
- {//關閉Tab
- if (index<0)
- return;
- QWidget* aForm=ui->tabWidget->widget(index);
- aForm->close();
- }
- void QWMainWindow::on_tabWidget_currentChanged(int index)
- {
- bool en=ui->tabWidget->count()>0; //再無頁面時,actions禁用
- ui->tabWidget->setVisible(en);
- }
刪除一個分頁或切換頁面時,會發射 currentChanged() 信號,在此信號的槽函數里判斷分頁個數是否為零,以控制 tabWidget 是否可見。