8. 对话框¶
GUI程序中少不了和用户简短交互,比如常见的“打开文件”功能,这些功能不适合放入主窗口,一般放在对话框中。 对话框通常会是一个顶层窗口,出现在程序最上层,主要用于短期任务和与用户的简短通信。
QDialog 类是对话框窗口的基类,也属于Qt控件的一种:
QDialogs分为模态对话框和非模态对话框:
模态对话框
模态对话框(又叫做模式对话框),是指在用户想要对对话框以外的应用程序进行操作时,必须首先对该对话框进行响应,如先要点击对话框的【确定】或【取消】按钮,之后才能操作其他。 模态对话框垄断了用户的输入,当一个模态对话框打开时,用户只能与该对话框进行交互,而其他用户界面对象收不到输入信息。
模态对话框的最常见方法是调用其exec()函数,当用户关闭对话框时,exec()将提供有用的返回值。另外,要获取返回适当的值,必须将一个默认按钮连接起来, 例如,将OK按钮连接到accept()槽函数,将Cancel按钮连接到reject()槽函数,或者调用done()槽函数。
另一种方法是调用setModal(true)或setWindowModality(),然后调用show(),与exec()不同,show()立即将控制权返回给调用者。 调用setModal(true)对于进度对话框特别有用,在该对话框中,用户必须具有与对话框进行交互的能力,例如取消长时间运行的操作。 如果同时使用show()和setModal(true)来执行较长的操作,则必须在处理期间定期调用QCoreApplication :: processEvents(),以使用户能够与对话框进行交互。
非模态对话框
非模态对话框(又叫做无模式对话框),与模态对话框不同,当用户打开非模态对话框时,依然可以操作其他窗口。
例如在文字处理器中查找和替换对话框通常是无模态的,以允许用户与应用程序的主窗口和对话框进行交互。
无模式对话框通常使用show()显示,该对话框立即将控制权返回给调用者。如果在隐藏对话框后调用show()函数,该对话框将以其原始位置显示。 这是因为窗口管理器决定了程序员未明确放置的窗口的位置。要保留用户已移动的对话框的位置,请将其位置保存在closeEvent()处理程序中,然后将对话框移至该位置,然后再次显示它。
接下来将介绍Qt中常用的对话框。
8.1. QFileDialog¶
QFileDialog类使用户可以遍历文件系统以选择一个或多个文件或目录。
下面分别是Ubuntu和Windows下面的打开文件对话框的效果。
创建QFileDialog的最简单方法是使用静态函数。
返回值 |
函数名 |
作用 |
参数 |
---|---|---|---|
QString |
getExistingDirectory |
返回用户选择的现有目录 |
(QWidget *parent = nullptr, const QString &caption = QString(), const QString &dir = QString(), QFileDialog::Options options = ShowDirsOnly) |
QUrl |
getExistingDirectoryUrl |
返回用户选择的现有目录URL |
(QWidget *parent = nullptr, const QString &caption = QString(), const QUrl &dir = QUrl(), QFileDialog::Options options = ShowDirsOnly, const QStringList &supportedSchemes = QStringList()) |
void |
getOpenFileContent |
返回用户选择的文件的内容 |
(const QString &nameFilter, const std::function<void (const QString &, const QByteArray &)> &fileOpenCompleted) |
QString |
getOpenFileName |
返回用户选择的现有文件 |
(QWidget *parent = nullptr, const QString &caption = QString(), const QString &dir = QString(), const QString &filter = QString(), QString *selectedFilter = nullptr, QFileDialog::Options options = Options()) |
QStringList |
getOpenFileNames |
返回用户选择的一个或多个现有文件 |
(QWidget *parent = nullptr, const QString &caption = QString(), const QString &dir = QString(), const QString &filter = QString(), QString *selectedFilter = nullptr, QFileDialog::Options options = Options()) |
QUrl |
getOpenFileUrl |
返回用户选择的现有文件URL |
(QWidget *parent = nullptr, const QString &caption = QString(), const QUrl &dir = QUrl(), const QString &filter = QString(), QString *selectedFilter = nullptr, QFileDialog::Options options = Options(), const QStringList &supportedSchemes = QStringList()) |
QList<QUrl> |
getOpenFileUrls |
返回用户选择的一个或多个现有文件URL |
(QWidget *parent = nullptr, const QString &caption = QString(), const QUrl &dir = QUrl(), const QString &filter = QString(), QString *selectedFilter = nullptr, QFileDialog::Options options = Options(), const QStringList &supportedSchemes = QStringList()) |
QString |
getSaveFileName |
返回用户选择的文件名,该文件不必存在 |
(QWidget *parent = nullptr, const QString &caption = QString(), const QString &dir = QString(), const QString &filter = QString(), QString *selectedFilter = nullptr, QFileDialog::Options options = Options()) |
QUrl |
getSaveFileUrl |
返回用户选择的文件URL,该文件不必存在 |
(QWidget *parent = nullptr, const QString &caption = QString(), const QUrl &dir = QUrl(), const QString &filter = QString(), QString *selectedFilter = nullptr, QFileDialog::Options options = Options(), const QStringList &supportedSchemes = QStringList()) |
void |
saveFileContent |
它将fileContent保存到文件中 |
(const QByteArray &fileContent, const QString &fileNameHint = QString()) |
在例程中,我们分别实现了,打开单个文件,打开多个文件,打开文件夹,将文本保存为文件。 通过调用QFileDialog的静态函数显示文件对话框与用户进行交互,让用户可以直观的选择文件、文件夹。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 | void MainWindow::on_btn_openFile_clicked()
{
QString curPath=QDir::currentPath();//获取应用程序的路径
QString dlgTitle="选择文件"; //对话框标题
QString filter="文本文件(*.txt);;图片文件(*.jpg *.gif *.png);;所有文件(*.*)"; //文件过滤器
QString fileName=QFileDialog::getOpenFileName(this,dlgTitle,curPath,filter);
if (fileName.isEmpty())
return;
QFile file(fileName);
if(!file.open(QIODevice::ReadOnly | QIODevice::Text))
{
ui->statusBar->showMessage("打开文件失败");
return;
}
ui->statusBar->showMessage("打开文件:"+fileName);
QTextStream in(&file);
ui->textEdit->clear();
ui->textEdit->setPlainText(in.readAll());
file.close();
}
void MainWindow::on_btn_openFiles_clicked()
{
QString curPath=QDir::currentPath();//获取应用程序的路径
QString dlgTitle="选择多个文件"; //对话框标题
QString filter="文本文件(*.txt);;图片文件(*.jpg *.gif *.png);;所有文件(*.*)"; //文件过滤器
QStringList filelist = QFileDialog::getOpenFileNames(this,dlgTitle,curPath,filter);
ui->textEdit->clear();
foreach(QString str,filelist)
ui->textEdit->append(str);
}
void MainWindow::on_btn_openDir_clicked()
{
QString curPath=QDir::currentPath();//获取应用程序的路径
QString dlgTitle="选择文件夹"; //对话框标题
QString dirname = QFileDialog::getExistingDirectory(this,dlgTitle,curPath);
if (dirname.isEmpty())
return;
QDir dir(dirname);
QList<QFileInfo> files=dir.entryInfoList();
ui->statusBar->showMessage("打开文件夹:"+dirname);
ui->textEdit->clear();
for(int i = 0;i<files.count(); i++)
{
ui->textEdit->append(files.at(i).filePath());
ui->textEdit->append(files.at(i).fileName());
}
}
void MainWindow::on_btn_save_clicked()
{
if(ui->textEdit->toPlainText().isEmpty())
{
ui->statusBar->showMessage("内容不能为空");
return;
}
QString curPath=QDir::currentPath();//获取应用程序的路径
QString filePath=curPath+"/"+QDateTime::currentDateTime().toString("yyyy-MM-dd-hh-mm-ss")+".txt";
qDebug()<<filePath;
QString dlgTitle="保存文件"; //对话框标题
QString filter="文本文件(*.txt);;图片文件(*.jpg *.gif *.png);;所有文件(*.*)"; //文件过滤器
QString fileName = QFileDialog::getSaveFileName(this, dlgTitle, filePath,filter);
if (fileName.isEmpty())
return ;
QFile file(fileName);
if (!file.open(QIODevice::WriteOnly)) {
ui->statusBar->showMessage("保存文件失败");
} else {
QTextStream stream(&file);
stream << ui->textEdit->toPlainText();
stream.flush();
file.close();
ui->statusBar->showMessage("保存文件:"+fileName);
}
}
|
QFileDialog的使用无外乎就是下面四个参数的设置:路径、对话框标题、文件过滤器、调用静态函数
路径是指,我们想要文件对话框打开时,默认选择的路径
标题指对用户的提示,比如本对话框的作用
文件过滤器,指显示对话框显示的时候,对当前默认路径目录下的文件进行过滤,比如只显示txt后缀的文本文件
最后就是调用静态函数显示对话框,获取相关文件路径等等
8.2. QFontDialog¶
QFontDialog类提供用于选择字体的对话框小部件。
返回值 |
函数名 |
作用 |
参数 |
---|---|---|---|
QFont |
getFont |
返回用户选择的字体 |
(bool *ok, const QFont &initial, QWidget *parent = nullptr, const QString &title = QString(), QFontDialog::FontDialogOptions options = FontDialogOptions()) |
QFont |
getFont |
返回用户选择的字体 |
1 2 3 4 5 6 7 8 9 10 11 12 13 | void MainWindow::on_btn_font_clicked()
{
bool choose;
QFont initfont=qApp->font();
QString dlgTitle="选择字体"; //对话框标题
QFont font=QFontDialog::getFont(&choose,initfont,this,dlgTitle); //选择字体
if(choose)
{
qApp->setFont(font);
ui->statusBar->showMessage("设置字体:"+font.toString());
}
}
|
例程中通过QFontDialog的静态函数getFont(),获取当前用户的选择的字体,并设置为当前app的字体。 其中,choose用于判断用户是直接关闭对话框,还是选择字体后窗口自行关闭的行为,简单点说用户是点击了取消还是确定。
8.3. QColorDialog¶
颜色对话框的功能是允许用户选择颜色。
返回值 |
函数名 |
作用 |
参数 |
---|---|---|---|
QColor |
customColor |
返回给定索引处的自定义颜色作为QColor值 |
(int index) |
int |
customCount |
返回QColorDialog支持的自定义颜色的数量 |
无 |
QColor |
getColor |
用户选择一种颜色并返回;如果用户取消则返回无效的颜色 |
(const QColor &initial = Qt::white, QWidget *parent = nullptr, const QString &title = QString(), QColorDialog::ColorDialogOptions options = ColorDialogOptions()) |
void |
setCustomColor |
设置在自定义颜色索引到的QColor 颜色值 |
(int index, QColor color) |
void |
setStandardColor |
设置标准色在指数到的QColor 颜色值 |
(int index, QColor color) |
QColor |
standardColor |
返回给定索引处的标准颜色作为QColor值 |
(int index) |
我们这里就仅仅使用getColor(),如果用户点击了确定,则会返回有效的颜色,我们将该颜色的设置成文本框中字体的颜色。
1 2 3 4 5 6 7 8 9 | void MainWindow::on_btn_color_clicked()
{
QColor color=QColorDialog::getColor(Qt::white,this,"选择颜色");
if(color.isValid())
{
qDebug()<<color;
ui->textEdit->setTextColor(color);
}
}
|
8.4. QMessageBox¶
QMessageBox类提供了一个模式对话框,用于通知用户或询问用户问题并接收答案。
消息框显示一个主要文本,以警告用户注意某种情况;一个信息性文本,用于进一步说明警报或询问用户问题; 以及可选的详细文本,以在用户请求时提供更多数据。消息框还可以显示一个图标和用于接受用户响应的标准按钮。
返回值 |
函数名 |
作用 |
参数 |
---|---|---|---|
void |
about |
显示带有标题标题和文本text的简单“关于”框 |
(QWidget *parent, const QString &title, const QString &text) |
void |
aboutQt |
显示一个有关Qt的简单消息框 |
(QWidget *parent, const QString &title = QString()) |
QMessageBox::StandardButton |
critical |
打开一个关键消息框 |
(QWidget *parent, const QString &title, const QString &text, QMessageBox::StandardButtons buttons = Ok, QMessageBox::StandardButton defaultButton = NoButton) |
QMessageBox::StandardButton |
information |
打开一个通知消息框 |
(QWidget *parent, const QString &title, const QString &text, QMessageBox::StandardButtons buttons = Ok, QMessageBox::StandardButton defaultButton = NoButton |
QMessageBox::StandardButton |
question |
打开一个询问消息框 |
(QWidget *parent, const QString &title, const QString &text, QMessageBox::StandardButtons buttons = StandardButtons(Yes | No), QMessageBox::StandardButton defaultButton = NoButton) |
QMessageBox::StandardButton |
warning |
打开一个警告消息框 |
(QWidget *parent, const QString &title, const QString &text, QMessageBox::StandardButtons buttons = Ok, QMessageBox::StandardButton defaultButton = NoButton) |
1 2 3 4 5 6 | void MainWindow::on_btn_critical_clicked()
{
QString dlgTitle="critical";
QString str="严重错误";
QMessageBox::critical(this, dlgTitle, str,QMessageBox::Ok);
}
|
1 2 3 4 5 6 | void MainWindow::on_btn_information_clicked()
{
QString dlgTitle="information";
QString str="提示消息";
QMessageBox::information(this, dlgTitle, str,QMessageBox::Yes);
}
|
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 | void MainWindow::on_btn_question_clicked()
{
QString dlgTitle="question";
QString str="询问消息";
int choose=QMessageBox::question(this, dlgTitle, str,QMessageBox::Yes,QMessageBox::No,QMessageBox::Cancel);
switch (choose) {
case QMessageBox::Yes:
ui->statusBar->showMessage("你选择了OK");
break;
case QMessageBox::No:
ui->statusBar->showMessage("你选择了NO");
break;
case QMessageBox::Cancel:
ui->statusBar->showMessage("你选择了Cancel");
break;
default:
ui->statusBar->showMessage("你关闭了对话框");
break;
}
}
|
1 2 3 4 5 6 | void MainWindow::on_btn_warning_clicked()
{
QString dlgTitle="warning";
QString str="警告消息";
QMessageBox::warning(this, dlgTitle, str,QMessageBox::Ok);
}
|
1 2 3 4 5 6 | void MainWindow::on_btn_about_clicked()
{
QString dlgTitle="about";
QString str="关于";
QMessageBox::about(this, dlgTitle, str);
}
|
1 2 3 4 5 | void MainWindow::on_btn_aboutQt_clicked()
{
QString dlgTitle="about Qt";
QMessageBox::aboutQt(this, dlgTitle);
}
|
8.5. QErrorMessage¶
QErrorMessage类提供了一个错误消息显示对话框。
1 2 3 4 5 6 | void MainWindow::on_btn_error_clicked()
{
QErrorMessage *errDlg = new QErrorMessage(this);
errDlg->setWindowTitle("QErrorMessage");
errDlg->showMessage("错误信息");
}
|
8.6. QInputDialog¶
QInputDialog类提供了一个简单的便捷对话框,可以从用户那里获取单个值。
返回值 |
函数名 |
作用 |
参数 |
---|---|---|---|
double |
getDouble |
从用户那里获取浮点数 |
(QWidget *parent, const QString &title, const QString &label, double value = 0, double min = -2147483647, double max = 2147483647, int decimals = 1, bool *ok = nullptr, Qt::WindowFlags flags = Qt::WindowFlags(), double step = 1) |
int |
getInt |
从用户那里获取整形 |
(QWidget *parent, const QString &title, const QString &label, int value = 0, int min = -2147483647, int max = 2147483647, int step = 1, bool *ok = nullptr, Qt::WindowFlags flags = Qt::WindowFlags()) |
QString |
getItem |
从用户那里获取选项 |
(QWidget *parent, const QString &title, const QString &label, const QStringList &items, int current = 0, bool editable = true, bool *ok = nullptr, Qt::WindowFlags flags = Qt::WindowFlags(), Qt::InputMethodHints inputMethodHints = Qt::ImhNone) |
QString |
getMultiLineText |
从用户那里获取多行文本 |
(QWidget *parent, const QString &title, const QString &label, const QString &text = QString(), bool *ok = nullptr, Qt::WindowFlags flags = Qt::WindowFlags(), Qt::InputMethodHints inputMethodHints = Qt::ImhNone) |
QString |
getText |
从用户那里获取文本 |
(QWidget *parent, const QString &title, const QString &label, QLineEdit::EchoMode mode = QLineEdit::Normal, const QString &text = QString(), bool *ok = nullptr, Qt::WindowFlags flags = Qt::WindowFlags(), Qt::InputMethodHints inputMethodHints = Qt::ImhNone) |
1 2 3 4 5 6 7 8 9 10 11 12 | void MainWindow::on_btn_getDouble_clicked()
{
QString dlgTitle="getDouble";
QString str="浮点数输入框";
int min=0, max=100,currValue=20.0,decimal=2;
bool choose=false;
double input = QInputDialog::getDouble(this, dlgTitle,str,currValue,min,max,decimal, &choose);
if (choose)
ui->statusBar->showMessage(QString::number(input));
}
|
1 2 3 4 5 6 7 8 9 10 11 12 | void MainWindow::on_btn_getInt_clicked()
{
QString dlgTitle="getInt";
QString str="整数输入框";
int min=0, max=100,step=1,currValue=20;
bool choose=false;
int input = QInputDialog::getInt(this, dlgTitle,str,currValue,min,max,step, &choose);
if (choose)
ui->statusBar->showMessage(QString::number(input));
}
|
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 | void MainWindow::on_btn_getItem_clicked()
{
QString dlgTitle="getItem";
QString str="Item输入框";
QStringList items;
items <<"0"<<"1"<<"2"<<"3"<<"4"<<"5";
int curIndex=0;//初始Item
bool editable=true; //ComboBox是否可编辑
bool choose=false;
QString input = QInputDialog::getItem(this, dlgTitle,str,items,curIndex,editable, &choose);
if (choose)
ui->statusBar->showMessage(input);
}
|
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 | void MainWindow::on_btn_getMultiLineText_clicked()
{
QString dlgTitle="getItem";
QString str="Item输入框";
QStringList items;
items <<"0"<<"1"<<"2"<<"3"<<"4"<<"5";
QString defaultstr="输入文本";
const QString defaulttext="输入文本";
bool choose=false;
QString input = QInputDialog::getMultiLineText(this, dlgTitle,str,defaultstr, &choose);
if (choose)
ui->statusBar->showMessage(input);
}
|
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 | void MainWindow::on_btn_getText_clicked()
{
QString dlgTitle="getText";
QString str="文本输入框";
QString defaultstr="输入文本";
QLineEdit::EchoMode echoMode=QLineEdit::Normal;
bool choose=false;
QString input = QInputDialog::getText(this, dlgTitle,str, echoMode,defaultstr, &choose);
if (choose)
{
if(input.isEmpty())
return;
ui->statusBar->showMessage(input);
}
}
|
8.7. QProgressDialog¶
QProgressDialog类提供有关缓慢操作进度的反馈
1 2 3 4 5 6 7 8 9 10 11 12 13 | void MainWindow::on_btn_progress_clicked()
{
QProgressDialog *progressDlg=new QProgressDialog(this);
progressDlg->setWindowModality(Qt::WindowModal);
progressDlg->setMinimumDuration(5);
progressDlg->setWindowTitle(tr("QProgressDialog"));
progressDlg->setLabelText(tr("进度条"));
progressDlg->setCancelButtonText(tr("取消"));
progressDlg->setRange(0,100);
progressDlg->setValue(59);
}
|
8.8. QPrintDialog¶
QPrintDialog类提供了一个用于指定打印机配置的对话框
1 2 3 4 5 6 | void MainWindow::on_btn_print_clicked()
{
QPrintDialog *print = new QPrintDialog(this);
print->exec();
}
|
8.9. 自定义对话框¶
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 | #ifndef QTMESSAGE233_H
#define QTMESSAGE233_H
#include "qtwidgetbase.h"
#include <QDialog>
#include <QFrame>
//MyFrame 为了实现圆角效果
class MyFrame : public QFrame {
Q_OBJECT
public:
explicit MyFrame(QWidget *parent = 0);
~MyFrame();
void setText(QString title,QString message,QString accept,QString reject);
signals:
private:
QString message;
QString message_title;
QString accept_text;
QString reject_text;
bool accept_hover;
bool reject_hover;
protected:
void paintEvent(QPaintEvent *);
void mouseMoveEvent(QMouseEvent *event);
};
#ifdef QtUi
#include <QtUi>
class QTUISHARED_EXPORT QtMessage : public QDialog {
#else
class QtMessage : public QDialog {
#endif
Q_OBJECT
public:
explicit QtMessage(QWidget *parent = 0);
//QtMessage(QWidget *parent = 0,QString title=tr("提示"),QString msg=tr("未知错误"),QString accept=tr("确认"),QString reject=tr("取消"));
~QtMessage();
void setMessage(QString Message);
signals:
private slots:
void acceptOperate();
void rejectOperate();
private:
MyFrame* frame;
protected:
void mousePressEvent( QMouseEvent * event );
void mouseReleaseEvent( QMouseEvent *);
void mouseMoveEvent(QMouseEvent *event);
};
#endif // QTMESSAGE_H
|
1 2 3 4 5 6 7 8 9 10 11 12 13 14 | void MainWindow::on_btn_logo_clicked()
{
QtMessage *msg=new QtMessage(this);
msg->setMessage(QString("自定义问对话框"));
if(msg->exec()==QDialog::Accepted)
{
qDebug()<<"你点击了确定按钮";
}
else
{
qDebug()<<"你点击了取消按钮";
}
delete msg;
}
|
8.10. 例程说明¶
示例中大多数通过调用静态函数,显示对话框。以QMessageBox为例:
1 2 3 | QString dlgTitle="information";
QString str="提示消息";
QMessageBox::information(this, dlgTitle, str,QMessageBox::Yes);
|
除了调用静态函数,还可以使用下面的方式,调用exec模态显示对话框:
1 2 3 4 5 | QMessageBox meg;
QString dlgTitle="information";
QString str="提示消息";
QMessageBox msg(QMessageBox::Information,dlgTitle, str,QMessageBox::Yes, NULL);
msg.exec();
|
8.10.1. 编译构建¶
Ubuntu 选择 Desktop Qt 5.15.2 GCC 64bit 套件,编译运行
LubanCat 选择 *LubanCat_RK,只编译生成可执行文件:
提示
当两种构建套件进行切换时,请重新构建项目或清除之前项目。如果是交叉编译远程部署参考下前面章节。
8.10.2. 运行结果¶
8.10.2.2. LubanCat板卡上实验¶
拷贝可执行程序到板卡,可以通过SCP、NFS、sftp、u盘等。 NFS使用 参考这里
SCP命令如下:
# scp传输文件,ip地址根据具体板子和PC,板子和PC在一个局域网下
# scp 文件名 服务器上的某个用户@服务器ip:/文件保存路径
scp filename server_user_name@192.168.103.102:server_file_path
# 从服务器拉取文件
# scp 服务器上的某个用户@服务器ip:/服务器文件存放路径 拉取文件保存路径
scp server_user_name@192.168.103.102:server_file_path local_path
编译好的程序在 lubancat_qt_tutorial_code/app_bin 目录中,通过scp命令将编译好的程序拉到LubanCat。
# 可执行程序文件的目录,根据自己实际项目设置的目录
scp root@192.168.103.102:~/lubancat_qt_tutorial_code/Dialog ~/home/cat/
在LubanCat板卡上运行程序,执行Dialog。
# 设置环境变量,然后执行程序
sudo ~/home/cat/Dialog