QT对话框及其类型

目录

1、对话框及其类型

对话框的概念 

对话框的类型 

对话框的返回值 

2、登录对话框实例分析


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()
{

}

 

 

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值