【技术】Qt对话框讲解

前言

Qt中对话框QDialog是几乎每个项目都会用到的GUI窗口对象。本文通过讲解QDialog及其子类在项目中经常被用到的功能点,帮助小伙伴们理解和掌握其使用方法。

QDialog

QDialog是Qt对话框类树中的基类,Qt为我们提供了很多QDialog子类,即标准对话框,实现了丰富的对话框功能。下面我们先看一下QDialog本身需要关注的一些问题。

模态对话框

一句话描述模态对话框:

除模态对话框外,用户无法选择并操作其他窗口,只有关闭了模态对话框,用户才能操作其他窗口。

下面的代码,用QDialog::exec函数实现了模态对话框(请结合Qt中QDialog的类帮助文档阅读下面的代码):

QDialog dlg;
dlg.exec(); // 执行模态对话框

等效于

QDialog dlg;
dlg.setModel(true); // 设置为模态
dlg.show(); // 显示对话框

原理上,exec函数是阻塞执行的,直到模态对话框关闭才返回,可以看出,exec内部有一个自己的消息循环,一直在循环处理消息。用代码模拟如下:

class QDialog
{
public:int exec(){show(); // 显示窗口m_event_loop.exec(); // 事件循环hide(); // 隐藏窗口return result(); // 返回退出码}private:QEventLoop m_event_loop; // 事件循环对象
}

而调用show函数是不需要对话框关闭就会立即返回的,相当于setVisible(true),仅仅设置了允许窗口显示的标记而已。先调用setModel(true),再调用show()仍然是立即返回的,这种情况下,模态对话框使用的消息循环是main函数中app.exec中的启动的应用全局消息循环。原理上尝试理解即可,暂时不需要掌握,在后面的文章中会有对消息循环(QEventLoop)的专门讲解。

使用场景

exec阻塞执行方式,不会将本来可以在一个函数内实现的业务代码,分散到多个函数中去。

比如下面的例子,弹出对话框让用户输入名称,然后校验用户输入的用户名是否正确,在一个函数内即可完成此功能:

class Test 
{
public:void checkUsername(){QString name;MyDialog dlg; // MyDialog为我们自定义的QDialog子类// 用户点击取消按钮,直接返回if (dlg.exec() == QDialog::Rejected) {return;}name = dlg.getName(); // 获取用户名if (name != "ABC") // 校验用户名{qDebug() << "Name Error!"; // 用户名校验错误return;}else{qDebug() << "Pass"; // 用户名校验正确}}
}

如果使用show会怎么样呢?使用show实现同样的功能,代码如下:

class Test : public QObject
{Q_OBJECT
public:void showNameInputDialog(){   // 下面额外监听对话框关闭信号connect(&m_dlg, SIGNAL(finished(int)), this, SLOT(slotDialogFinished(int)));m_dlg.setModel(true);m_dlg.show();}// 响应对话框关闭信号的槽void slotDialogFinished(int code){if (code == QDialog::Rejected) // 用户点击取消按钮,直接返回{return;}name = m_dlg.getName(); // 获取用户名if (name != "ABC") // 校验用户名{qDebug() << "Name Error!";return;}else{qDebug() << "Pass"; // 用户名校验正确}}private:// MyDialog为我们自定义的QDialog子类// 需要延长dlg的生命周期,把exec例子中的函数内变量,写成类的成员变量MyDialog m_dlg; 
}

可以看到,使用show来显示对话框,不仅要使用信号槽,还要添加成员变量、添加槽函数,非常麻烦,而且一个连续的业务流程代码被分散到了多个函数中。

exec()是开发中最常用的模块对话框调用方法。由上面的例子可知,模态对话框一般用来在某个处理过程中,请求用户输入内容,或配置必要的处理参数。而且,这样可以保持业务处理代码连续不分散。

非模态对话框

一句话描述非模态对话框:

非模态对话框不会独占用户鼠标和键盘输入,用户可以随时在其他窗口和非模态窗口之间切换操作。

非模态对话框一般用来实现悬浮窗口。非模态对话框会悬浮在父窗口上层,父窗口通过构造函数的parent参数设置。即使点击了父窗口,非模态对话框也会保持在父窗口上层,变化仅仅是失去焦点。

非模态对话框的典型例子是,使用文本编辑软件如notepad.exe,进行文本编辑时悬浮的文本搜索框,就是一种非模态对话框。

非模态对话框使用比较简单,定义好对话框变量后,直接调用成员函数show即可显示,这里不做过多讲解。

QDialog子类

说完了QDialog,下面开始介绍QDialog子类。

Qt标准对话框

根据使用频率大致对QDialog子类排序,见下表,读者可根据此顺序学习使用:

子类描述
QMessageBox信息对话框,最常用,用于显示提示信息、警告信息、询问信息、致命信息,并接受用户选择下一步操作。
QFileDialog文件对话框,常用,用于选择文件、文件夹。
QInputDialog输入对话框,用于获取字符串输入、数值输入、以及选择列表中的某一项。
QColorDialog、QFontDialog颜色和字体对话框。
QProgressDialog进度显示对话框。
QErrorMessage错误信息显示对话框,提供不再显示某条内容的消息的选项。
QWizard向导对话框,用于引导用户进行某个操作。

自定义QDialog子类

自定义QDialog子类是必备技能。很多情况下,标准对话框不满足使用要求,此时就需要我们自定义对话框实现响应的功能。

自定义对话框有以下几点需要说明。

1. done、accept、reject

这三个函数是自定义函数一定需要用到的函数,用于控制以什么样的状态码退出对话框。
done函数用来退出对话框并设置退出码。
对于模态对话框,done相当于:

void QDialog::done(int code)
{setResult(code); // 设置退出码if (isModel()) // 如果是模态对话框{m_event_loop.exit(code); // 退出消息循环}else{hide(); // 隐藏窗口}
}

done结束对话框内部消息循环,done函数退出,随后下一个消息循环中,exec函数中的消息循环返回,exec函数也退出,最后返回到调用对话框的代码处。

accept相当于

done(QDialog::Accepted);

reject相当于

done(QDialog::Rejected);

2. 不要用exec的返回值来传递内容信息

exec的返回值可以用来传递退出码。由上述内容可知,done、accept、reject可以用来退出对话框并设置退出码。

笔者在初次自定义对话框时,总想着将对话框中的输入内容,用exec返回。例如,将用户在对话框中选择的列表项索引,用done(index)来返回。这里明确告诉小伙伴们这样的用法是不提倡的。因为如果是字符串,那怎么返回呢?

正确的做法是,使用done返回用户对编辑的确认状态,即确认设置内容还是取消设置,确认内容用accept,取消设置用reject。这样一来,自定义的QDialog类需要提供对话框数据获取接口,当exec返回后,再使用对话框对象实例,调用数据获取接口获取用户编辑的数据。

举个简单的例子:

class MyDialog : public QDialog
{
public:explicit MyDialog(QWidget *parent = NULL);QString getName(){// 从界面输入框中获取用户输入内容return ui->lineEdit_name->text();}QString getPassword(){// 从界面输入框中获取用户输入内容return ui->lineEdit_password->text();}private:// 点击确认按钮响应void slotOkButtonClicked(){accept();}// 点击取消按钮响应void slotCancelButtonClicked(){reject();}
}

结语

本文代码略多,粗略地讲解了Qt中对话框的类型和理解对话框工作原理的关键问题。细节的部分需要读者自己去实践,文章中无法讲解得太过详细。讲解太过详细,第一,读起来费时费力,倒不如花时间自己写代码尝试,第二,学习容易出现问题的地方是较难理解的地方,细节不需要面面俱到 ,用到的时候再查就可以。学习Qt某个模块,要先把握住某一个功能模块的运作机理、框架,而不是一头钻进庞杂的内容里,没有方向地去学习,效率很低也很痛苦。

本文是Qt基础文章,笔者想尽快写完Qt的基础部分,除了基础还有很多东西需要掌握,不能一直在基础上转圈圈。小伙伴们如果有疑问,欢迎留言。如果问题很多,笔者会考虑建一个讨论群,尽自己能力帮助想要学习Qt的同学,大家一起进步。


本文首发于微信公众号“Qt未来工程师”。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/437016.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

mysql集群方案对比_MySQL云原生方案在携程开发测试场景中的实践

一、背景与使用场景随着Kubernetes平台在容器云计算领域的一统天下&#xff0c;云原生 (Cloud Native) 一词也被提的越来越频繁。各类应用纷纷走上了容器化、云原生化的道路&#xff0c;无状态服务应用在Kubernetes平台上的运行&#xff0c;已经得到了大规模生产级别的实践认可…

UML核心问题

帮助读者理解每种图是为了展现什么内容、解决什么核心问题而存在的。 下面按照重要性先后依次说明。 1. 用例图 核心&#xff1a;人、目标、功能 以人为出发点&#xff0c;描述人实现一个目标需要使用哪些功能&#xff0c;仅仅指出功能点就行&#xff0c;点到即止&#xff0c…

【转】setsocketopt getsocketopt比较全的参数说明

setSocketOption各项的含义 DELAY 小缓冲写入延迟值。如果为0&#xff0c;则禁用了TCP对于小缓冲区操作的Nagle算法。如果需要启动该算法则需要把该值设置为非0 KEEPLIVE 保持连接的特性。如果该值为0&#xff0c;则禁用了保持连接的特性。如果要启动该特性则要把…

vb.net datagridview数据批量导入sql_【自学C#】|| 笔记 44 ComboBox:组合框控件数据绑定...

一、ComboBox&#xff1a;组合框控件数据绑定在 Windows 应用程序中很多控件都提供了 DataSource 属性&#xff0c;并将 DataSet 或 DataTable 的值直接赋给该属性&#xff0c;这样在控件中即可显示从数据库中查询出来的数据。 常用的数据绑定控件有文本框(TextBox)、标签(L…

【转】C#Socket编程详解(一)TCP与UDP简介

一、TCP与UDP 1、TCP 1.1 定义 TCP&#xff08;TransmissionControl Protocol&#xff09;传输控制协议。 是一种可靠的、面向连接的协议&#xff08;eg:打电话&#xff09;、传输效率低全双工通信&#xff08;发送缓存&接收缓存&#xff09;、面向字节流。使用TCP的应…

【精华】掌握Qt调试技术

前言 软件调试&#xff0c;是开发过程中必备的技能。通过调试可以发现软件存在的bug&#xff0c;即缺陷。调试可以帮助开发者窥探到软件运行过程中的详细状态&#xff0c;从而为消除bug提供重要信息。调试的英文是debug&#xff0c;前面的de在英文中表示“反对”&#xff0c;“…

ps海报合成教程_如何利用PS制作海报?详细教程来了!

今天能学长给大家带来一套利用PS做【月满中秋】海报的教程。福利干货到&#xff0c;请大家接住&#xff01;话不多说&#xff0c;直接上教程【月满中秋-第一课】月满中秋-海报制作教程https://www.zhihu.com/video/1187797197951918080为了方便大家阅读&#xff0c;本篇文章特地…

【转】WebSocket详解(一):初步认识WebSocket技术

1、前言 HTML5规范在传统的web交互基础上为我们带来了众多的新特性&#xff0c;随着web技术被广泛用于web APP的开发&#xff0c;这些新特性得以推广和使用&#xff0c;而websocket作为一种新的web通信技术具有巨大意义。 本文将带您认识WebSocket。也可查看本文的下篇&#x…

【Qt调试技巧】Profile配置使用及一些坑

介绍 不知从哪个版本起&#xff0c;Qt Creator中的构建配置中&#xff0c;增加了一种新型配置&#xff0c;名叫“Profile”&#xff0c;如下图所示&#xff1a; 官方对Profile的描述是&#xff1a;Profile是介于Debug和Release中间的一种配置。具体是什么意思呢&#xff1f;…

python 语句简写_自学Python-语句之列表推导式

先举例分析运行过程&#xff1a;例如&#xff1a;#将list_a[1,2,3,4,5]元素扩大10倍&#xff0c;生成新的列表。如果按传统的for循环来写&#xff1a;--------------------list_a[1,2,3,4,5]list_b[]for x in list_a:list_b.append(x*10)print(list_b)输出&#xff1a;[10, 20,…

Qt中使用OpenSSL

概述 OpenSSL官网 OpenSSL官网&#xff1a;OpenSSL是一个开源跨平台的加密库&#xff0c;应用广泛。Windows提供了自己的一套加密认证API&#xff0c;感兴趣的话可以参考&#xff1a;Windows Authentication Overview。 Qt官方文档&#xff1a; Secure Sockets Layer (SSL)…

【转】带你玩转Visual Studio——03.带你了解VC++各种类型的工程

上一篇文章带你玩转Visual Studio——带你新建一个工程一文中提到新建一个工程时会有很多的工程类型(图1)&#xff0c;现在将简单介绍各种类型工程的含义和主要用途。由于这里包含的工程类型太多&#xff0c;有很多本人也没有接触过&#xff0c;有些可能理解的不太对的地方还请…

数学学习过程中的感悟(一)

前言 最近在考研复习&#xff0c;回顾自己的学习数学的过程&#xff0c;有一些感悟&#xff0c;在此记录一下。 正文 大学的时候&#xff0c;学习到了高数&#xff0c;但是接触不久就丧失了兴趣。明明中学时代还很喜欢学习数学&#xff0c;为什么到了大学&#xff0c;一点兴…

如何调整金格电子章服务器印章_重磅!公安部再度认可电子签名、电子印章法律效力!...

近日&#xff0c;公安部发布《关于修改〈公安机关办理刑事案件程序规定〉的决定》&#xff0c;对《公安机关办理刑事案件程序规定》&#xff08;以下简称规定&#xff09;进行了全面修改完善&#xff0c;并将于9月1日起施行。修改后的规定共14章388条。其中&#xff0c;新增的第…

【转】带你玩转Visual Studio——04.带你高效开发

上一篇文章带你玩转Visual Studio——带你了解VC各种类型的工程一文中讲了各种类型VC工程的主要功能和用途。现在将带你一起快速开发c程序。 有过Java开发经验的人都知道Java的常用开发工具(如Eclipse、Intellij IDEA等)都有非常强大的关键字高亮、智能提示、快速追踪等的功能…

python编译make_Python在Linux下编译安装

【准备环境】Linux centos【前言】1 linux下默认带Python&#xff0c;带的是2.7版本的 &#xff0c;如果需要升级版本&#xff0c;需要把系统的自带的Python改名或者卸载&#xff0c;再次安装你所需要的Python版本&#xff0c;centos下由于yum依赖自带的Python2.7&#xff0c;所…

【信号与线性系统】知识点与学习攻略

知识点理解 关于正交分解可以看这个视频&#xff1a; https://www.bilibili.com/video/BV1qV411C7u6/ 记住两个完备正交函数集&#xff1a; 一个是正余弦三角函数&#xff0c;非零不同频率项乘积为0&#xff0c;非零同频率项乘积积分为T/2&#xff0c;零频率项乘积积分为T。 一…

【转】C# 网络连接中异常断线的处理:ReceiveTimeout, SendTimeout 及 KeepAliveValues(设置心跳)

在使用 TcpClient 网络连接中常常会发生客户端连接异常断开, 服务端需要设置检测手段进行这种异常的处理&#xff1b; 1、对于短连接, 通过对 Socket 属性ReceiveTimeout 和 SendTimeout 设置恰当的值, 使得程序在进行读/写时超时, 会产生 SocketException 异常, 通过检查这个…

python 几何教学_opencv-python教程学习系列11-几何变换

前言opencv-python教程学习系列记录学习python-opencv过程的点滴&#xff0c;本文主要介绍几何变换&#xff0c;坚持学习&#xff0c;共同进步。系统环境系统&#xff1a;win7_x64;python版本&#xff1a;python3.5.2&#xff1b;opencv版本&#xff1a;opencv3.3.1&#xff1b…

【数学+编程】对数学函数进行抽象

目的 将数学函数抽象为类。 类名 函数 属性 基本属性 表达式定义域值域周期性、单调性等特性 方法 求值&#xff1a;返回值平移&#xff1a;返回新的函数伸缩&#xff1a;返回新的函数反转&#xff1a;返回新的函数复合&#xff1a;参数为另外一个函数&#xff0c;返回…