Qt QComboBox之setEditable和currentTextChanged及其源码分析
Qt QComboBox之setEditable和currentTextChanged以及其源码分析
前言
最近做了一个QComboBox里有选项,然后选中选项之后就会自动触发条件搜索。然后我发现,在我初始化comboBox时,由于信号连接的原因会触发这个currentTextChanged信号。代码大致如下:
connect(ui->comboBox, &QComboBox::currentTextChanged,
this, &CountryType::slot_pageSearch);
void Country::setComboBox()
{
QStringList content;
int maxLen = 0;
QFont font;
font.setFamily("Microsoft YaHei");
font.setPixelSize(16);
QFontMetrics fontMetrics(font);
QString command = jointQueryComboBoxTextCommand();
QList<QStringList> texts = m_oracle->runSelectCommand(command);
foreach (QStringList text, texts) {
QString item = text.value(0)+"-"+text.value(1);
content.push_back(item);
// 计算最大宽度
maxLen = maxLen > fontMetrics.boundingRect(item).width() ?
maxLen :
fontMetrics.boundingRect(item).width();
}
// comboBox的宽度为 文字的最大宽度 + 下拉箭头的宽度 + 文字两边的间距
ui->comboBox->setMinimumWidth(maxLen + 38 + 8);
ui->comboBox->clear();
// 填充一个空选项作为筛选所有
ui->comboBox->addItem("");
ui->comboBox->addItems(content);
}
void Country::search()
{
setComboBox();
}
问题的出现
在我每一次对页面进行切换的时候,我发现这个search都会触发这个slot_pageSearch槽函数,然后执行条件搜索。
但是我今天突发奇想,我是不是应该让使用者能够手动的输入这个条件呢,于是我setEditable(true);,将编辑打开了。
也就是:
ui->comboBox->setEditable(true);
在设置了这个之后,我惊奇的发现,并没有像之前一样会触发slot_pageSearch这个槽函数。
问题分析
因为我只修改了ui->comboBox->setEditable(true);,所以我肯定,问题就是发生在这个地方,于是我在网上搜索与这个问题有关联的答案。
最后,我还是在QT的官方文档中对于currentText这个部分的介绍中,找到了问题的原因。
大概意思就是说,当你将QComboBox设置成可编辑的状态时(setEditable(true)),currentText就是当前的框内显示的文字。当不为可编辑的状态时,currentText就是当前的选项或者是一个空的字符串。
所以我猜想,设置成不可编辑状态时,由于我进行了一个条目的添加,所以就将当前的选项改变了。
currentTextChanged信号触发
于是我在正常的流程下,添加了一些打印语句,用于证实我的猜想。
void Country::setComboBox() {
...
// 填充一个空选项作为筛选所有
qDebug() << "1";
ui->comboBox->addItem("");
qDebug() << "2";
ui->comboBox->addItems(content);
qDebug() << "3";
...
}
void CountryType::slot_pageSearch()
{
...
qDebug() << "111";
...
}
输出的结果为:
1
111
2
3
这也就表明了,我是在setItem之后,就会触发槽函数。但是具体为啥是这样的,为啥addItems不会触发currentTextChanged呢?
所以我带着问题,决定去源码里找答案
源码分析
// 代码调用结构
1. QComboBox::addItem(int , const QIcon &, const QString &, const QVariant &)
----> QStandardItem::setData(const QVariant &, int )
----> QStandardItemModelPrivate::itemChanged(QStandardItem *, const QVector<int> &)
----> signal: QStandardItemModel::dataChanged(QModelIndex,QModelIndex) slot: QComboBox::_q_dataChanged(QModelIndex,QModelIndex)
----> if (lineEdit) lineEdit->setText(); else emit currentTextChanged(QString);
2. QComboxBox::addItems(QStringList)
----> QComboxBox::insertItems(int, QStringList)
----> QStandardItem::insertRows(int, QList<QStandardItem*>)
----> QStandardItemPrivate::insertRows(int, QList<QStandardItem*>)
----> rowsAboutToBeInserted(QStandardItem *, int , int)
----> QAbstractItemModel::beginInsertRows(const QModelIndex &, int , int )
----> signal: rowsAboutToBeInserted(const QModelIndex &, int , int ) slot:
----> QAbstractItemModelPrivate::rowsAboutToBeInserted(const QModelIndex &, int , int )
----> QStandardItemModelPrivate::rowsInserted(QStandardItem *, int , int )
----> QAbstractItemModel::endInsertRows()
----> void QAbstractItemModelPrivate::rowsInserted(const QModelIndex &, int , int )
----> signal: QAbstractItemModel::rowsInserted(QModelIndex,int,int) slot: QComboBox::_q_rowsInserted(QModelIndex,int,int)
- 首先,我从最简单的来入手——
addItem

