目录
1、对话框及其类型
对话框的概念
对话框是与用户进行简短交互的顶层窗口, QDialog是Qt中所有对话框窗口的基类
QDialog继承于QWidget是一种容器类型的组件 ,QDialog是定制了窗口式样的特殊的QWidget
QDialog作为一种专用的交互窗口而存在 ,QDialog不能作为子部件嵌入其它容器中
QDialog和QWidget的区别
#include <QtGui/QApplication>
#include <QWidget>
#include <QDialog>
int main(int argc, char *argv[])
{
QApplication a(argc, argv);
QWidget widget;
QDialog dialog(&widget);
widget.setWindowTitle("i am widget");
widget.show();
dialog.setWindowTitle("i am dialog");
dialog.show();
return a.exec();
}
当两者交换顺序
QDialog dialog;
QWidget widget(&dialog);
对话框的类型
模态对话框(QDialog::exec())
-显示后无法与父窗口进行交互 ,是一种阻塞式的对话框调用方式
非模态对话框(QDialog::show())
-显示后独立存在可以同时与父窗口进行交互,是一种非阻塞式的对话框调用方式
一般情况下
-模态对话框用于必须依赖用户选择的场合 。例如: 消息提示,文件选择,打印设置,等
-非模态对话框用于特殊功能设置的场合。例如:查找操作,属性设置,等
- 在栈上创建模态对话框是最简单常用的方式,一般情况下非模态对话框需要在堆上创建
- 通过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"; // 运行这里后,仅仅dialog指针被销毁
}
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 "Dialog.h"
int main(int argc, char *argv[])
{
QApplication a(argc, argv);
Dialog dialog;
dialog.show();
return a.exec();
}
对话框的返回值
只有模态对话框才有返回值的概念,模态对话框的返回值用于表示交互结果
QDialog::exec()的返回值为交互结果
- void QDialog::done(int i):关闭对话框并将参数作为交互结果
- QDialog::Accepted:用户操作成功
- QDialog::Rejected:用户操作失败
Dialog.cpp(修改部分)
void Dialog::ModalBtn_Clicked()
{
done(Accepted);
qDebug() << "ModalBtn_Clicked() End";
}
void Dialog::NormalBtn_Clicked()
{
done(Rejected);
qDebug() << "NormalBtn_Clicked() End";
}
void Dialog::MixedBtn_Clicked()
{
done(100);
qDebug() << "MixedBtn_Clicked() End";
}
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 dialog;
int r = dialog.exec();
if(r == QDialog::Accepted)
{
qDebug() << "QDialog::Accepted";
}
else if(r == QDialog::Rejected)
{
qDebug() << "QDialog::Rejected";
}
else
{
qDebug() << r;
}
return r; // 没有必要重复进入消息循环
}
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"
#include <QDebug>
QLoginDialog::QLoginDialog(QWidget* parent) : QDialog(parent, Qt::WindowCloseButtonHint),
UserLabel(this), PwdLabel(this), UserEdit(this), PwdEdit(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);
CancelBtn.setText("Cancel");
CancelBtn.move(85, 110);
CancelBtn.resize(85, 30);
LoginBtn.setText("Login");
LoginBtn.move(180, 110);
LoginBtn.resize(85, 30);
setWindowTitle("Login");
setFixedSize(285, 170);
connect(&LoginBtn, SIGNAL(clicked()), this, SLOT(LoginBtn_Clicked()));
connect(&CancelBtn, SIGNAL(clicked()), this, SLOT(CancelBtn_Clicked()));
}
void QLoginDialog::LoginBtn_Clicked()
{
qDebug() << "LoginBtn_Clicked() Begin";
m_user = UserEdit.text().trimmed();
m_pwd = PwdEdit.text();
done(Accepted);
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;
}
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(400, 200);
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()
{
}
改进:增加随机验证码
验证码必须动态随机产生 ,验证码的显示避开使用标准组件(标签,文本框,等),将验证码直接绘制于登录对话框
验证码应该附带足够多的障碍增加程序识别难度 :验证码中的字符颜色随机改变 ,在验证码区域随机绘制噪点
注:计算机无法产生真正意义上的随机数 ,计算机只能模拟随机数序列(伪随机数) ,随机种子决定每次产生的随机序列是否相同
QPainter的使用:https://blog.csdn.net/qq_39654127/article/details/81876086
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; // 枚举类型,包含很多Qt预定义的QColor对象
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(); // 每100ms改变颜色
}
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); // 颜色范围2,17
}
return colors;
}
QLoginDialog::~QLoginDialog()
{
}