Part 02 对话框(Qt)

来源:互联网 发布:淘宝女装宣传视频 编辑:程序博客网 时间:2024/06/05 17:25

Part 02 对话框(Qt)

0. 本次学习Qt时主要方法:分析代码,从分析中学习语法,从分析中掌握Qt的程序设计思路。

1. 编写学习笔记主要形式:展示程序功能,从功能分析程序,总结程序设计思路,摘录(经修改)代码。

2. 主要参考学习书籍《零基础学Qt编程》(吴迪)和《C++ GUI Qt 4编程(第二版)》电子工业出版社。

3. 本Part内容:对话框,了解如何使用Qt设计模态、非模态和不同表现形态的对话框。

 

 

004 Program– ExtensionDlg

 

01.展示程序功能

           

          如图,本Dialog Box 可以输入名字,选择性别,还可以按下确定,按下Detail按钮(如下图)。

       

          按下“Detail”按钮后,在原Dialog Box的基础上扩展开来了,一般把这个按钮称为“toggle button”,可以让用户在对话框的简单外观和扩展外观之间来回切换。

 

02.从功能分析程序设计思路

          看见这程序,可以想到的问题有:

          第一,可以将这个窗口划分为多少个子窗口,

          第二,每个子窗口之间又是如何布局,

          第三,如何去完成Detail的功能。

 

          首先,我们可以使用一个类来完成这一整个功能,而这个类中,我们需要两个子窗口的数据成员。

          即,我们可以把这个窗口先划分为两个大的子窗口,根据点击”Detail”前后的窗口可以按下图来划分。

          这样划分以后,然后,我们就可以在编写类的时候,分别给这两个Widget创建一个初始化函数,而这个初始化函数需要完成的工作就是将每一个子窗口再写出来,我们再细入到每一个窗口中去,可以把这两个窗口按下图划分:

         

          待写好每一个Widget后,就可以开始给这些Widget布局了:

          

          按照这个先合并列,使其成为行,再将行合并,使其成为一个整体的思想去设计整个窗口的布局。

          最后,如果需要完成toggle button的功能,只需要加上一slots函数,让用户点击时触发这个函数即可。

 

 

03.从功能总结程序设计思路

 

           

 

04.程序代码

# 表示程序类型是appTEMPLATE = app# 指定可执行文件或库的基本文件名,其中不包含任何的扩展、前缀或版本号,默认的就是当前的目录名TARGET =DEPENDPATH += .# INCLUDEPATH 指定C++编译器搜索全局头文件的路径INCLUDEPATH += .# Input# HEADERS 指定工程的C++头文件(.h)多个文件可用空格或回车隔开HEADERS += \    extensionDlg.h# SOURCES 指定工程的C++实现文件(.cpp)多个文件可用空格或回车隔开SOURCES += \    main.cpp \    extensionDlg.cpp


 

// main.cpp#include <QApplication>#include "extensionDlg.h"int main(int argc, char * argv[]){    QApplication app(argc, argv);    ExtensionDlg exDlg;    exDlg.show();    return app.exec();}


 

// extensionDlg.h#ifndef EXTENSIONDLG_H#define EXTENSIONDLG_H#include <QtGui>                    // 引入QtGui模块的头文件class ExtensionDlg: public QDialog  // 声明自定义对话框类ExtensionDlg单公有继承自QDialog{    Q_OBJECT    // 加入Q_OBJECT宏,程序中用到诸如[信号/槽]等Qt核心机制的时候,都要加入这个宏    public:        ExtensionDlg();         // 构造函数        void initBasicInfo();   // 初始化基础信息        void initDetailInfo();  // 扩展信息    public slots:               // 声明公有槽类        void slot2Extension();  // 这个公有槽将在用户单击Detail按钮时触发    private:        QWidget * baseWidget;      // 伸缩前的对话框框体        QWidget * detailWidget;    // 伸缩后的对话框框体};#endif // EXTENSIONDLG_H


 

