Qt中的QDialog
生活随笔
收集整理的這篇文章主要介紹了
Qt中的QDialog
小編覺得挺不錯的,現在分享給大家,幫大家做個參考.
文章目錄
- 1 Qt中的QDialog
- 1.1 QDialog簡介
- 1.2 模態對話框和非模態對話框
- 1.3 對話框的返回值
- 2 登陸對話框實例分析
- 2.1 分析
- 2.2 代碼實現
- 2.3 登錄對話框的改進
- 3 Qt種的標準對話框
1 Qt中的QDialog
1.1 QDialog簡介
對話框的概念:
- 對話框是與用戶進行簡短交互的頂層窗口。
- QDialog是Qt中所有對話框窗口的基類。
- QDialog繼承于QWidget是一種容器類型的組件。
QDialog的意義: - QDialog作為一種專用的交互窗口而存在。
- QDialog不能作為子部件嵌入其它容器中。
- QDialog是定制了窗口樣式的特殊的QWidget。
注意:如果QDialog沒有指定parent是不會一直處于最上層的,如果制定了parent則會一直處于最上層。
1.2 模態對話框和非模態對話框
模態對話框(QDialog::exec()):
- 顯示后無法與父窗口進行交互。
- 是一種阻塞式的對話框調用方式。
非模態對話框(QDialog::show()):
- 顯示后獨立存在可以同時與父窗口進行交互。
- 是一種非阻塞式的對話框調用方式。
一般情況下:
- 模態對話框用于必須依賴用戶選擇的場合(80%):
- 消息提示、文件選擇、打印設置等。
- 非模態對話框用于特殊功能設置的場合(20%):
- 查找操作、屬性設置等。
小技巧:
- 在棧上創建模態對話框是最簡單常用的方式。
- 一般情況下非模態對話框需要在堆上創建。
- 通過QDialog::setModal函數可以創建混合特性的對話框(不會阻塞,但是必須做出選擇)。
- 非模態對話框需要指定Qt::WA_DeleteOnClose屬性。
測試代碼如下:
Dialog.h:
Dialog.cpp:
#include "Dialog.h"#include <QDebug>Dialog::Dialog(QWidget *parent) :QDialog(parent), ModalBtn(this), NormalBtn(this), MixedBtn(this) {ModalBtn.setText("Modal Dialog");ModalBtn.move(20, 20);ModalBtn.resize(100, 30);NormalBtn.setText("Normal Dialog");NormalBtn.move(20, 70);NormalBtn.resize(100, 30);MixedBtn.setText("Mixed Dialog");MixedBtn.move(20, 120);MixedBtn.resize(100, 30);connect(&ModalBtn, SIGNAL(clicked()), this, SLOT(ModalBtn_Clicked()));connect(&NormalBtn, SIGNAL(clicked()), this, SLOT(NormalBtn_Clicked()));connect(&MixedBtn, SIGNAL(clicked()), this, SLOT(MixedBtn_Clicked()));resize(140, 170); }void Dialog::ModalBtn_Clicked() {qDebug() << "ModalBtn_Clicked() Begin";QDialog dialog(this);dialog.exec();qDebug() << "ModalBtn_Clicked() End"; }void Dialog::NormalBtn_Clicked() {qDebug() << "NormalBtn_Clicked() Begin";QDialog* dialog = new QDialog(this);dialog->setAttribute(Qt::WA_DeleteOnClose);dialog->show();qDebug() << "NormalBtn_Clicked() End"; }void Dialog::MixedBtn_Clicked() {qDebug() << "MixedBtn_Clicked() Begin";QDialog* dialog = new QDialog(this);dialog->setAttribute(Qt::WA_DeleteOnClose);dialog->setModal(true);dialog->show();qDebug() << "MixedBtn_Clicked() End"; }Dialog::~Dialog() {qDebug() << "~Dialog()"; }main.cpp:
#include <QtGui/QApplication> #include <QWidget> #include <QDialog> #include <QDebug> #include "Dialog.h"int main(int argc, char *argv[]) {QApplication a(argc, argv);Dialog dlg;dlg.show();return a.exec(); }1.3 對話框的返回值
只有模態對話框才有返回值的概念:
- 模態對話框的返回值用于表示交互結果。
- QDialog::exec()的返回值為交互結果:
- void QDialog::done(int i)關閉對話框并將參數作為交互結果。
- QDialog::Accepted:用戶操作成功。
- QDialog:Rejected:用戶操作失敗。
測試代碼如下:
QDialog.h的代碼和上面一樣,就不貼了。
QDialog.cpp:
#include "Dialog.h"#include <QDebug>Dialog::Dialog(QWidget *parent) :QDialog(parent), ModalBtn(this), NormalBtn(this), MixedBtn(this) {ModalBtn.setText("Modal Dialog");ModalBtn.move(20, 20);ModalBtn.resize(100, 30);NormalBtn.setText("Normal Dialog");NormalBtn.move(20, 70);NormalBtn.resize(100, 30);MixedBtn.setText("Mixed Dialog");MixedBtn.move(20, 120);MixedBtn.resize(100, 30);connect(&ModalBtn, SIGNAL(clicked()), this, SLOT(ModalBtn_Clicked()));connect(&NormalBtn, SIGNAL(clicked()), this, SLOT(NormalBtn_Clicked()));connect(&MixedBtn, SIGNAL(clicked()), this, SLOT(MixedBtn_Clicked()));resize(140, 170); }void Dialog::ModalBtn_Clicked() {done(Accepted); }void Dialog::NormalBtn_Clicked() {done(Rejected); }void Dialog::MixedBtn_Clicked() {done(100); }Dialog::~Dialog() {qDebug() << "~Dialog()"; }main.cpp:
#include <QtGui/QApplication> #include <QWidget> #include <QDialog> #include <QDebug> #include "Dialog.h"int main(int argc, char *argv[]) {QApplication a(argc, argv);Dialog dlg;int r = dlg.exec();if( r == QDialog::Accepted ){qDebug() << "Accepted";}else if( r == QDialog::Rejected ){qDebug() << "Rejected";}else{qDebug() << r;}return r; }2 登陸對話框實例分析
2.1 分析
登陸對話框是應用程序中的常用部件,思考:如何開發一個可以在不同項目間復用的登陸對話框?
登陸對話框需求分析:
- 可復用軟件部分。
- 獲取用戶名和密碼。
附加需求:
- 隨機驗證碼。
登陸對話框的設計與架構:
如何獲取用戶輸入的用戶名和密碼:
- 如何在兩個不同的對話框之間傳遞數據?
對話框之間通過成員變量和成員函數傳遞數據:
- 將用戶數據保存在私有成員變量中。
- 通過公有成員函數進行數據傳遞。
我們話可以進一步開發(這里未完成):
- 檢查用戶名和密碼是否為空:
- 當用戶名或密碼為空時提示錯誤。
- 隨機驗證碼:
- 當驗證碼輸入錯誤時進行提示。
- 驗證碼隨機刷新。
2.2 代碼實現
代碼組織如下:
QLoginDialog.h:
#ifndef _QLOGINDIALOG_H_ #define _QLOGINDIALOG_H_#include <QtGui/QDialog> #include <QLabel> #include <QLineEdit> #include <QPushButton>class QLoginDialog : public QDialog {Q_OBJECT private:QLabel UserLabel;QLabel PwdLabel;QLineEdit UserEdit;QLineEdit PwdEdit;QPushButton LoginBtn;QPushButton CancelBtn;QString m_user;QString m_pwd; private slots:void LoginBtn_Clicked();void CancelBtn_Clicked(); public:QLoginDialog(QWidget *parent = 0);QString getUser();QString getPwd();~QLoginDialog(); };#endifQLoginDialog.cpp:
#include "QLoginDialog.h"QLoginDialog::QLoginDialog(QWidget *parent): QDialog(parent, Qt::WindowCloseButtonHint), m_lblName(this), m_lblPwd(this), m_editName(this), m_editPwd(this),m_btnCancle(this), m_btnLogin(this) {setWindowTitle("Login");setFixedSize(285, 170);m_lblName.setText("User ID:");m_lblName.resize(80, 25);m_lblName.move(10, 30);m_lblPwd.setText("Password:");m_lblPwd.resize(80, 25);m_lblPwd.move(10, 65);m_editName.move(95, 30);m_editName.resize(180, 25);m_editPwd.move(95, 65);m_editPwd.resize(180, 25);m_editPwd.setEchoMode(QLineEdit::Password);m_btnCancle.setText("Cancle");m_btnCancle.resize(85, 30);m_btnCancle.move(95, 110);m_btnLogin.setText("Login");m_btnLogin.resize(85, 30);m_btnLogin.move(190, 110);connect(&m_btnCancle, SIGNAL(clicked()), this, SLOT(onBtnCancleClicked()));connect(&m_btnLogin, SIGNAL(clicked()), this, SLOT(onBtnLoginClicked())); }void QLoginDialog::onBtnCancleClicked() {m_name = "";m_pwd = "";done(Rejected); }void QLoginDialog::onBtnLoginClicked() {m_name = m_editName.text().trimmed();m_pwd = m_editPwd.text();done(Accepted); }QString QLoginDialog::getName() {return m_name; }QString QLoginDialog::getPwd() {return m_pwd; }QLoginDialog::~QLoginDialog() {}Widget.h:
#ifndef _WIDGET_H_ #define _WIDGET_H_#include <QtGui/QWidget> #include <QPushButton>class Widget : public QWidget {Q_OBJECT private:QPushButton TestBtn; private slots:void TestBtn_Clicked(); public:Widget(QWidget *parent = 0);~Widget(); };#endifWidget.cpp:
#include "Widget.h" #include "QLoginDialog.h" #include "QDebug"Widget::Widget(QWidget *parent) :QWidget(parent), m_btnTestLoginDialog(this) {m_btnTestLoginDialog.setText("Test login dialog");setFixedSize(300, 200);connect(&m_btnTestLoginDialog, SIGNAL(clicked()), this, SLOT(onBtnTest())); }void Widget::onBtnTest() {QLoginDialog loginDlg(this);if (loginDlg.exec() == QDialog::Accepted){qDebug() << loginDlg.getName();qDebug() << loginDlg.getPwd();} }main.cpp:
#include <QtGui/QApplication> #include "QLoginDialog.h" #include "Widget.h"int main(int argc, char *argv[]) {QApplication a(argc, argv);Widget w;w.show();return a.exec(); }2.3 登錄對話框的改進
分析下如上對話框存在的問題:
- 沒有實現驗證碼功能,容易被惡意程序攻擊,盜取用戶名和密碼。
改進思路-驗證碼機制:
需求:
- 驗證碼必須能夠有效避開惡意程序的識別!
關于驗證碼和惡意程序:
- 自動測試原理:
- 利用一些特殊的系統函數能夠通過代碼控制程序,從而模擬用戶操作。
- 惡意程序:
- 使用自動測試原理對目標程序進行控制,從而盜取信息或進行攻擊。
- 驗證碼:
- 隨機產生,用戶容易識別,程序難以識別,從而有效避免惡意攻擊。
需要注意的問題:
- 驗證碼必須動態隨機產生。
- 驗證碼的顯示避開使用標準組件(標簽、文本框等)。
- 驗證碼應該附帶足夠多的障礙增加程序識別難度。
解決方案:
關于隨機數:
- 計算機無法產生真正意義上的隨機數。
- 計算機只能模擬隨機數序列(偽隨機數)。
- 隨機種子決定每次產生的隨機序列是否相同。
隨機產生驗證碼:
驗證碼繪制:
改進后的代碼如下:
QLoginDialog.h:
#ifndef _QLOGINDIALOG_H_ #define _QLOGINDIALOG_H_#include <QtGui/QDialog> #include <QLabel> #include <QLineEdit> #include <QPushButton> #include <QTimer>class QLoginDialog : public QDialog {Q_OBJECT private:QLabel UserLabel;QLabel PwdLabel;QLabel CaptLabel;QLineEdit UserEdit;QLineEdit PwdEdit;QLineEdit CaptEdit;QPushButton LoginBtn;QPushButton CancelBtn;QString m_user;QString m_pwd;QString m_captcha;Qt::GlobalColor* m_colors;QTimer m_timer; private slots:void LoginBtn_Clicked();void CancelBtn_Clicked();void Timer_Timeout(); protected:void paintEvent(QPaintEvent *);QString getCaptcha();Qt::GlobalColor* getColors(); public:QLoginDialog(QWidget *parent = 0);QString getUser();QString getPwd();~QLoginDialog(); };#endifQLoginDialog.cpp:
#include "QLoginDialog.h" #include <QPainter> #include <QTime> #include <QDebug> #include <QMessageBox>QLoginDialog::QLoginDialog(QWidget* parent) : QDialog(parent, Qt::WindowCloseButtonHint),UserLabel(this), PwdLabel(this), CaptLabel(this),UserEdit(this), PwdEdit(this), CaptEdit(this),LoginBtn(this), CancelBtn(this) {UserLabel.setText("User ID:");UserLabel.move(20, 30);UserLabel.resize(60, 25);UserEdit.move(85, 30);UserEdit.resize(180, 25);PwdLabel.setText("Password:");PwdLabel.move(20, 65);PwdLabel.resize(60,25);PwdEdit.move(85, 65);PwdEdit.resize(180, 25);PwdEdit.setEchoMode(QLineEdit::Password);CaptLabel.setText("Captcha:");CaptLabel.move(20, 100);CaptLabel.resize(60, 25);CaptEdit.move(85, 100);CaptEdit.resize(85, 25);CancelBtn.setText("Cancel");CancelBtn.move(85, 145);CancelBtn.resize(85, 30);LoginBtn.setText("Login");LoginBtn.move(180, 145);LoginBtn.resize(85, 30);m_timer.setParent(this);setWindowTitle("Login");setFixedSize(285, 205);connect(&m_timer, SIGNAL(timeout()), this, SLOT(Timer_Timeout()));connect(&LoginBtn, SIGNAL(clicked()), this, SLOT(LoginBtn_Clicked()));connect(&CancelBtn, SIGNAL(clicked()), this, SLOT(CancelBtn_Clicked()));qsrand(QTime::currentTime().second() * 1000 + QTime::currentTime().msec());m_captcha = getCaptcha();m_colors = getColors();m_timer.start(100); }void QLoginDialog::LoginBtn_Clicked() {qDebug() << "LoginBtn_Clicked() Begin";QString captcha = CaptEdit.text().replace(" ", "");if( m_captcha.toLower() == captcha.toLower() ){m_user = UserEdit.text().trimmed();m_pwd = PwdEdit.text();if( m_user == "" ){QMessageBox::information(this, "Info", "User ID can NOT be empty!");}else if( m_pwd == "" ){QMessageBox::information(this, "Info", "Password can NOT be empty!");}else{done(Accepted);}}else{QMessageBox::critical(this, "Error", "The captcha is NOT matched!");m_captcha = getCaptcha();CaptEdit.selectAll();}qDebug() << "LoginBtn_Clicked() End"; }void QLoginDialog::CancelBtn_Clicked() {qDebug() << "CancelBtn_Clicked() Begin";done(Rejected);qDebug() << "CancelBtn_Clicked() End"; }QString QLoginDialog::getUser() {return m_user; }QString QLoginDialog::getPwd() {return m_pwd; }void QLoginDialog::Timer_Timeout() {m_colors = getColors();update(); }void QLoginDialog::paintEvent(QPaintEvent *) {QPainter painter(this);painter.fillRect(180, 100, 84, 24, Qt::white);painter.setFont(QFont("Comic Sans MS", 12));for(int i=0; i<150; i++){painter.setPen(m_colors[i%4]);painter.drawPoint(180 + qrand() % 84, 100 + qrand() % 24);}for(int i=0; i<4; i++){painter.setPen(m_colors[i]);painter.drawText(180 + 20 * i, 100, 20, 24, Qt::AlignCenter, QString(m_captcha[i]));} }QString QLoginDialog::getCaptcha() {QString ret = "";for(int i=0; i<4; i++){int c = (qrand() % 2) ? 'a' : 'A';ret += static_cast<QChar>(c + qrand() % 26);}return ret; }Qt::GlobalColor* QLoginDialog::getColors() {static Qt::GlobalColor colors[4];for(int i=0; i<4; i++){colors[i] = static_cast<Qt::GlobalColor>(2 + qrand() % 16);}return colors; }QLoginDialog::~QLoginDialog() {}Widget.h:
#ifndef _WIDGET_H_ #define _WIDGET_H_#include <QtGui/QWidget> #include <QPushButton>class Widget : public QWidget {Q_OBJECT private:QPushButton TestBtn; private slots:void TestBtn_Clicked(); public:Widget(QWidget *parent = 0);~Widget(); };#endifWidget.cpp:
#include "Widget.h" #include "QLoginDialog.h"#include <QDebug>Widget::Widget(QWidget *parent) : QWidget(parent), TestBtn(this) {TestBtn.setText("Test Login Dialog");setFixedSize(200, 50);connect(&TestBtn, SIGNAL(clicked()), this, SLOT(TestBtn_Clicked())); }void Widget::TestBtn_Clicked() {QLoginDialog dlg;if( dlg.exec() == QDialog::Accepted ){qDebug() << "User: " + dlg.getUser();qDebug() << "Pwd: " + dlg.getPwd();} }Widget::~Widget() {}main.cpp:
#include <QtGui/QApplication> #include "widget.h"int main(int argc, char *argv[]) {QApplication a(argc, argv);Widget w;w.show();return a.exec(); }3 Qt種的標準對話框
標準對話框:
- Qt為開發者提供了一些可復用的對話框類型。
- Qt提供的可復用對話框全部繼承自QDialog類。
Qt中的標準對話框遵循相同的使用方式:
參考資料:
總結
以上是生活随笔為你收集整理的Qt中的QDialog的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 房东帮忙办理的居住证本人能用吗?
- 下一篇: C++中流的基本概念