17.5 对话框
到现在为止,你都是通过继承QMainWindow来创建界面。对应用程序中的主窗口来说,使用QMainWindow是合适的,但对于生命期比较短的对话框来说,你应该使用QDialog构件。
当你想让用户为某一特定任务输入特定的信息时,或者你想向用户显示一些信息(如一条警告或错误信息)时,对话框是很有用的。通过继承QDialog来完成这些任务是一个好方法,因为你可以获取到一些便捷的方法来运行对话框,使用专门设计的信号和槽来处理用户响应。
除了通常的模式对话框和非模式对话框以外,Qt还提供了一种半模式对话框。下面我们来回顾一下模式对话框和非模式对话框的区别,同时也看看何为半模式对话框。
❑ 模式对话框:阻止所有其他窗口的输入,以强制用户响应当前对话框。它用于从用户那里获取即时的响应和显示严重的错误信息。
❑ 非模式对话框:非阻塞窗口,与应用程序中的其他窗口一起正常操作。它用于搜索或输入窗口,你可以在它和主窗口之间复制、粘贴数据。
❑ 半模式对话框:一个没有自己的事件循环的模式对话框。这样可以将控制权返回到应用程序,但仍阻塞对话框以外的所有窗口输入。它只在极少数情况下有用,比如当你有一个进度条表示某个耗时的关键操作的进度时,你可能想要给用户一个取消的机会。因为半模式对话框没有自己的事件循环,所以你必须定期调用QApplication∷processEvents来更新对话框。
17.5.1 QDialog
QDialog是Qt中的对话框基类,它提供了exec和show方法来处理模式与非模式对话框,集成了QLayout,并有几个用于响应按钮按下的信号和槽。
你通常将为对话框创建一个继承自QDialog的类,向其中增加构件来创建对话框界面:
与QMainWindow不同,你可以直接将QLayout对象的parent参数设置为MyDialog,而无需创建一个无用的QWidget,并将它作为QLayout的父构件。
注意,这个例子省略了用于创建ok_pushbutton和cancel_pushbutton构件的代码。
QDialog有两个槽:(accept和reject),它们用于表明对话框的结果。这个结果由exec方法返回。通常情况下,你将OK和Cancel按钮的信号连接到槽,就像在上面的MyDialog类中所做的那样。
1.模式对话框
要将对话框作为模式对话框,你需要调用exec。该函数弹出对话框,并根据被激活的槽返回QDialog∷Accepted或QDialog∷Rejected:
对话框在exec返回时会自动隐藏,但你仍然要从内存中删除它。
注意,在调用exec时,其他所有处理都被阻塞,所以当程序中有对时间要求比较高的代码时,使用非模式或半模式对话框更加合适一些。
2.非模式对话框
非模式对话框与普通主窗口没有多大区别,主要的不同是非模式对话框将它们自己定位在其父窗口之上,与父窗口共享任务栏,并在accept或reject槽被调用时自动隐藏。
要显示一个非模式对话框,与显示QMainWindow的方式相同,调用show方法即可:
show函数显示对话框,随后立即返回继续处理循环。为了处理按钮按下事件,你需要编写槽函数并连接槽:
与模式对话框一样,当一个按钮被按下时,对话框将自动隐藏。
3.半模式对话框
要创建半模式对话框,你必须在QDialog的构造函数中设置模式标志,并使用show方法:
QDialog (QWidget parent=0, const char name=0, bool modal=FALSE, WFlags f=0)
对于模式对话框,你没有将modal设置为TRUE的原因是:调用exec将强制对话框变为模式对话框,而不管这个标志是什么。
半模式对话框的构造函数如下所示:
一旦定义好一个对话框,你就可以调用show函数,然后继续运行程序,并定期调用QApplication∷ProcessEvents来更新对话框:
在继续处理之前,要保证对话框未被取消。注意,wasCancelled并不是QDialog的一部分,你必须自己提供它。
Qt还提供了现成的QDialog子类,它们专用于特定的任务,如文件选择、文本输入、进度条和消息框等。使用这些构件可以省去你许多麻烦。
17.5.2 QMessageBox
QMessageBox是一个模式对话框,它用于显示一段简单的消息,并伴有图标和按钮。图标的样式取决于消息的严重程度,它可以是常规信息、警告或其他的关键信息。
下面是QMessageBox类用于创建和显示这3类信息的静态方法:
QMessageBox预先提供了一系列的按钮,它们与上述静态方法的返回值相对应:
❑ QMessageBox∷Ok;
❑ QMessageBox∷Cancel;
❑ QMessageBox∷Yes;
❑ QMessageBox∷No;
❑ QMessageBox∷Abort;
❑ QMessageBox∷Retry;
❑ QMessageBox∷Ignore。
QMessageBox的一个典型使用方法如下所示:
你将按钮代码与Default和Escape做或(丨)运算,是为了设置键盘上的Enter键和Esc键被按下时的默认动作。最终的对话框如图17-8所示。
图 17-8
17.5.3 QInputDialog
QInputDialog用于输入单值数据,它可以是文本、一个下拉列表中的选项、一个整数或一个浮点数。QInputDialog类有与QMessageBox类似的静态方法,不过更复杂一点,因为它们有许多参数,但好在大多数参数都有默认值。
如果要输入一行文本,你可以这样编写代码:
QInputDialog由一个QLineEdit构件和OK、Cancel按钮组成,见图17-9。
图 17-9
由QInputDialog∷getText创建的对话框使用了一个QLineEdit构件。你传递给getText函数的编辑模式参数用于控制如何将文本回显给用户,这与QLineEdit构件中同一模式的作用完全相同。你还可以设置默认的文本或像上面那样将它设置为空。每个QInputDialog都有OK和Cancel按钮,它传递一个布尔值指针给该方法以表明哪个按钮被按下。如果用户按下OK按钮,那么result将为TRUE。
getItem通过QComboBox向用户提供一个选项列表:
生成的对话框见图17-10。
图 17-10
getInteger和getDouble的工作方式都类似,我们在这里就不展开讲了。
17.5.4 使用qmake简化makefile文件的编写
编译使用KDE库和Qt库的应用程序相当繁琐,因为你的makefile文件变得非常复杂,它需要使用moc,并且到处都要用到库。幸运的是,Qt自带了一个被称为qmake的工具,它可以帮助你创建makefile文件。
如果以前使用过Qt,你可能会对工具tmake比较熟悉,它是较早版本的Qt自带的一个早期的、类似qmake的工具(现在已不用)。
qmake以.pro文件作为输入。这个文件包含了编译所需的最基本信息,如源文件、头文件、目标二进制文件和KDE/Qt库的位置。
一个典型的KDE.pro文件如下所示:
你指定了目标二进制文件、临时的moc和目标目录、KDE库路径、要编译的源文件和头文件。注意,KDE头文件和库文件的目录取决于你所使用的Linux发行版。SUSE用户要把INCLUDEPATH设置为/opt/kde3/include,QMAKE_LIBDIR_X11设置为/opt/kde3/lib。
$ qmake file.pro -o Makefile
接下来,你就可以像通常一样运行make,就这么简单。对于任何复杂程度的KDE/Qt程序来说,你都应该使用qmake来简化编译过程。