【Qt学习】04:QDialog

这篇具有很好参考价值的文章主要介绍了【Qt学习】04:QDialog。希望对大家有所帮助。如果存在错误或未考虑完全的地方,请大家不吝赐教,您也可以点击"举报违法"按钮提交疑问。

QDialog


对话框是 GUI 程序中不可或缺的组成部分,对话框通常会是一个顶层窗口出现在程序最上层,用于实现短期任务或者简单用户交互。

Qt 中使用QDialog类实现对话框,通常会设计一个类继承QDialog。如果QDialog 的 parent 为 NULL,则该对话框会作为一个顶层窗口,否则则作为其父组件的子对话框(此时其默认出现的位置是 parent 的中心),顶层窗口与非顶层窗口的区别在于,顶层窗口在任务栏会有自己的位置,而非顶层窗口则会共享其父组件的位置。

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

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

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

一、自定义对话框

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

  • 模态对话框,会阻塞同一应用程序中其它窗口的输入。模态对话框很常见,比如“打开文件”功能。你可以尝试一下记事本的打开文件,当打开文件对话框出现时,我们是不能对除此对话框之外的窗口部分进行操作的。
  • 非模态对话框相反,例如查找对话框,我们可以在显示着查找对话框的同时,继续对记事本的内容进行编辑。

Qt 支持模态对话框和非模态对话框,模态与非模态的实现:

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

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

  1. 应用程序级别的模态(默认):

    当该种模态的对话框出现时,用户必须首先对对话框进行交互,直到关闭对话框,然后才能访问程序中其他的窗口。

  2. 窗口级别的模态:

    该模态仅仅阻塞与对话框关联的窗口,但是依然允许用户与程序中其它窗口交互。窗口级别的模态尤其适用于多窗口模式。

调用exec()将对话框显示出来(模态对话框),当对话框出现时用户不能与主窗口进行任何交互,直到关闭了该对话框。

QDialog dialog(this);//对象创建在栈上(匿名函数释放后 dialog对象会释放)
dialog.resize(400, 300);
dialog.setWindowTitle("modal dialog");
dialog.exec();
qDebug() << "modal dialog poped up.";
2.非模态对话框

下面将 exec() 修改为 show() 定义出非模态对话框:

QDialog dialog(this);
dialog->resize(400, 300);
dialog->setWindowTitle("modalless dialog");
dialog->show();
qDebug() << "modalless dialog poped up.";

对话框竟然一闪而过,这是因为 show() 函数不会阻塞当前线程对话框会显示出来,然后函数立即返回代码继续执行。dialog 是建立在栈上的,当show()函数返回MainWindow::open()函数结束,dialog 超出作用域被析构,因此对话框消失了。

将 dialog 改成堆上建立,就不会出现这个问题了:

QDialog *dialog = new QDialog(this);//对象创建在堆区(匿名函数释放后 dialog对象不会释放)
dialog->resize(400, 300);
dialog->setWindowTitle("modalless dialog");
dialog->show();
qDebug() << "modalless dialog poped up.";

上面的代码是有问题的dialog 存在内存泄露,dialog 使用 new 在堆上分配空间却一直没有 delete。解决方案也很简单:将 MainWindow 的指针赋给 dialog 即可,利用对象树自动析构释放内存。

不过这样做存在问题:

  • 若对话框不是在一个界面类中出现,由于QWidget的parent必须是QWidget指针,就不能将普通的 C++ 类指针传给 Qt 对话框。
  • 另外如果对内存占用有严格限制,当将主窗口作为parent时,若主窗口不关闭对话框就不会被销毁,导致会一直占用内存。

在这种情景下可以设置dialog的WindowAttribute解决:函数设置对话框关闭时,自动销毁对话框。

QDialog *dialog = new QDialog(this);//对象创建在堆区(匿名函数释放后 dialog对象不会释放)
dialog->resize(400, 300);
dialog->setWindowTitle("modalless dialog");
dialog->setAttribute(Qt::WA_DeleteOnClose);//防止用户重复操作 多次在堆区开辟内存 导致内存泄露
dialog->show();
qDebug() << "modalless dialog poped up.";
3.练习代码
#include "mainwindow.h"
#include "ui_mainwindow.h"
#include <QDialog>
#include <QDebug>