// extensionDlg.cpp#include "extensiondlg.h"// 构造函数ExtensionDlg::ExtensionDlg(){    setWindowTitle(tr("Extension Dialog")); // 设置应用程序的标题    initBasicInfo();                        // 初始化基本信息窗体    initDetailInfo();                       // 初始化扩展信息窗体    // 设置窗体的布局    QVBoxLayout * layout = new QVBoxLayout; // 定义一个垂直布局类实体layout    layout -> addWidget(baseWidget);        // 将baseWidge加入布局中    layout -> addWidget(detailWidget);    layout -> setSizeConstraint(QLayout::SetFixedSize);                                           // setSizeConstraint()设置窗体的缩放模式                                           // QLayout::SetDefaultConstraint 设定为默认值                                           // QLayout::SetFixedSize 固定的窗体大小,不可通过鼠标拖动改变                                           // 如果这里不这样设置,用户再次单击Detail将无法恢复原来大小    layout -> setSpacing(6);               // 设置位于布局之中的窗口部件之间的间隔大小    setLayout(layout);                     // 将设置好的布局应用加载到窗体上}// 初始化基础信息void ExtensionDlg::initBasicInfo(){    baseWidget = new QWidget;                        // 实例化私有数据成员 baseWidge    QLabel * nameLabel = new QLabel(tr("Name"));     // 新建一个“name”的标签, 用QLabel    QLineEdit * nameEdit = new QLineEdit;            // 新建的“name”的标签的后面加一行可输入行,用QLineEdit    QLabel * sexLabel = new QLabel (tr("Sex"));      // 新建一个"sex“的标签,用QLabel    QComboBox * sexComboBox = new QComboBox;         // 新建的"sex"后面加入一个下拉列表框,用QcomboBox    sexComboBox -> addItem(tr("male"));              // 为下拉列表框中加入选项    sexComboBox -> addItem(tr("female"));    QPushButton * okButton = new QPushButton(tr("OK"));             // 新建按钮窗口部件,名字为"OK"    QPushButton * detailButton = new QPushButton(tr("Detail"));     // 同上,名字为"Detail"    connect(detailButton, SIGNAL(clicked()), this, SLOT(slot2Extension()));                                    // 使用信号/槽机制连接detailButton的单击信号和this窗口类中的slot2Wxtension()函数    // 下面三个语句,使用QDialogButtonBox创建一个符合当前窗口部件样式的一组按钮,并且它们被排列在某种布局之中。    QDialogButtonBox * btnBox = new QDialogButtonBox(Qt::Horizontal);  // Qt::Horizontal 创建水平方向的按钮组合    btnBox -> addButton(okButton, QDialogButtonBox::ActionRole);       // addButton将按钮加入到这个组合中    btnBox -> addButton(detailButton, QDialogButtonBox::ActionRole);   // 并且ActionRole,创建的按钮有实际的功能    // 设置窗口的布局。窗体的顶级布局是一个垂直布局,而其中嵌套了一个表单布局。    QFormLayout * formLayout = new QFormLayout;     // 设置表单布局,使其可以整齐地分成两列的情况    formLayout -> addRow(nameLabel, nameEdit);      // addRow加入行,行里面包含了哪些变量(窗口部件)    formLayout -> addRow(sexLabel, sexComboBox);    QVBoxLayout * vboxLayout = new QVBoxLayout;     // 创建窗体的顶级布局,并将其两个元素formLayout和btnBox都加入其中    vboxLayout -> addLayout(formLayout);    vboxLayout -> addWidget(btnBox);    baseWidget -> setLayout(vboxLayout);            // 将设定好的布局都加载到窗体上    return;}// 初始化扩展信息void ExtensionDlg::initDetailInfo(){    detailWidget = new QWidget;                     // 实例化私有数据成员detailWidget    // 定义“age"一栏的两个Widget    QLabel * ageLabel = new QLabel(tr("Age"));    QLineEdit * ageEdit = new QLineEdit;    ageEdit -> setText(tr("25"));    QLabel * deptLabel = new QLabel(tr("Department"));    // 定义Department一栏的两个Widget    QComboBox * deptComboBox = new QComboBox;    deptComboBox -> addItem(tr("department 1"));    deptComboBox -> addItem(tr("department 2"));    deptComboBox -> addItem(tr("department 3"));    deptComboBox -> addItem(tr("department 4"));    // 定义address一栏的两个Widget    QLabel * addressLabel = new QLabel(tr("address"));    QLineEdit * addressEdit = new QLineEdit;    // 定义表单布局,并且将三行内容分别添加进去    QFormLayout * formLayout = new QFormLayout;    formLayout -> addRow(ageLabel, ageEdit);    formLayout -> addRow(deptLabel, deptComboBox);    formLayout -> addRow(addressLabel, addressEdit);    detailWidget -> setLayout(formLayout);    detailWidget -> hide();    return;}// 在用户单击Detail按钮时触发void ExtensionDlg::slot2Extension(){    // 通过一个if语句,可以控制它显示和隐藏两个动作    // 当时,也可以用 isShown()函数    if(detailWidget -> isHidden())    {        detailWidget -> show();    }    else    {        detailWidget -> hide();    }    return;}


 

