Dialog是一种常见的短周期任务和简介交互的top-level window。Dialog可以分为模式对话框和非模式对话框。Qt中的QDialog类提供了Dialog的原型,它可以有返回值和默认的按钮。每个窗体都有用户按下了enter键时默认的按钮。可以通过QPushButton::setDefault(), QPushButton::isDefault() and QPushButton::autoDefault()函数类设置控制窗体的默认按钮。如果用户按下了ESC按键,则默认会调用QDialog::reject()函数,最终将导致窗体关闭。为了定制窗体关闭动作,可以重写accept(), reject() or done()函数,closeEvent()函数只能用来恢复窗体位置和响应标准的close or reject操作。
模式对话框阻止同一应用程序中其他可见窗体的输入,用于向用户请求用户名的对话框通常是模式对话框。打开模式对话框后,用户必须完成和该对话框的交互并将其关闭,然后才能访问应用程序中的其他窗体。
最常用的显示Dialog的方法是调用它自己的exec()函数,当用户关闭dialog时,exec()将提供一个返回值。通常,为了得到适当的返回值,我们会设计一个按钮,比如OK按钮,连接accept()槽函数,Cancel按钮连接reject()函数。或者,你可以用done()槽函数实现接受还是拒绝。
另一种方法是通过调用setModal(true)或者setWindowModality(),然后调用show()。与exec()不同的是,show() 立即将控制权返回给用户。调用setModal(true)对于进度对话框特别的有用, 因为在进度对话框中,用户必须具有与对话框的交互能力,例如cancel一个厂的运行流程。如果用show() 和 setModal(true) 一起来实现一个长的操作,你必须调用 QApplication::processEvents() 以使得用户能够于对话框交互。
非模式对话框是可以在同一应用程序中相对于其他窗体独立进行操作的dialog.word中的查找和替换对话框就是一种非模式对话框,它可以同时和主窗口和对话框进行交互。非模式对话框同样用show()函数显示,并立刻返回控制权给用户。如果在隐藏对话框后调用show函数,对话框将显示在其原始位置。这是因为窗体管理器决定了未经开发者显式放置的窗口的位置。要恢复窗体的原始位置,需要在closeEvent()函数中保存位置,然后在show之前move窗体到保存的位置。
Qt提供了一些常用的标准对话框,如开发文件对话框、选择颜色对话框、信息提示和确认选择对话框、标准输入对话框等。用户无需再自己设计这些常用对话框。
QColorDialog |
Dialog widget for specifying colors |
QFileDialog |
Dialog that allow users to select files or directories |
QFontDialog |
Dialog widget for selecting a font |
QInputDialog |
Simple convenience dialog to get a single value from the user |
QMessageBox |
Modal dialog for informing the user or for asking the user a question and receiving an answer |
QProgressDialog |
Feedback on the progress of a slow operation |
color dialog提供颜色集可供用户选择。
static getColor() 函数将显示颜色窗体且允许用户选择某个颜色。用setCustomColor()函数存储不同的自定义颜色。用 customColor() 获取自定义颜色。
QFileDialog 就是常见的让用户选择文件或路径的对话框。最简单的调用方式是:
fileName = QFileDialog::getOpenFileName(this,
tr("Open Image"), "/home/jana", tr("Image Files (*.png *.jpg *.bmp)"));
上述调用方式将会创建一个模式对话框,对话框将展示"/home/jana"路径下的内容,且显示与"Image Files (*.png *.jpg *.bmp)"符合的文件。过滤器通常是下面的格式:
"Images (*.png *.xpm *.jpg);;Text files (*.txt);;XML files (*.xml)"
可以设置显示任何文件:
QFileDialog dialog(this);
dialog.setFileMode(QFileDialog::AnyFile);
设置过滤器:
dialog.setNameFilter(tr("Images (*.png *.xpm *.jpg)"));
QFontDialog
QFontDialog 为选择字体对话框。
bool ok;
QFont font = QFontDialog::getFont(
&ok, QFont("Helvetica [Cronyx]", 10), this);
if (ok) {
// the user clicked OK and font is set to the font the user selected
} else {
// the user canceled the dialog; font is set to the initial
// value, in this case Helvetica [Cronyx], 10
}
QInputDialog 提供一个简单的输入对话框。有单行字符串输入、整数输入、浮点数输入、列表框选择输入和多行文本等输入方式。
bool ok;
QString text = QInputDialog::getText(this, tr("QInputDialog::getText()"),
tr("User name:"), QLineEdit::Normal,
QDir::home().dirName(), &ok);
if (ok && !text.isEmpty())
textLabel->setText(text);
消息对话框用于显示提示、警告、错误等信息,或进行确认选择,由warning(),information(), critical(), about()和question()等几个静态函数实现。其中QMessageBox:: question()函数用于打开一个选择对话框,显示信息,并提供Yes,No,OK,Cancle等按钮。
最简单的应用是显示信息:
QMessageBox msgBox;
msgBox.setText("The document has been modified.");
msgBox.exec();
int ret = QMessageBox::warning(this, tr("My Application"),
tr("The document has been modified.\n"
"Do you want to save your changes?"),
QMessageBox::Save | QMessageBox::Discard
| QMessageBox::Cancel,
QMessageBox::Save);
也可以自己设计按钮:
QMessageBox msgBox;
QPushButton *connectButton = msgBox.addButton(tr("Connect"), QMessageBox::ActionRole);
QPushButton *abortButton = msgBox.addButton(QMessageBox::Abort);
msgBox.exec();
if (msgBox.clickedButton() == connectButton) {
// connect
} else if (msgBox.clickedButton() == abortButton) {
// abort
}
QProgressDialog 显示程序的运行进度。可以将QProgressDialog设计为模式对话框或是非模式对话框,模式对话框使用起来比较简单。
QProgressDialog progress("Copying files...", "Abort Copy", 0, numFiles, this);
progress.setWindowModality(Qt::WindowModal);
for (int i = 0; i < numFiles; i++) {
progress.setValue(i);
if (progress.wasCanceled())
break;
//... copy one file
}
progress.setValue(numFiles);
非模式的进度对话框比较适用于用户需要和应用交互且任务在后台运行的情况。典型的应用是基于QTimer (or QObject::timerEvent()),QSocketNotifier, 或者 QUrlOperator的任务,实际上MainWindow状态栏中的QProgressBar就是非模式的进度对话框。
// Operation constructor
Operation::Operation(QObject *parent)
: QObject(parent), steps(0)
{
pd = new QProgressDialog("Operation in progress.", "Cancel", 0, 100);
connect(pd, SIGNAL(canceled()), this, SLOT(cancel()));
t = new QTimer(this);
connect(t, SIGNAL(timeout()), this, SLOT(perform()));
t->start(0);
}
void Operation::perform()
{
pd->setValue(steps);
//... perform one percent of the operation
steps++;
if (steps > pd->maximum())
t->stop();
}
void Operation::cancel()
{
t->stop();
//... cleanup
}