第二章 创建对话框 (可变形对话框)

发布: 2008-05-29 22:17







可变形对话框


我们已经知道了如何创建总是显示相同的物件的对话框。某些情况下,需要创建可以变形的对话框。两种常用的可变形对话框是扩展对话框和多页对话框。这个两种对话框都可以在Qt中实现,不管是手写代码还是使用Qt Designer


可扩展对话框通常提供一个简单的外观,但是包含一个开关按钮允许用户在对话框简单外观和可扩展外观之间转换。可扩展对话框一般用在同时适用于普通用户和高级用户的应用中,默认隐藏高级选项功能,当用户明确指定的时候再显示出来。在本节中,我们要用 Qt 设计师来创建图 2.10 中的可扩展对话框。


Figure 2.10. The Sort dialog with simple and extended appearances

[View full size image]


 


 


这个对话框是一个spreadsheet应用程序中的排序对话框,在这个对话框中用户可以选择一列或多列进行排序。对话框的简单外观允许用户输入一个排序关键字,扩展外观提供了额外的两个排序关键字。一个附加的按钮允许用户在简单外观和扩展外观之间转换。


我们将用Qt Designer创建物件和它的扩展外观,并在运行时按需要隐藏第二和第三个关键字。物件看起来很复杂,但是在Qt Designer实现起来却是相当容易的。窍门就是先做主关键字部分,然后复制它两次来获取第二和第三关键字:




  1. 点击 File|New Form 并选择 "Dialog with Buttons Right" 模板。




  2. 创建 More button 并把它拖拽它到垂直布局,放在垂直空白占位符下面。设置 More 按钮的 text 属性为 "&More"checkable 属性为 "true",设置 OK 按钮的默认属性 "true"




  3. 创建一个分组框,两个标签,两个下拉列表框和一个水平占位符,并把它们放在窗体的任意位置。




  4. 拖拽分组框的右下角使它变大。然后将其他物件移动到分组框中,位置像2.11(a) 显示的那样。




Figure 2.11. Laying out the group box's children in a grid

[View full size image]


 




  1. 拖拽第二个下拉列表框的右边线使它大概为第一个下拉列表框宽度的两倍。




  2. 设置分组框的 title 属性为 "&Primary Key",第一个标签的 text 属性为 "Column:",第二个标签的 text 属性为 "Order:"




  3. 右键单击第一个分组框并下从上下文菜单中选择 Edit Items 弹出 Qt Designer的下拉列表编辑器。创建一个 text"None"项。




  4. 右键单击第二个分组框并下从上下文菜单中选择 Edit Items 弹出 Qt Designer的下拉列表编辑器。创建一个 "Ascending" 项和一个 "Descending" 项。




  5. 点击分组框,然后点击 Form|Lay Out in a Grid。再次点击分组框点击 Form|Adjust Size。这将生成一个如 2.11 (b)显示的布局。




如果一个布局不是很合适或者如果你犯了一个错误,你可以点击 Edit|Undo 或者 Form|Break Layout,然后重新布局物件再次尝试。


现在我们将添加第二和第三主键的分组框:




  1. 确保对话框窗口拥有足够高的高度来存放额外的部分。




  2. 按住 Ctrl (Alt on the Mac) 的同时点击 Primary Key 分组框创建分组框的一份拷贝(包括它的内容)。同时按住 Ctrl( 或者 Alt)键,拖动此拷贝到下面的分组框中。使用同样的方法创建出第三个分组框,并把它放在第二个下面。




  3. 重置它们的 title 属性为 "&Secondary Key" "&Tertiary Key".




  4. 创建一个垂直占位符并把它放置在第一关键字和第二关键字分组框之间。






  1. Arrange the widgets in the grid-like pattern shown in Figure 2.12 (a).




Figure 2.12. Laying out the form's children in a grid

[View full size image]


 




  1. 点击窗体取消对所有选择物件的选择,然后点击 Form|Lay Out in a Grid。窗体现在应该和 2.12 (b)一样。




  2. 设置两个垂直空白占位符元素的 sizeHint 属性为 [20, 0]




结果的网格布局有两列和四行,
8 个单元。 主键的分组框,最靠左的垂直空白占位符项,第二主键分组框,第三主键分组框每一个占据一个单元格。垂直布局包含OKCancelMore按钮占据两个单元格。在对话框的右下方留下两个空白单元格。如果你没有得到这个,取消布局,重新放置物件,然后重试。


重命名窗体 "SortDialog" 设置窗口的标题为 "Sort"。设置子物件的名字为 Figure 2.13 显示的那样:


Figure 2.13. Naming the form's widgets

[View full size image]


 


 


点击 Edit|Edit Tab Order。从上到下依次点击每个下拉列表框,然后点击右边的OKCancelMore按钮。单击Edit|Eeit Widgets 离开tab顺序模式。


现在我们已经创建了窗体,我们准备设置一些信号/槽连接使它可用。Qt Designer 允许我们在同一窗体的物件之间建立连接。我们需要创建两个连接。


单击 Edit|Edit Signals/Slots 进入 Qt Designer的连接模式。窗体物件之间的蓝色箭头代表了物件之间的连接。因为我们选择了 "Dialog with Buttons Right" 模板, OK Cancel 按钮已经连接到 QDialog's accept() reject() 槽上。连接也在 Qt Designer'signal/slot 编辑器窗口列出来了。