MainWindow::MainWindow(QWidget *parent):QMainWindow(parent),ui(new Ui::MainWindow) {
    ui->setupUi(this);
    //点击按钮 弹出对话框
    connect(ui->actionnew, &QAction::triggered, this, [=](){
        QDialog dialog(this);//对象创建在栈上(匿名函数释放后 dialog对象会释放)
        dialog.resize(400, 300);
        dialog.setWindowTitle("modal dialog");
        dialog.exec();
        qDebug() << "modal dialog poped up.";
    });
    connect(ui->actionopen, &QAction::triggered, this, [=](){
        QDialog *dialog = new QDialog(this);//对象创建在堆区(匿名函数释放后 dialog对象不会释放)
        dialog->resize(400, 300);
        dialog->setWindowTitle("modalless dialog");
        dialog->setAttribute(Qt::WA_DeleteOnClose);//防止用户重复操作 多次在堆区开辟内存 导致内存泄露
        dialog->show();
        qDebug() << "modalless dialog poped up.";
    });
}

MainWindow::~MainWindow() {
    delete ui;
}

二、标准对话框

1.消息对话框

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

  • about:显示关于对话框。
  • aboutQt:显示关于 Qt 对话框。该对话框用于显示有关 Qt 的信息。
  • critical:显示严重错误对话框。
  • information:与QMessageBox::critical()类似,不同之处在于这个对话框提供一个普通信息图标。
  • question:与QMessageBox::critical ()类似,不同之处在于这个对话框提供一个问号图标,并且其显示的按钮是“是”和“否”。
  • warning:与QMessageBox::critical()类似,不同之处在于这个对话框提供一个黄色叹号图标。

使用QMessageBox::question()来询问一个问题,关于函数参数的解释:

  • 这个对话框的父窗口是 this。QMessageBox是QDialog的子类,这意味着它的初始显示位置将会是在 parent 窗口的中央。

  • 第二个参数是对话框的标题。

  • 第三个参数是我们想要显示的内容。

  • 第四个参数是关联的按键类型,我们可以使用或运算符(|)指定对话框应该出现的按钮。比如我们希望是一个 Yes 和一个 No。

  • 最后一个参数指定默认选择的按钮。这个函数有一个返回值,用于确定用户点击的是哪一个按钮。按照我们的写法,应该很容易的看出,这是一个模态对话框,因此我们可以直接获取其返回值。

QMessageBox使用案例:

#include "mainwindow.h"
#include "ui_mainwindow.h"
#include <QDialog>
#include <QDebug>
#include <QMessageBox>

MainWindow::MainWindow(QWidget *parent):QMainWindow(parent),ui(new Ui::MainWindow) {
    ui->setupUi(this);
    //点击按钮 弹出对话框
    connect(ui->actionnew, &QAction::triggered, this, [=](){
        QDialog dialog(this);//对象创建在栈上(匿名函数释放后 dialog对象会释放)
        dialog.resize(400, 300);
        dialog.setWindowTitle("modal dialog");
        dialog.exec();
        qDebug() << "modal dialog poped up.";
    });
    connect(ui->actionopen, &QAction::triggered, this, [=](){
        QDialog *dialog = new QDialog(this);//对象创建在堆区(匿名函数释放后 dialog对象不会释放)
        dialog->resize(400, 300);
        dialog->setWindowTitle("modalless dialog");
        dialog->setAttribute(Qt::WA_DeleteOnClose);//防止用户重复操作 多次在堆区开辟内存 导致内存泄露
        dialog->show();
        qDebug() << "modalless dialog poped up.";
    });
    //点击按钮 弹出消息对话框
    connect(ui->actionwelcome, &QAction::triggered, this, [=](){
        QMessageBox::information(this, "welcome", "welcome to this application!~  ");
        qDebug() << "critical message box poped up.";
    });
    connect(ui->actionedit, &QAction::triggered, this, [=](){
        QMessageBox::critical(this, "sorry", "being developing, looking forward to more content.");
        qDebug() << "critical message box poped up.";
    });
    connect(ui->actionhelp, &QAction::triggered, this, [=](){
        QMessageBox::StandardButton choose;
        choose = QMessageBox::question(this, "question?", "Is there any problem when using this product? ");
        if (choose == QMessageBox::Yes) {
            qDebug() << "User have question about the use of the software.";
        } else if (choose == QMessageBox::No) {
            qDebug() << "User have no question about the use of the software.";
        }
        qDebug() << "question message box poped up.";
    });
    connect(ui->actionproject, &QAction::triggered, this, [=](){
        QMessageBox::warning(this, "warning", "project cannot be edit now.");
        qDebug() << "question message box poped up.";
    });
}

MainWindow::~MainWindow() {
    delete ui;
}

自定义细节QMessageBox细节

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