005 Program – FindDialog

 

01. 展示程序功能

          如图,本FindDialog有六个子窗口,可以实现关键字查找,查找匹配,往后查找,关闭的功能。

         

          在未在Findwhat的EditLine输入字符时,”Find”Button不允许用户单击,输入字符后,情况则不同了。

         

          最后,这个对话框中,还有两个可选项,可以根据用户需求选择功能。

          

 

02. 从界面分析总结程序设计思路

          看见这程序,可以想到的问题有:

          第一,可以将这个窗口划分为多少个子窗口,

          第二,每个子窗口之间又是如何布局,

          第三,如何去完成LineEdit、2个CheckBox与FindButtonBox之间建立信号/槽机制。

 

          首先,这个程序与上一个程序的情况有点不同,因为它不需要实现切换的功能,不需要“ toggle Button”,所以,不用创建多个QWidget父类,来实现整个窗口的布局了,只需要创建QPushButton, QLabel, QCheckBox, QLineEdit这些子类就可以完成窗口布局了。如下图所示。

         

          然后,关于第三个问题,它们之间如何建立信号/槽机制。

         

 

03. 程序代码

#FindDialog.proHEADERS += \    finddialog.hSOURCES += \    finddialog.cpp \    main.cpp
// main.cpp#include <QApplication>#include "finddialog.h"int main(int argc, char * argv[]){    QApplication app(argc, argv);    finddialog * dialog = new finddialog;    dialog -> show();    return app.exec();}

// finddialog.h#ifndef FINDDIALOG_H#define FINDDIALOG_H#include <QDialog>      // 包含Qt对话框的基类class QCheckBox;class QLabel;class QLineEdit;class QPushButton;class finddialog: public QDialog{        Q_OBJECT     // 对于所有定义了信号和槽的类,在类定义开始处的Q_OBJECT宏都是必需的    public:        finddialog(QWidget * parent = 0); // parent参数指定父窗口对象,空指针则指明该对话框无父对象    signals:         // signals,用户消息事件,这关键字实际上也是一个宏,C++预处理器会在编译前转换成标准的C++代码。        void findNext(const QString &str, Qt::CaseSensitivity cs);        void findPrevious(const QString & str, Qt::CaseSensitivity cs);    private slots:  // slots,槽,这关键字也是一个宏,C++预处理器会在编译前转换成标准的C++代码。        void findClicked();        void enableFindButton(const QString & test);    private:        // 这里的私有数据成员,实际上就是按照对话框需要的Widget的顺序而定义的。        QLabel * label;        QLineEdit * lineEdit;        QCheckBox * caseCheckBox;        QCheckBox * backwardCheckBox;        QPushButton * findButton;        QPushButton * closeButton;};#endif // FINDDIALOG_H/* C++知识补充: * 这里使用了类的前置声明。 * 由于这些私有数据成员都是指针,也没有在头文件中就访问它们,所以编译程序就不需要这些类的完整定义。 * 这也是这里没有包含与这几个类相关的头文件的原因。 * 只是使用一些前置声明,这可以使编过程更加快些。 **/

