QT<五> 对话框

一、对话框

1、基本概念

对话框通常会是一个顶层窗口,出现在程序最上层,用于实现短期任务或者简洁的用户交互。

Qt 中使用QDialog类实现对话框。就像主窗口一样,我们通常会设计一个类继承QDialog。QDialog(及其子类,以及所有Qt::Dialog类型的类)的对于其 parent 指针都有额外的解释:如果 parent 为 NULL,则该对话框会作为一个顶层窗口,否则则作为其父组件的子对话框(此时,其默认出现的位置是 parent 的中心)。 顶层窗口与非顶层窗口的区别在于,顶层窗口在任务栏会有自己的位置,而非顶层窗口则会共享其父组件的位置。

对话框分为模态对话框非模态对话框

  • 模态对话框:就是会阻塞同一应用程序中其它窗口的输入。不关闭当前窗口无法对其他窗口进行操作。
  • 非模态对话框:打开之后还可以对其他窗口进行操作。

2、标准对话框

所谓标准对话框,是 Qt 内置的一系列对话框,用于简化开发。事实上,有很多对话框都是通用的,比如打开文件、设置颜色、打印设置等。这些对话框在所有程序中几乎相同,因此没有必要在每一个程序中都自己实现这么一个对话框。

Qt 的内置对话框大致分为以下几类:

  • QColorDialog: 选择颜色;
  • QFileDialog: 选择文件或者目录;
  • QFontDialog: 选择字体;
  • QInputDialog: 允许用户输入一个值,并将其值返回;
  • QMessageBox: 模态对话框,用于显示信息、询问问题等;
  • QPageSetupDialog: 为打印机提供纸张相关的选项;
  • QPrintDialog: 打印机配置;
  • QPrintPreviewDialog:打印预览;
  • QProgressDialog: 显示操作过程。

1)消息对话框QMessageBox示例
QMessageBox用于显示消息提示。我们一般会使用其提供的几个 static 函数:

  • 显示关于对话框。
    这是一个最简单的对话框,其标题是 title,内容是 text,父窗口是 parent。对话框只有一个 OK 按钮。
void about(QWidget * parent, const QString & title, const QString & text)
  • 显示关于 Qt 对话框。该对话框用于显示有关 Qt 的信息。
void aboutQt(QWidget * parent, const QString & title = QString())
  • 显示严重错误对话框。
    这个对话框将显示一个红色的错误符号。我们可以通过 buttons 参数指明其显示的按钮。默认情况下只有一个 Ok 按钮,我们可以使用StandardButtons类型指定多种按钮。
QMessageBox::StandardButton critical(QWidget *parent, const QString &title, const QString &text, QMessageBox::StandardButtons buttons, QMessageBox::StandardButton defaultButton = NoButton)

int critical(QWidget *parent, const QString &title, const QString &text, QMessageBox::StandardButton button0, QMessageBox::StandardButton button1)


//错误对话框示例
   QMessageBox::critical(this,"critical","错误");
  • 显示普通信息对话框。
    这个对话框提供一个普通信息图标。
QMessageBox::StandardButton information(QWidget *parent, const QString &title, const QString &text, QMessageBox::StandardButtons buttons, QMessageBox::StandardButton defaultButton = NoButton)
QMessageBox::StandardButton information(QWidget *parent, const QString &title, const QString &text, QMessageBox::StandardButton button0, QMessageBox::StandardButton button1 = NoButton)

//信息对话框示例
   QMessageBox::information(this,"info","信息");

  • 显示提问对话框。
    这个对话框提供一个问号图标,并且其显示的按钮是“是”和“否”。
QMessageBox::StandardButton question(QWidget *parent, const QString &title, const QString &text, QMessageBox::StandardButtons buttons = ..., QMessageBox::StandardButton defaultButton = NoButton)
int question(QWidget *parent, const QString &title, const QString &text, QMessageBox::StandardButton button0, QMessageBox::StandardButton button1)


//提问对话框示例
   QMessageBox::question(this,"quest","疑问");
   QMessageBox::question(this,"quest","疑问",QMessageBox::Save|QMessageBox::Cancel);
   //参数1:父亲  参数2:标题 参数3:提示内容 参数4:按钮类型 参数5:默认关联回车的按钮
   QMessageBox::question(this,"quest","疑问",QMessageBox::Save|QMessageBox::Cancel,QMessageBox::Cancel);
  • 显示警告对话框。
    这个对话框提供一个黄色叹号图标。
QMessageBox::StandardButton warning(QWidget *parent, const QString &title, const QString &text, QMessageBox::StandardButtons buttons, QMessageBox::StandardButton defaultButton = NoButton)
int warning(QWidget *parent, const QString &title, const QString &text, QMessageBox::StandardButton button0, QMessageBox::StandardButton button1)

  //警告对话框示例
   QMessageBox::warning(this,"waring","警告");

在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
返回值是QMessageBox::StandardButton类型,可以用来判断用户选择的按钮:

        //判断用户选择的按钮
        if( QMessageBox::Save
                == QMessageBox::question(this,"quest","疑问",QMessageBox::Save|QMessageBox::Cancel,QMessageBox::Cancel) )
        {
                qDebug()<<"Save";
        }
        else
            qDebug()<<"Cancel";