在上面这张图里可以知道,addItem调用的是insertItem这个函数,这个是用来插入条目的一个函数;
然后就是insertItem这个函数,我们可以看到,这个函数会根据你的是不是原始的QStandardItemModel,是的话,就会去设置数据;

这里有两个分支,
setData


随着函数的调用过程,信号dataChanged被发射了,同时,在qcombobox.cpp中有对这个信号的连接,


我们进到这个_q_dataChanged()函数里面,

这里有一段代码:
if (currentIndex.row() >= topLeft.row() && currentIndex.row() <= bottomRight.row()) {
const QString text = q->itemText(currentIndex.row());
if (lineEdit) {
lineEdit->setText(text);
updateLineEditGeometry();
} else {
emit q->currentTextChanged(text);
}
q->update();
#ifndef QT_NO_ACCESSIBILITY
QAccessibleValueChangeEvent event(q, text);
QAccessible::updateAccessibility(&event);
#endif
}
在这里,我们就找到了我们的目标currentTextChanged这个信号。但是发射这个信号的前提条件是:
currentIndex.row() >= topLeft.row() && currentIndex.row() <= bottomRight.row()也就是说,当前的下标的值需要在范围内- 当前的状态必须是不可编辑状态才会发射信号
所以这里就是设置成可编辑状态后,不会触发信号的原因;
insertRow



现在关键的函数要来了,这个函数bool QStandardItemPrivate::insertRows,在待会addItems这个函数分析时也会用到。


在这里发射了这个rowInserted()信号,这个信号,又在QComboBox中进行了槽函数的连接


所以在这个函数里面,如果是插入的第一个条目,就会把当前的下表设置成0,这时候就会触发另外一个信号currentIndexChanged。

至此,我们就能明白,为什么addItem会触发currentTextChanged的信号。同时,如果设置成可编辑状态,又是为何不会触发currentTextChanged
- 其次,我们从第二个函数,也就是
addItems