// finddialog.cpp#include "finddialog.h"#include <QtGui>    // 包含了QDialog, QCheckBox, QLabel, QLineEdit, QPushButton// 构造函数finddialog::finddialog(QWidget * parent):QDialog(parent)    // 把parent参数传递给基类的构造函数{// 设置Widget    // 设置第一列第一行的两个Widget    label = new QLabel(tr("Find &what:"));  // 在字符串中的“&”可以表示快捷键    lineEdit = new QLineEdit;    label -> setBuddy(lineEdit);    // 设置标签伙伴(buddy),接收焦点(focus)                                    // 即,当按下label的快捷键后,焦点(focus)移动到LineEdit上.    // 设置第一列第二行的两个Widget    caseCheckBox = new QCheckBox(tr("Match & case"));    backwardCheckBox = new QCheckBox(tr("Search &backward"));    // 设置第二列的第一个 Widget--fidButton    findButton = new QPushButton(tr("&Find"));    findButton -> setDefault(true);         // 让findButton按钮成为默认按钮    findButton -> setEnabled(false);        // 禁用Find按钮,使其不能与用户进行交互操作    // 设置第二列的第二个 Widget -- closeButton    closeButton = new QPushButton(tr("Close")); // 设置槽    // 只要行编辑器中的文本发生变化,就会调用私有槽enableFindNutton(const QString&);    connect(lineEdit, SIGNAL(textChanged(const QString &)),            this, SLOT(enableFindButton(const QString &)));    // 单击Find按钮时,能实现其功能,调用findClicked()函数    connect(findButton, SIGNAL(clicked()), this, SLOT(findClicked()));    // 单击closeButton时,可以调用QWidget的close()函数,将对话框关闭    connect(closeButton, SIGNAL(clicked()), this, SLOT(close()));// 设置布局    // 设置最上面两个Widget为水平排列    QHBoxLayout * topLeftLayout = new QHBoxLayout;    topLeftLayout -> addWidget(label);    topLeftLayout -> addWidget(lineEdit);    // 设置左边的三行竖排列    QVBoxLayout * leftLayout = new QVBoxLayout;    leftLayout -> addLayout(topLeftLayout);    leftLayout -> addWidget(caseCheckBox);    leftLayout -> addWidget(backwardCheckBox);    // 设置右边的两个按钮竖排列    QVBoxLayout * rightLayout = new QVBoxLayout;    rightLayout -> addWidget(findButton);    rightLayout -> addWidget(closeButton);    // 使整个窗口水平排列    QHBoxLayout * mainLayout = new QHBoxLayout;    mainLayout -> addLayout(leftLayout);    mainLayout -> addLayout(rightLayout);// 设置该 dialog box的主要参数    setLayout(mainLayout);              // 设定布局    setWindowTitle(tr("Find"));         // 设置标题    setFixedHeight(sizeHint().height());// QWidget::sizeHint()返回一个窗口部件“理想”的尺寸大小}// 对话框中所用到的槽void finddialog::findClicked(){    QString text = lineEdit -> text();    Qt::CaseSensitivity cs = caseCheckBox -> isChecked() ? Qt::CaseSensitive                                                         : Qt::CaseInsensitive;    // backwardCheckBox功能启动时,则激发信号,向后找,否则,向前找    if(backwardCheckBox -> isChecked())    {        emit findPrevious(text, cs);    }    else    {        emit findNext(text, cs);    }    return;}// 判断是否允许开始查找的功能void finddialog::enableFindButton(const QString &text){    findButton -> setEnabled(!text.isEmpty());    return;}


 

 

006 Program – GoToCellDialog(QtDesigner)

 