QMessageBox类的 static 函数优点是方便使用,缺点也很明显:非常不灵活。我们只能使用简单的几种形式。为了能够定制QMessageBox细节,我们必须使用QMessageBox的属性设置 API。如果我们希望制作一个询问是否保存的对话框,我们可以使用如下的代码:

QMessageBox msgBox;
msgBox.setText("The document has been modified.");
msgBox.setInformativeText("Do you want to save your changes?");
msgBox.setDetailedText("Differences here...");
msgBox.setStandardButtons(QMessageBox::Save
                          | QMessageBox::Discard
                          | QMessageBox::Cancel);
msgBox.setDefaultButton(QMessageBox::Save);
int ret = msgBox.exec();
switch (ret) 
{
case QMessageBox::Save:
    qDebug() << "Save document!";
    break;
case QMessageBox::Discard:
    qDebug() << "Discard changes!";
    break;
case QMessageBox::Cancel:
    qDebug() << "Close document!";
    break;
}

msgBox 是一个建立在栈上的QMessageBox实例。我们设置其主要文本信息为“The document has been modified.”,informativeText 则是会在对话框中显示的简单说明文字。下面我们使用了一个detailedText,也就是详细信息,当我们点击了详细信息按钮时,对话框可以自动显示更多信息。我们自己定义的对话框的按钮有三个:保存、丢弃和取消。然后我们使用了exec()是其成为一个模态对话框,根据其返回值进行相应的操作。

2)QColorDialog示例:

返回选择的颜色


QColor getColor(const QColor &initial = Qt::white, QWidget *parent = nullptr, const QString &title = QString(), QColorDialog::ColorDialogOptions options = ...)

//颜色对话框 返回选择的颜色
   QColor color = QColorDialog::getColor(QColor(255,0,0));
   qDebug()<< "r = "<<color.red()<<" g = "<<color.green()<<" b = "<<color.blue();

在这里插入图片描述
3)QFileDialog示例:
返回值 选取的文件路径


QString getSaveFileName(QWidget *parent = nullptr, const QString &caption = QString(), const QString &dir = QString(), const QString &filter = QString(), QString *selectedFilter = nullptr, QFileDialog::Options options = ...)

//文件对话框 //返回值 选取的文件路径
 QFileDialog::getOpenFileName(this,"打开文件","D:/");
  //参数1:父亲  参数2:标题 参数3:默认路径 参数4:默认过滤文件类型
QString str = QFileDialog::getOpenFileName(this,"打开文件","D:/","(*.txt)");

在这里插入图片描述
4)QFontDialog示例:

返回值选取的字体属性


QFont getFont(bool *ok, const QFont &initial, QWidget *parent = nullptr, const QString &title = QString(), QFontDialog::FontDialogOptions options = ...)
QFont getFont(bool *ok, QWidget *parent = nullptr)

  //字体对话框
   bool flag;
   QFont font =QFontDialog::getFont(&flag,QFont("宋体",36));
   qDebug() << "字体:"<<font.family().toUtf8().data() << " 字号:" <<font.pointSize()
            << " 是否加粗:"<< font.bold() << " 是否倾斜"<< font.italic();

在这里插入图片描述

3、自定义消息框

支持模态对话框和非模态对话框。

  • 使用QDialog::exec()实现应用程序级别的模态对话框
  • 使用QDialog::open()实现窗口级别的模态对话框
  • 使用QDialog::show()实现非模态对话框。

1)模态对话框

Qt 有两种级别的模态对话框:

  • 应用程序级别的模态
    当该种模态的对话框出现时,用户必须首先对对话框进行交互,直到关闭对话框,然后才能访问程序中其他的窗口。
  • 窗口级别的模态
    该模态仅仅阻塞与对话框关联的窗口,但是依然允许用户与程序中其它窗口交互。窗口级别的模态尤其适用于多窗口模式。

一般默认是应用程序级别的模态。

示例:

  //模态创建 阻塞
     QDialog dlg(this);
     dlg.setWindowTitle("test");
     dlg.resize(200,100);
     dlg.exec();

调用了exec()将对话框显示出来,因此这就是一个模态对话框。当对话框出现时,我们不能与主窗口进行任何交互,直到我们关闭了该对话框。

2)非模态对话框

非模态对话框需要把.exec()换成.show(),但是show()函数不会阻塞当前线程,对话框会显示出来,然后函数立即返回,代码继续执行。若将QDialog类建立在栈上,show()函数返回,函数结束,QDialog类对象超出作用域被析构,因此对话框会消失了(一闪而过)。因此需要建立堆上的对象。

示例如下:

 //非模态对话框
        QDialog *dlg2 = new QDialog(this);//用栈区模式创建会一闪而过 需要用堆区创建
        dlg2->resize(200,100);
        dlg2->show();
        dlg2->setAttribute(Qt::WA_DeleteOnClose);//设置属性,在关闭的时候释放 防止内存泄漏