到这里,就能发现,这个部分调用的还是这个bool QStandardItemPrivate::insertRows,同样根据条件判断,currentIndex = 0而其他两个分别为1和添加条目的数量,很显然不符合要求。
所以这也就是为什么addItems不会触发currentIndexChange的原因。
至此,根据源码的分析,所有发生的事情,都能够正常的解释通了。
Qt QComboBox之setEditable和currentTextChanged及其源码分析的更多相关文章
- hadoop之hdfs------------------FileSystem及其源码分析
FileSystem及其源码分析 FileSystem这个抽象类提供了丰富的方法用于对文件系统的操作,包括上传.下载.删除.创建等.这里多说的文件系统通常指的是HDFS(DistributedFile ...
- [Qt] 《开发指南》samp4.1 源码分析
界面: 功能: 输入单价和数量,计算总价:进制转换 控件: Qlabel QLineEdit QPushButton 文件依赖关系图(depend on): main.cpp:程序入口 widget. ...
- LinkedHashMap及其源码分析
以下内容基于jdk1.7.0_79源码: 什么是LinkedHashMap 继承自HashMap,一个有序的Map接口实现,这里的有序指的是元素可以按插入顺序或访问顺序排列: LinkedHashMa ...
- CoordinatorLayout自定义Bahavior特效及其源码分析
@[CoordinatorLayout, Bahavior] CoordinatorLayout是android support design包中可以算是最重要的一个东西,运用它可以做出一些不错的特效 ...
- String,StringBuffer,StringBuilder的区别及其源码分析
String,StringBuffer,StringBuilder的区别这个问题几乎是面试必问的题,这里做了一些总结: 1.先来分析一下这三个类之间的关系 乍一看它们都是用于处理字符串的java类,而 ...
- 经典的HTML5游戏及其源码分析
HTML5已经相当强大,在HTML5平台上,我们可以完成很多非常复杂的动画效果,包括游戏在内.早期我们只能利用flash来实现网络游戏,现在我们又多了一种选择,即用HTML5制作游戏.相比flash, ...
- [Java] I/O底层原理之一:字符流、字节流及其源码分析
关于 I/O 的类可以分为四种: 关于字节的操作:InputStream 和 OutPutStream: 关于字符的操作:Writer 和 Reader: 关于磁盘的操作:File: 关于网络的操作: ...
- pdfmake.js使用及其源码分析
公司项目在需要将页面的文本导出成DPF,和支持打印时,一直没有做过这样的功能,花了一点时间将其做了出来,并且本着开源的思想和技术分享的目的,将自己的编码经验分享给大家,希望对大家有用. 现在是有一个文 ...
- 8.深入k8s:资源控制Qos和eviction及其源码分析
转载请声明出处哦~,本篇文章发布于luozhiyun的博客:https://www.luozhiyun.com,源码版本是1.19 又是一个周末,可以愉快的坐下来静静的品味一段源码,这一篇涉及到资源的 ...
随机推荐
- tensorflow源码解析之framework-device
目录 什么是设备 设备属性描述 device_base 关系图 涉及的文件 迭代记录 1. 什么是设备 "设备"是一个很容易引起混淆的概念,在TF中,设备device专指能够执行实 ...
- 【故障公告】没有龙卷风,k8s集群翻船3次,投用双集群恢复
今天没有龙卷风(异常的高并发请求),故障却依然出现,问题非常奇怪. 某种异常情况会造成短时间内, k8s 集群中大量 pod (超过60%)因健康检查失败而处于 CrashLoopBackOff 状态 ...
- 2022年官网下安装MongoDB最全版与官网查阅方法(5.0.6)
一.下载安装 1.百度搜索,找到官网,或直接访问:https://www.mongodb.com/ 2.寻找下载位置,双击下载. 3.找到本地位置,双击执行,进入欢迎界面,选择next. 4.勾选协议 ...
- 【译】.NET 6 网络改进
原文 | Máňa Píchová 翻译 | 郑子铭 对于 .NET 的每个新版本,我们都希望发布一篇博客文章,重点介绍网络的一些变化和改进.在这篇文章中,我很高兴谈论 .NET 6 中的变化. 这篇 ...
- Python入门随记(3)
1.len() 长度或规模函数 2.Unicode转为单字符用chr() 单字符转为Unicode用ord() 3.关于字符的操作函数 函数 作用 lower() 变为小写 upper() 变为大写 ...
- JavaWeb——Http
4.1.什么是http http(超文本传输协议)是一个简单的请求-响应协议,它通常运行在TCP之上. 文本:无链接 超文本:利用超链接将普通文本的信息组织在一起的超级文本 4.2.http两个时代的 ...
- Failed to execute "C:\learn\C\程序练习\1.exe": Error 0: 操作成功完成。 请按任意键继续. . .问题解决
在DEV中编译运行时出现以上提示,原因是该文件被杀毒软件隔离了,认为它是病毒文件 解决办法,找到该文件进行恢复
- BZOJ3159: 决战(FHQ Treap)
传送门: 解题思路: 算是补坑了,这题除了Invert以外就可以树剖线段树解决了. 考虑Invert操作,延续先前树链剖分的做法,考虑先前算法的瓶颈. 最暴力的方法是暴力交换权值,然而这种方法忽略了当 ...
- GitHub如何选择合适的license(许可证)
license译为许可证,也可作为开源协议,它可以将自己创作的东西,授权给他人使用,并约定了使用者可以有的权利和必须遵从的义务.现在很多优秀的开源项目都有设置license,不同的license所约束 ...
- Redis常见问题及其场景问题
假如 Redis 里面有 1 亿个 key,其中有 10w 个 key 是以 某个固定的已知的前缀开头的,如果将它们全部找出来? 使用 keys 指令可以扫出指定模式的 key 列表. 对方接着追 ...