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:
#ifndef DIALOG_H
#define DIALOG_H#include <QtGui/QDialog>
#include <QPushButton>class Dialog : public QDialog
{Q_OBJECT
protected:QPushButton ModalBtn;QPushButton NormalBtn;QPushButton MixedBtn;
protected slots:void ModalBtn_Clicked();void NormalBtn_Clicked();void MixedBtn_Clicked();
public:Dialog(QWidget *parent = 0);~Dialog();
};#endif // 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();
};#endif
QLoginDialog.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();
};#endif
Widget.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();
};#endif
QLoginDialog.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();
};#endif
Widget.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实验分析教程
Qt中的QDialog相关推荐
- 【Qt】QMainWindow |QDialog对话框
文章目录 1.QMainWindow 1.1 菜单栏 1.2 工具栏 1.3 状态栏 1.4 停靠部件 1.5 核心部件(中心部件) 1.6 使用UI文件创建窗口 1.6.1 UI设计窗口介绍 1.6 ...
- QT中QWidget、QDialog及QMainWindow的区别
QWidget类是所有用户界面对象的基类. 窗口部件是用户界面的一个基本单元:它从窗口系统接收鼠标.键盘和其它事件,并且在屏幕上绘制自己.每一个窗口部件都是矩形的,并且它们按Z轴顺序排列.一个窗口部件 ...
- 【PyQt】Qt中QMainWindow, QWidget以及QDialog的区别和选择
PyQt中MainWindow, QWidget以及Dialog的区别和选择 1. Qt界面分类 在Qt Designer设计界面时,首先需要选择界面模板,主要分为三个类: 1. Main Windo ...
- 关于Qt中QDialog对话框调用exec()函数界面退出造成僵尸程序问题
关于Qt中QDialog对话框调用exec函数产生的问题 问题一: 问题描述: 原因分析: 解决方案: 问题二: 问题描述: 求助:关于这个问题,学识尚浅,求大佬分析一波 问题一: QDialog对话 ...
- Qt / QMainWindow、QDialog、QWidget
在 Qt 中,我们将窗口和控件统称为部件(Widget). 窗口是指程序的整体界面,可以包含标题栏.菜单栏.工具栏.关闭按钮.最小化按钮.最大化按钮等. 控件是指按钮.复选框.文本框.表格.进度条等这 ...
- QT中父子窗口事件传递与事件过滤器
处理监控系统的时候遇到问题,在MainWidget中创建多个子Widget的时候,原意是想鼠标点击先让MainWidget截获处理后再分派给子Widget去处理,但调试后发现如果子Widget重新实现 ...
- QT中的模态对话框及非模态对话框
模态对话框(Modal Dialog)与非模态对话框(Modeless Dialog)的概念不是Qt所独有的,在各种不同的平台下都存在.又有叫法是称为模式对话框,无模式对话框等.所谓模态对话框就是在其 ...
- Qt中的模态对话框和非模态对话框
模态对话框及非模态对话框(详情见课本P51). 模态对话框:在没有被关闭之前,用户不能与同一个应用程序的其他窗口进行交互,直到该对话框关闭. 非模态对话框:当被打开时,用户既可选择和该对话框进行交互, ...
- Qt的对话框与窗口--Qt中主要的窗体类及其用途
Qt中主要的窗体类及其用途 常用的窗体基类是QWidget.QDialog和QMainWindow,在创建GUI应用程序时选择窗体基类就是从这3个类中选择.QWidget直接继承于QObjec ...
最新文章
- python实用程序育儿法_Python多线程 简明例子
- linux挂载fc存储有超级坏块_Nand Flash基础知识与坏块管理机制的研究
- linux 文件颜色的含义
- Python学习---深浅拷贝的学习
- 深入了解AI在金融、能源领域的网络安全应用
- 【疾病识别】基于matlab GUI SVM农作物叶子虫害识别与分类【含Matlab源码 1322期】
- 企业多园区统一灾备建设最佳实践
- c语言敏感词屏蔽编程题,C#敏感词过滤实现方法
- [ssd]linux系统sh后,找不到文件夹的解决
- Android 查看是否支持指定解码器(H265)
- 结对作业-基于GUI的四则运算
- 3GPP TS 23501-g51 中英文对照 | 5.3.3 Connection Management
- Spring声明式事物配置管理
- 国外最大的购物搜索/比较购物网站
- SuperSet (真)完全汉化
- 未来生活里掌握计算机技术的重要性,浅谈计算机教育重要性的几点理解.doc
- Kademlia算法 理解 总结
- (转)在图像处理中,散度 div 具体的作用是什么?
- 区块链媒体宣发的注意事项
- 理解JPEG文件头的格式
热门文章
- linux 打开文件表 文件描述符,文件描述符-mjsc1023-ChinaUnix博客
- 搭建项目_跟着团子学SAP PS:项目模版搭建
- Ardino基础教程 14_倾斜开关
- 【system generator】基于system generator的整数除法器设计
- go 通过 channel 控制并发任务
- 03、Swagger2和Springmvc整合详细记录(爬坑记录)
- 【sublime text3】破解 最近破解码 /激活成功,但是过一会就提示激活码失效的 Build3143...
- bzoj2720 [Violet 5]列队春游
- 【288天】每日项目总结系列026(2017.11.20)
- 用html+ccs3就能 做出一个太阳系行星