但由于主窗口作为parent时,主窗口不关闭,对话框就不会被销毁,所以会一直占用内存,容易引发内存泄漏。在这种情景下,我们可以设置 dialog 的WindowAttribute,setAttribute()函数设置Qt::WA_DeleteOnClose属性,对话框关闭时,自动销毁对话框

4、一个简单的文本文件编辑器

在这里插入图片描述

#include "mainwindow.h"
#include "ui_mainwindow.h"
#include <QDialog>
#include <QDebug>
#include <QMessageBox>
#include <QColorDialog>
#include <QFileDialog>
#include <QFontDialog>
#include <QString>
#include <QToolBar>
#include <QStatusBar>
#include <QLabel>
#include <QFile>
#include <QAction>
#include <QTextStream>

MainWindow::MainWindow(QWidget *parent) :
    QMainWindow(parent),
    ui(new Ui::MainWindow)
{
    ui->setupUi(this);
    resize(800,600);
//文本编辑功能的窗口
//设置提示
    ui->actionopen->setStatusTip("Open an file");
    ui->actionsave->setStatusTip("Save an file");
//工具栏
    QToolBar * toolBar = new QToolBar(this);
    addToolBar(Qt::LeftToolBarArea,toolBar);
    toolBar->setFloatable(false);
 //   QAction* Open = new QAction("OPEN",this);
    toolBar->addAction(ui->actionopen);
    toolBar->addAction(ui->actionsave);
//状态栏
    QStatusBar *stBar = statusBar();
    setStatusBar(stBar);
    QLabel *label = new QLabel("文本编辑工具");
    stBar->addWidget(label);
//将QTextEdit类组件作为窗口的中心组件,放在窗口中央显示区。
    textEdit = new QTextEdit(this);
    setCentralWidget(textEdit);

//使用connect()函数,为这两个QAction对象添加响应的动作
    connect(ui->actionopen,&QAction::triggered,this,&MainWindow::openFile);
    connect(ui->actionsave,&QAction::triggered,this,&MainWindow::saveFile);

}
//打开文件
void MainWindow::openFile()
{
    QString path = QFileDialog::getOpenFileName(this,"Open File","D:/");
    if(!path.isEmpty())
    {
        QFile file(path);
        if(!file.open(QIODevice::ReadOnly|QIODevice::Text))
        {
            QMessageBox::warning(this,"Read File","Open file error");
            return;
        }

        QTextStream in(&file);
        textEdit->setText(in.readAll());
        file.close();
    }
    else
    {
           QMessageBox::warning(this,"Path","Need to select any file");
    }
    return;
}
//保存文件
void MainWindow::saveFile()
{
    QString path = QFileDialog::getSaveFileName(this,"Open File","D:/","(.txt)");
    if(!path.isEmpty())
    {
        QFile file(path);
        if(file.open(QIODevice::WriteOnly|QIODevice::Text))
        {
            QMessageBox::warning(this,"Write File","Can't open file");
            return;
        }

        QTextStream out(&file);
        out<<textEdit->toPlainText();
        file.close();

    }
    else
    {
           QMessageBox::warning(this,"Path","Need to select any file");
    }
    return;
}
MainWindow::~MainWindow()
{
    delete ui;
}

在openFile()函数中,我们使用QFileDialog::getOpenFileName()来获取需要打开的文件的路径。这个函数原型如下:

QString getOpenFileName(QWidget * parent = 0,
                        const QString & caption = QString(),
                        const QString & dir = QString(),
                        const QString & filter = QString(),
                        QString * selectedFilter = 0,
                        Options options = 0)

它的所有参数都是可选的,因此在一定程度上说,这个函数也是简单的。这六个参数分别是:

  • parent:父窗口。
    Qt 的标准对话框提供静态函数,用于返回一个模态对话框;

  • caption:对话框标题;

  • dir:对话框打开时的默认目录

    • “.” 代表程序运行目录
    • “/” 代表当前盘符的根目录(特指 Windows 平台;Linux 平台当然就是根目录),这个参数也可以是平台相关的,比如“C:\”等;
  • filter:过滤器。
    用于过滤特定的后缀名。如果我们使用“Image Files(.jpg .png)”,则只能显示后缀名是 jpg 或者 png 的文件。如果需要多个过滤器,使用“;;”分割,比如“JPEG Files(.jpg);;PNG Files(.png)”;

  • selectedFilter:默认选择的过滤器;

  • options:对话框的一些参数设定
    比如只显示文件夹等等,它的取值是enum QFileDialog::Option,每个选项可以使用 | 运算组合起来。

QFileDialog::getOpenFileName()返回值是选择的文件路径。我们将其赋值给 path。通过判断 path 是否为空,可以确定用户是否选择了某一文件。只有当用户选择了一个文件时,我们才执行下面的操作。

在saveFile()中使用的QFileDialog::getSaveFileName()也是类似的。使用这种静态函数,在 Windows、Mac OS 上面都是直接调用本地对话框,但是 Linux 上则是QFileDialog自己的模拟。这暗示了,如果你不使用这些静态函数,而是直接使用QFileDialog进行设置,那么得到的对话框很可能与系统对话框的外观不一致。这一点是需要注意的。

  • 1
    点赞
  • 13
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值