Qt 入門 3 之對話框 QDialog
本文從以下幾點分開講述:
- 對話框的基本原理介紹
- 兩種不同類型的對話框
- 一個由多個窗口組成并且窗口間可以相互切換的程序
1.模態和非模態對話框
- QDialog 類是所有對話框窗口類的基類。對話框窗口是一個經常用來完成短小任務或者和用戶進行簡單交互的頂層窗口
- 按照運行對話框時是否還可以和該程序的其他窗口進行交互,對話框常被分為兩類:模態的(model) 和非模態的(modeless)。
- 新建Qt Qwidgets應用項目,名稱為mydialog1,然后項目中命名如下圖,找到
mywidget.cpp文件添加一下代碼:
#include "mywidget.h"
#include "ui_mywidget.h"
#include"qdialog.h"MyWidget::MyWidget(QWidget *parent): QWidget(parent), ui(new Ui::MyWidget)
{ui->setupUi(this);QDialog dialog(this);dialog.show();
}
- 在 MyWidget 類的構造函數中定義了一個QDialog類對象,還指定了 dialog的父窗口為 MyWidget 類對象(即this參數的作用),最后調用show()函數讓其顯示。運行程序時就發現,一個窗口一閃而過,然后就只顯示MyWidget窗口了,為什么會這樣呢?因為對于一個函數中定義的變量,等這個函數執行結束后,它就會自動釋放。也就是說,這里的 dialog對象只在這個構造函數中有用,等這個構造函數執行完了,dialog也就消失了。為了不讓dialog消失,可以將QDialog對象的創建代碼更改如下:
QDialog* dialog = new QDialog(this);dialog->setWindowTitle(QObject::tr("dialog1"));dialog->show();
- 可以正常顯示了。需要說明的是,我們說定義一個對象是指“QDialog dialog;”這樣的方式,而像“QDialog *dialog;“這樣不能被稱為定義了一個對象,而應該說成定義了一個指向QDialog類對象的指針變量。后面也會把“QDialog *dialog;"說成是定義了一個QDialog對象。再補充一點,這里為對話框對象指明了父窗口,所以就沒有必要使用delete來釋放該對象了
其實不用指針也可讓對話框顯示出來,可以將代碼修改如下:
QDialog dialog(this);dialog.exec();
- 這時運行程序就會發現對話框彈出來了,但是MyWidget(MyWidget)窗口并沒有出來,當關閉對話框后,MyWidget窗口才彈出來。這個對話框與前面那個對話框的效果不同,稱它為模態對話框,而前面那種對話框稱為非模態對話框。
- 模態對話框就是在沒有關閉它之前,不能再與同一個應用程序的其他窗口進行交互,比如新建項目時彈出的對話框。而對于非模態對話框,既可以與它交互,也可以與同一程序中的其他窗口交互,如Microsoft Word中的查找替換對話框。就像前面看到的,要想使一個對話框成為模態對話框,則只需要調用它的exec()函數;而要使其成為非模態對話框,則可以使用new操作來創建,然后使用show()函數來顯示。其實使用show()函數也可以建立模態對話框,只須在其前面使用setModal()函數即可。例如:
QDialog * dialog = new QDialog(this);
dialog->setModal(true);
dialog->show();
- 運行程序后可以看到,生成的對話框是模態的。但是,它與用exec()函數時的效果是不一樣的,因為現在的MyWidget窗口也顯示出來了。這是因為調用完show()函數后會立即將控制權交給調用者,程序可以繼續往下執行。而調用exec()數卻不同,只有當對話框被關閉時才會返回。與setModal()函數相似的還有一個setWindowModality()函數,它有一個參數來設置模態對話框要阻塞的窗口類型,可以是Qt::NonModal(不阻塞任何窗口,就是非模態)、Qt::WindowModal(阻塞它的父窗口、所有祖先窗口以及它們的子窗口)或Qt::ApplicationModal(阻塞整個應用程序的所有窗口)。而setModal()函數默認設置的是Qt::ApplicationModal。
2.多窗口切換
2.1 認識信號與槽
- Qt中使用信號與槽機制來完成對象之間的協同操作
- 簡單來說,信號和槽都是函數,比如單擊窗口上的一個按鈕后想要彈出一個對話框,那么可以將這個按鈕的單擊信號和自定義相關的槽關聯起來,在這個槽中創建一個對話框來顯示它
- 舉個例子,在之前的項目中做出如下更改:
- 在mywidget.h中加入槽函數 定義:
public:void showChildDialog();
- 在mywidget.cpp中添加槽函數定義
void MyWidget::showchildDialog()
{QDialog* dialog = new QDialog(this);dialog->show();
}
- 在mywidget.cpp 基類構造函數中添加connect函數:
connect(ui->showchildButton,&OPushButton::clicked,this, &MyWidget::showchildDialog);
-
然后點擊mywidget.ui做出如下界面編輯操作:新拉一個pushputton并更改按鈕名和顯示文本,新拉一個label并更改顯示本文
-
上述更改主要想實現以下功能:點擊 按鈕 則顯示新的子窗口
-
connect函數詳解,其時QObject類中的函數,因為QWidget繼承自QObject,因此可以直接使用
-
函數4個參數分別對應:發射信號的對象、發射的信號、接收信號的對象、要執行的槽
-
上述信號與槽的連接成為手動關聯,還有一種是自動關聯,比如前邊的槽函數可以重命名為 on_showChildButton_clicked(),就是由字符on 、發射信號的部件對象名和信號名組成
2.2 自定義對話框
-
依然在前邊的項目中更改:
-
第一步,添加自定義對話類框。依然在前面的項目中更改。首先向該項目中添加Qt設計師界面類。界面模板選擇DialogwithoutButtons,類名改為MyDialog。然后在設計模式中向窗口添加兩個PushButton,并且分別更改其顯示文本為“進人主界面”和“退出程序”
-
第二步,設計信號與槽。這里使用設計器來實現”退出程序" 按鈕的信號和槽的關聯。單擊設計器上方的Edit Signals/Slots圖標,或者按下快捷鍵F4,于是進入了部件的信號和槽的編輯模式。在“退出程序”按鈕上按住鼠標左鍵,然后拖動到窗口界面上,這時松開鼠標左鍵。在彈出的配置連接對話框中選擇“顯示從QWidget繼承的信號和槽”選項,然后在左邊的QPushButton欄中選擇信號clicked(),在右邊的 QDialog欄中選擇對應的槽close(),完成后單擊OK按鈕
-
如圖下圖所示(這里還可以單擊“編輯”按鈕添加自定義的槽,不過這還需要在MyDialog類中實現該槽)。這時“退出程序”按鈕的單擊信號就和對話框中的關閉操作槽進行了關聯。要想取消這個關聯,只須在信號和槽編輯模式中選擇這個關聯;當它變為紅色時,按下Delete鍵,或者右擊選擇“刪除”。也可以在設計器下方的信號和槽編輯器中看到設置好的關聯。當然,直接在信號和槽編輯器中建立關聯也是可以的,它與鼠標選擇部件進行關聯是等效的。設置好關聯后按下F3鍵,或者單擊“編輯控件”圖標,則回到部件編輯模式。
-
現在設置“進人主界面”按鈕的信號和槽的關聯。在該按鈕上右擊,在彈出的級聯菜單中選擇“轉到槽”,然后在彈出的對話框中選擇clicked()信號,并單擊OK按鈕。這時便會進人代碼編輯模式,并且定位到自動生成的on_pushButton_clicked()槽中在其中添加代碼:
void MyDialog::on_pushButton_clicked()
{accept();
}
- 這個 accept()函數是 QDialog類中的一個槽,對于一個使用exec()函數實現的模態對話框,執行了這個槽就會隱藏這個模態對話框,并返回QDialog::Accepted值,這里就是要使用這個值來判斷是哪個按鈕被按下了。與其對應的還有一個**reject()**槽,它可以返回一個 QDialog::Rejected值,前面的“退出程序”按鈕也可以關聯這個槽。
- 在主界面中使用自定義的對話框,更改 main 函數如下:
#include "mywidget.h"
#include"mydialog.h"
#include <QApplication>
int main(int argc, char *argv[])
{QApplication a(argc, argv);MyWidget w;//w.show();//return a.exec;MyDialog dialog;if(dialog.exec()==QDialog::Accepted){w.show();return a.exec();}else{return 0 ;}
}
- 運行程序后可以發現,已經實現了從錄對話框到主界面,再從主界面顯示一個對話框的應用了。執行后效果如下:
1744004049407
- 再來實現可以從主界面重新進入登錄界面的功能。雙擊mywidget.ui文件,在設計模式中再向界面添加兩個PushButton,分別更改它們的顯示文本為“重新登錄”和“退出”。然后使用信號和槽模式將“退出”按鈕的clicked()信號和MyWidget 界面的**close()槽關聯。完成后再轉到“重新登錄”按鈕的clicked()**信號的槽,并更改如下:
void MyWidget::on_pushButton _clicked()
{//先關閉界面,其實是隱藏了,并沒有真正退出,然年新建MyDialog對象close();MyDialog dlg;//如果按下了[重新登錄]按鈕,則再次顯示主界面if(dlg.exec()==QDialog::Accepted)show();
}
運行后效果如下:
1744004593360