最近做了一个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
就是当前的选项或者是一个空的字符串。
所以我猜想,设置成不可编辑状态时,由于我进行了一个条目的添加,所以就将当前的选项改变了。
于是我在正常的流程下,添加了一些打印语句,用于证实我的猜想。
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中进行了槽函数的连接currentIndexChanged
。addItem
会触发currentTextChanged
的信号。同时,如果设置成可编辑状态,又是为何不会触发currentTextChanged
addItems
bool QStandardItemPrivate::insertRows
,同样根据条件判断,currentIndex = 0
而其他两个分别为1和添加条目的数量,很显然不符合要求。addItems
不会触发currentIndexChange
的原因。