01. 展示程序功能

     

      该对话框的WindowTitle为Go to Cell, 对话框内有正常的确认取消按钮,有一个QLabel一个LineEdit,当在LineEdit输入时,仅能按照"[A-Za-z][1-9][0-9]{0,2}"这样的格式输入。

 

 

02. 使用Qt Desinger设计程序的一般思路

        第一步:使用Qt Designer创建.ui文件:(设置窗口部件及窗口布局)

                     ① 创建并初始化子窗口部件

                     ② 把子窗口部件放到布局中

                     ③ 设置Tab键顺序

                     ④ 建立信号-槽之间的连接

                     ⑤ 实现对话框中的自定义槽

        第二步:创建.h头文件。(通过简单地增加另一个间接层,解决直接使用.ui的大多数问题)

        第三步:创建.cpp源文件。(包括main, 类)

        第四步:创建.pro工程文件。

 

03. 程序编写过程

        第一步:使用Qt Designer创建.ui文件:(设置窗口部件及窗口布局)

               ① 创建并初始化子窗口部件

               

               -> 创建

               

                 -> 设置属性

                 &&

                -> 设置属性,伙伴关系

              

 

                ② 把子窗口部件放到布局

                -> 弄好基本布局

                   

                -> 这是令窗口能自动调整大小的前提

                     

                -> 调整大小

                     

                -> 布局完成

                    

                ③ 设置Tab键顺序

                ④ 建立信号-槽之间的连接

                ⑤ 实现对话框中的自定义槽

 

第二步:创建.h头文件。(通过简单地增加另一个间接层,解决直接使用.ui的大多数问题)

// gotocelldialog.h#ifndef GOTOCELLDIALOG_H#define GOTOCELLDIALOG_H#include <QDialog>#include "ui_gotocelldialog.h"// uic工具会将gotocelldialog.ui文件转换为C++并且将转换结果存放在ui_gotocelldialog.h文件中。// 生成的ui_gotocelldialog.h文件中包含了类Ui::GoToCellDialog(用QtDesigner时定义的类名)的定义class GoToCellDialog:public QDialog, public Ui::GoToCellDialog{        Q_OBJECT         // 程序中用到诸如信号/槽等Qt核心机制的时候,都要加入这个宏。public:GoToCellDialog(QWidget * parent = 0);        private slots:   // 建立私有槽void on_lineEdit_textChanged();};#endif


 

第三步:创建.cpp源文件。(包括main, 类)

// gotocelldialog.cpp#include <QtGui>#include "gotocelldialog.h"// 构造函数GoToCellDialog::GoToCellDialog(QWidget * parent): QDialog(parent){        setupUi(this);          // 用于初始化窗体        QRegExp regExp("[A-Za-z][1-9][0-9]{0,2}"); // 检验器类,限制输入范围lineEdit -> setValidator(new QRegExpValidator(regExp, this));        // 注意,这里的okButton变量和cancelButton变量是从gotocelldialog.ui那里设置的。        connect(okButton, SIGNAL(clicked()), this, SLOT(accept()));     // 接受信号        connect(cancelButton, SIGNAL(clicked()), this, SLOT(reject())); // 取消信号}// 一个关于okButton的私有槽void GoToCellDialog::on_lineEdit_textChanged(){    // 当lineEdit有输入数据时,okButton的按钮变为可操作的。    // 注意,这里的okButton变量是从gotocelldialog.ui那里设置的。    okButton -> setEnabled(lineEdit -> hasAcceptableInput());}


 

// main.cpp#include <QApplication>#include <QDialog>#include "gotocelldialog.h"int main(int argc, char *argv[]){QApplication app(argc, argv);GoToCellDialog * dialog = new GoToCellDialog;dialog -> show();return app.exec();}


 

第四步:创建.pro工程文件。

# GoToCellDialog(QtDesigner).proHEADERS += \    gotocelldialog.hSOURCES += \    main.cpp \    gotocelldialog.cppFORMS += \    gotocelldialog.ui


 