MainWindow::MainWindow(QWidget *parent):QMainWindow(parent),ui(new Ui::MainWindow) {
    ui->setupUi(this);
    //点击save按钮 弹出save对话框(模态对话框)
    connect(ui->actionsave, &QAction::triggered, this, [=](){
        QMessageBox msgBox(this);
        msgBox.setText(tr("The document has been modified."));
        msgBox.setInformativeText(tr("Do you want to save your changes?"));
        msgBox.setDetailedText(tr("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.文件对话框
  1. 首先需要创建一个带有文本编辑功能的窗口

    QAction *openAction = ui->actionopen;
    QAction *saveAction = ui->actionsave;
    //设置按钮图片
    openAction->setIcon(QIcon(":/res/img/ParticleSmoke.png"));
    saveAction->setIcon(QIcon(":/res/img/filetransfer.png"));
    //设置按钮提示tips
    openAction->setStatusTip(tr("Open an existing file"));
    saveAction->setStatusTip(tr("Save a new file"));
    //设置中心组件为textEdit
    QTextEdit *textEdit = new QTextEdit(this);
    
  2. 使用connect()函数,为这两个QAction对象添加响应的动作:

    connect(openAction, &QAction::triggered, this, &MainWindow::openFile);
    connect(saveAction, &QAction::triggered, this, &MainWindow::saveFile);
    
  3. 编写核心的逻辑处理openFile()saveFile() 函数:

    //打开文件
    void MainWindow::openFile() {
        QString filepath = QFileDialog::getOpenFileName(this, tr("Open File"), ".", tr("Text Files(*.txt)"));
        if(!filepath.isEmpty()) {
            QFile file(filepath);
            if (!file.open(QIODevice::ReadOnly | QIODevice::Text)) {
                QMessageBox::warning(this, tr("Read File"), tr("Cannot open file:\n%1").arg(filepath));
                return;
            }
            QTextStream in(&file);
            textEdit->setText(in.readAll());
            file.close();
        } else {
            QMessageBox::warning(this, tr("Path"), tr("You did not select any file."));
        }
    }
    
    //保存文件
    void MainWindow::saveFile() {
        QString filepath = QFileDialog::getSaveFileName(this, tr("Open File"), ".", tr("Text Files(*.txt)"));
        if(!filepath.isEmpty()) {
            QFile file(filepath);
            if (!file.open(QIODevice::WriteOnly | QIODevice::Text)) {
                QMessageBox::warning(this, tr("Write File"), tr("Cannot open file:\n%1").arg(filepath));
                return;
            }
            QTextStream out(&file);
            out << textEdit->toPlainText();
            file.close();
        } else {
            QMessageBox::warning(this, tr("Path"), tr("You did not select any file."));
        }
    }
    
  4. 在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,每个选项可以使用 | 运算组合起来。

saveFile()中使用的QFileDialog::getSaveFileName()也是类似的。使用这种静态函数,在 Windows、Mac OS 上面都是直接调用本地对话框,但是 Linux 上则是QFileDialog自己的模拟。这表明如果你不使用这些静态函数,而是直接使用QFileDialog进行设置,那么得到的对话框很可能与系统对话框的外观不一致(需要注意的)。文章来源地址https://www.toymoban.com/news/detail-686271.html

3.颜色对话框
//颜色对话框
connect(ui->actioncolor, &QAction::triggered, this, [=](){
    QColor color = QColorDialog::getColor(QColor(255, 0, 0));
    qDebug() << "red = " << color.red() << "green = " << color.green() << "blue = " << color.blue();
});
4.字体对话框
//字体对话框
connect(ui->actionfont, &QAction::triggered, this, [=](){
    bool flag;
    QFont font = QFontDialog::getFont(&flag, QFont("方正喵呜简体", 18));
    qDebug() << "font-family:" << font.family() << "font-size:" << font.pointSize()
    << "isBold:" << font.bold() << "isitalic:" << font.italic();
    qDebug() << "QFileDialog poped up.";
});

到了这里,关于【Qt学习】04:QDialog的文章就介绍完了。如果您还想了解更多内容,请在右上角搜索TOY模板网以前的文章或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处: 如若内容造成侵权/违法违规/事实不符,请点击违法举报进行投诉反馈,一经查实,立即删除!

领支付宝红包赞助服务器费用

相关文章

  • Qt 8. UDP客户端通信

    Qt 8. UDP客户端通信

    1. 代码 2. 效果 以上代码可以实现UDP收发功能。

    2024年02月13日
    浏览(11)
  • QT客户端开发的应用场景

    QT客户端开发的应用场景

    QT 是一跨平台应用程序开发框架,支持多种操作系统,包括 Windows、macOS、Linux、Android、iOS 和嵌入式系统等。这使得 QT 非常适合开发需要在多种平台上运行的应用程序。北京木奇移动技术有限公司,专业的软件外包开发公司,欢迎交流合作。 QT 提供了一套完整的开发工具和

    2024年04月29日
    浏览(11)
  • 【Qt专栏】Qt实现TCP服务端和客户端通信

    【Qt专栏】Qt实现TCP服务端和客户端通信

    网络通信是程序员必须会的一项生存技能,这里简单的实现了服务端和客户端通信的两个小示例,代码可以直接拿来用,开发环境是Qt5.9.6。 1.项目架构 2.tcpserver.h文件 3.tcpserver.cpp文件 4.测试效果 1.项目架构 2.tcpserver.h文件 3.tcpserver.cpp文件 4.测试效果 好了,两个小程序写完并

    2024年02月12日
    浏览(13)
  • QT实现tcp服务器客户端

    QT实现tcp服务器客户端

    2024年02月07日
    浏览(14)
  • Qt 服务器/客户端TCP通讯

    Qt 服务器/客户端TCP通讯

    最近需要用到TCP/IP通讯,这边就先找个简单的例程学习一下。Qt的TCP通讯编程可以使用QtNetwork模块,QtNetwork模块提供的类能够创建基于TCP/IP的客户端与服务端应用程序,一般会使用QTcpSocket、QTcpServer类 网络通信方式主要有两种:TCP与UDP。以下拷贝网络上总结两者之间的区别:

    2023年04月26日
    浏览(7)
  • 【QT 网络云盘客户端】——实现文件属性窗口

    【QT 网络云盘客户端】——实现文件属性窗口

    目录 文件属性对话框 设置字体样式  获取文件的信息 显示文件属性对话框 当我们点击文件中的属性,则会弹出一个属性对话框:    实现过程: 0. 设置 属性 菜单项的槽函数 。 1.鼠获取鼠标选中的 QListWidgetItem ,它包含 图标 和 文件名 2.根据 文件名 找到对应的 FileInfo对象

    2024年02月15日
    浏览(7)
  • 《QT从基础到进阶·十六》QT实现客户端和服务端的简单交互

    《QT从基础到进阶·十六》QT实现客户端和服务端的简单交互

    QT版本:5.15.2 VS版本:2019 客户端程序主要包含三块:连接服务器,发送消息,关闭客户端 服务端程序主要包含三块:打开消息监听,接收消息并反馈,关闭服务端 1、先打开服务端监听功能 2、点击客户端connect连接服务端 3、在客户端输入消息点击send发送到服务端 4、在服务

    2024年02月03日
    浏览(11)
  • QT充当客户端模拟浏览器等第三方客户端对https进行双向验证

    QT充当客户端模拟浏览器等第三方客户端对https进行双向验证

    在 ssl单向证书和双向证书校验测试及搭建流程 文章中,已经做了基于https的单向认证和双向认证,,, 在进行双向认证时,采用的是curl工具或浏览器充当客户端去验证。 此次采用QT提供的接口去开发客户端向服务器发送请求,来验证https的双向认证流程。 依然以 ssl单向证书

    2024年02月14日
    浏览(38)
  • QT-使用QTcpSocket建立TCP客户端连接

    QT-使用QTcpSocket建立TCP客户端连接

    使用QT的QTcpSocket建立TCP客户端方式,十分的简单,上手也快,代码量不多,并且还自动支持重连接机制,也就是说如果你的服务端突然死机了,然后服务端又重启,那么我们的客户端这个时候是会自动去再连接的,不需要你的程序再做重连接的机制,所以我们应用起来是十分

    2024年02月14日
    浏览(13)
  • 【QT 网络云盘客户端】——主窗口界面的设计

    【QT 网络云盘客户端】——主窗口界面的设计

    目录 1.设计主窗口界面   2.设置窗口的背景图片 3. 自定义标题栏  3.1 设置toolbutton按钮的图片  3.2 设置按钮的大小 3.3 将自定义标题栏添加设置到主页面中  3.4 去除窗口的原标题栏  3.5 设置按钮颜色 3.6 切换页面功能实现 4.我的文件页面的设计 4.1 菜单栏的设计 4.2 自定义

    2024年02月15日
    浏览(6)

觉得文章有用就打赏一下文章作者

支付宝扫一扫打赏

博客赞助

微信扫一扫打赏

请作者喝杯咖啡吧~博客赞助

支付宝扫一扫领取红包,优惠每天领

二维码1

领取红包

二维码2

领红包