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. 一个不可改变大小的布局
- Part 02 对话框(Qt)
- Part 02 对话框(Qt)[2012.01.20]
- Part 04 各类对话框(Qt)[2012.02.11]
- Qt基础 02_Qt对话框(一)
- Qt入门(对话框)
- 3)~Qt~find对话框
- QT学习 之 对话框 (四) 字体对话框、消息对话框、文件对话框、进程对话框
- Qt对话框
- QT 对话框
- Qt 对话框
- Qt 对话框
- Qt-对话框
- qt对话框
- QT对话框
- QT对话框
- QT学习 之 对话框 (一) 可扩展对话框
- QT学习 之 对话框 (三) 标准颜色对话框
- Qt基础 04_Qt对话框(三) 标准对话框
- 二叉树输出
- HandBrake界面簡單說明
- JSP元素和标签
- java web 随笔
- STM32串行通讯采用中断方式发送,接收
- Part 02 对话框(Qt)
- jsp实现文件上传
- Linux代码性能检测利器(四)- 获取分析结果
- messages报logger: Waiting minutes for filesystem containing crsctl
- Java 观察者模式的浅析
- S3C2440系统时钟
- 初识jQuery
- 物体的加速运动(只受重力影响)
- HandBrakeCLI命令(google翻譯)