要在两个物件之间建立一个连接,点击 sender 物件并拖拽红色箭头线widget and drag the red arrow line to the receiver widget, 然后释放。这会弹出一个对话框允许你选择要建立连接信号和槽。


Figure 2.14. Connecting the form's widgets

 


 


第一个连接建立在More按钮和第二个分组框之间。拖拽红色箭头线在这两个物件之间,然后选择 toggled(bool) 作为信号 setVisible(bool) 作为槽。默认,Qt Designer 不在槽的列表中列出 setVisible(bool) ,但是如果你打开Show all signals and slots 选项它就会显示。


Figure 2.15. Qt Designer's connection editor

[View full size image]


 


 


第二个连接在More按钮的toggled(bool) 信号和 tertiaryGroupBoxsetVisible(bool) 槽之间建立。一旦连接建立点击 Edit|Edit Widgets 离开连接模式。


在一个目录名为sort中以 sortdialog.ui 保存对话框。向窗体添加代码,我们将使用在上一部分中Go-to-Cell对话框中用到的相同的多重继承的方式。


首先,创建一个 sortdialog.h 文件,内容如下:


#ifndef SORTDIALOG_H


#define SORTDIALOG_H


#include <QDialog>


#include "ui_sortdialog.h"


class SortDialog : public QDialog, public Ui::SortDialog


{


   Q_OBJECT


public:


   SortDialog(QWidget *parent = 0);


   void setColumnRange(QChar first, QChar last);


};


#endif


 


然后创建 sortdialog.cpp:


1 #include <QtGui>


2 #include "sortdialog.h"


3 SortDialog::SortDialog(QWidget *parent)


4 : QDialog(parent)


5 {


6 setupUi(this);


7 secondaryGroupBox->hide();


8 tertiaryGroupBox->hide();


9 layout()->setSizeConstraint(QLayout::SetFixedSize);


10 setColumnRange('A', 'Z');


11 }


12 void SortDialog::setColumnRange(QChar first, QChar last)


13 {


14 primaryColumnCombo->clear();


15 secondaryColumnCombo->clear();


16 tertiaryColumnCombo->clear();


17 secondaryColumnCombo->addItem(tr("None"));


18 tertiaryColumnCombo->addItem(tr("None"));


19 primaryColumnCombo->setMinimumSize(


20 secondaryColumnCombo->sizeHint());


21 QChar ch = first;


22 while (ch <= last) {


23 primaryColumnCombo->addItem(QString(ch));


24 secondaryColumnCombo->addItem(QString(ch));


25 tertiaryColumnCombo->addItem(QString(ch));


26 ch = ch.unicode() + 1;


27 }


28 }


 


构造函数隐藏对话框的第二和第三部分。它还设置窗体布局的 sizeConstraint 属性为 QLayout::SetFixedSize,使得对话框对用户不可改变大小。当子物件显示或隐藏时,布局将接管更改大小的回应,然后自动更改对话框的大小,确保对话框总是以合适的大小显示。


setColumnRange() 槽根据spreadsheet选择的列来初始化下拉列表的内容。我们在下拉列表中插入一个 "None" in the comboboxes for the (optional) secondary and tertiary keys.






19 20 暗示了一种微妙的布局思想。 QWidget::sizeHint() 函数返回一个物件的理想大小,这是布局系统所期望的。这就解释了为什么不同的物件或者包含不同内容的相似的物件可能被布局系统赋予不同的尺寸了。 对于下拉列表框,这意味着包含内容”None”的第二和第三下拉框会大于只包含一个字母的第一个下拉框。为了避免这种矛盾,我们把第一个下拉框的最小尺寸设置为第二个下拉框的理想尺寸了。



这里有一个 main() 测试函数设置包含了列'C' 'F' 范围然后显示对话框:


#include <QApplication>


#include "sortdialog.h"


int main(int argc, char *argv[])


{


QApplication app(argc, argv);


SortDialog *dialog = new SortDialog;


dialog->setColumnRange('C', 'F');


dialog->show();


return app.exec();


}


 


到这里我们就全部完成了可扩展对话框。就像例子中展示的那样,设计一个可扩展对话框并不比设计一个普通对话框困难多少:我们所需要做的就是一个开关按钮,一些额外的信号槽连接,和一个不可变的布局。在生产级应用程序,用按钮控制高级扩展内容的显示是很普通的一件事情 >>> 仅当基础对话框可见并且是高级模式时 <<< 仅当扩展显示时。这在Qt中可很容易的当点击QPushButton时调用setText()实现。


其他常用的可变形对话框,多页对话框用Qt创建甚至更简单,不管是手写代码还是使用Qt Designer。这些对话框可以使用很多不同的方法创建。




  • 一个 QTabWidget 可以自我控制,它在顶部提供了一个tab栏控制一个內建的 QStackedWidget 物件。




  • 一个 QListWidget 和一个 QStackedWidget 可以一起使用,通过连接 QListWidget::currentRowChanged() 信号到 QStackedWidget::setCurrentIndex() 槽上,用 QList-Widget 的当前项决定QStackedWidget 显示哪一页。




  • 一个 QtreeWidget 可以被可以像 QListWidget 一样和 QStackedWidget 一起使用




 QStackedWidget 类描述在 6 章 中(布局管理).


 



原文: http://qtchina.tk/?q=node/112

Powered by zexport