007 Program – sortdialog(QtDesigner)

 

01. 展示程序功能

       

        这个对话框是一个用于电子制表软件应用程序的排序对话框(Sort对话框),在这个对话框中,用户可以选择一列或多列进行排序。More按钮允许用户在简单外观和扩展外观之间切换。

 

02. 使用Qt Desinger设计程序的一般思路

        第一步:使用Qt Designer创建.ui文件:(设置窗口部件及窗口布局)

                ① 创建并初始化子窗口部件

                ② 把子窗口部件放到布局中

                ③ 设置Tab键顺序

                ④ 建立信号-槽之间的连接

                ⑤ 实现对话框中的自定义槽

        第二步:创建.h头文件。(通过简单地增加另一个间接层,解决直接使用.ui的大多数问题)

        第三步:创建.cpp源文件。(包括main, 类)

        第四步:创建.pro工程文件。

 

03. 程序编写过程

        第一步:使用Qt Designer创建.ui文件:(设置窗口部件及窗口布局)

                       

                ① 创建并初始化子窗口部件

                -> 先创建出三个Group Box

                       

                -> 然后,创建子窗口部件

                       

                -> 这时,记得将MoreButton的属性设置为Checkable

                       

                ->然后,设置它们的伙伴关系

                       

                                    

               ② 把子窗口部件放到布局中

                       

                       

                ③ 设置Tab键顺序

                       

                ④ 建立信号-槽之间的连接

                       

                ⑤ 实现对话框中的自定义槽

 

        第二步:创建.h头文件。(通过简单地增加另一个间接层,解决直接使用.ui的大多数问题)

// sortdialog.h#ifndef SORTDIALOG_H#define SORTDIALOG_H#include <QDialog>#include "ui_sortdialog.h"class SortDialog: public QDialog, public Ui::SortDialog{        Q_OBJECTpublic:    SortDialog(QWidget * parent = 0);    void setColumnRange(QChar first, QChar last);};#endif // SORTDIALOG_H


     第三步:创建.cpp源文件。(包括main, 类)

// sortdialog.cpp#include "sortdialog.h"SortDialog::SortDialog(QWidget * parent):QDialog(parent){    setupUi(this);    groupBox_2 -> hide();    groupBox_3 -> hide();    layout() -> setSizeConstraint(QLayout::SetFixedSize); // 使用户不能再修改这个对话框窗体的大小    setColumnRange('A', 'Z');}// 根据电子制表软件,选择初始化组合框中的内容。void SortDialog::setColumnRange(QChar first, QChar last){    // 清空组合框中的内容    comboBox -> clear();    comboBox_3 -> clear();    comboBox_5 -> clear();    // 给组合框中添加None选项    comboBox_6 -> addItem(tr("None"));    comboBox_4 -> addItem(tr("None"));    comboBox_2 -> setMinimumSize(comboBox_3 -> sizeHint());    // 给组合框添加内容,使用一个循环语句    QChar ch = first;    while (ch <= last)    {        comboBox -> addItem(QString(ch));        comboBox_3 -> addItem(QString(ch));        comboBox_5 -> addItem(QString(ch));        ch = ch.unicode() + 1;    }    return;}


 

// main.cpp#include <QApplication>#include "sortdialog.h"int main(int argc, char * argv[]){    QApplication app(argc, argv);    SortDialog * dialog = new SortDialog;    dialog -> setColumnRange('A', 'G'); // 给ComboBox添加选项    dialog -> show();    return app.exec();}


 

        第四步:创建.pro工程文件。

# sortdialog(QtDesigner).proSOURCES += \    main.cpp \    sortdialog.cppHEADERS += \    sortdialog.hFORMS += \    sortdialog.ui


   第五步:最后小结

                        设计一个扩展对话框并不比设计一个简单对话框难,需要:

                         1. 一个切换按钮  2. 信号-槽连接 3. 一个不可改变大小的布局


 

0 0
原创粉丝点击