QComboBox - filtering by typing
-
@VRonin said in QComboBox - filtering by typing:
Does this do what you want?
#include <QApplication> #include <QStringListModel> #include <QPushButton> #include <QComboBox> #include <QSortFilterProxyModel> int main(int argc, char **argv) { QApplication app(argc, argv); QStringList modleList; for(int i=1;i<1000;++i) modleList << QStringLiteral("%1%2").arg(QLatin1Char('a'+(i%26))).arg(i,3,10,QLatin1Char('0')); QStringListModel model(modleList); QSortFilterProxyModel filterModel; filterModel.setSourceModel(&model); QComboBox w; w.setModel(&filterModel); w.setEditable(true); w.setCompleter(nullptr); QObject::connect(&w, &QComboBox::editTextChanged, &filterModel, [&filterModel](const QString& input){filterModel.setFilterRegExp('^'+input);},Qt::QueuedConnection); w.show(); app.exec(); return 0; }
There isn't filtration by content. Am I wrong?
-
Looking at the code I'm pretty sure there is. Have you actually loaded it in your IDE and given it a try?
-
@kshegunov said in QComboBox - filtering by typing:
Looking at the code I'm pretty sure there is. Have you actually loaded it in your IDE and given it a try?
Of course.
-
@michaeldev said in QComboBox - filtering by typing:
There isn't filtration by content. Am I wrong?
What does the line:
QObject::connect(&w, &QComboBox::editTextChanged, &filterModel, [&filterModel](const QString& input){filterModel.setFilterRegExp('^'+input);},Qt::QueuedConnection);
do?
-
@JonB said in QComboBox - filtering by typing:
@michaeldev said in QComboBox - filtering by typing:
There isn't filtration by content. Am I wrong?
What does the line:
QObject::connect(&w, &QComboBox::editTextChanged, &filterModel, [&filterModel](const QString& input){filterModel.setFilterRegExp('^'+input);},Qt::QueuedConnection);
do?
Have you actually loaded it in your IDE and given it a try?
-
@michaeldev
No, I don't have an IDE or a C++ compiler. -
@michaeldev said in QComboBox - filtering by typing:
Have you actually loaded it in your IDE and given it a try?
I have and it works. There a couple of GUI tweaks to be done to it, which I imagine are left to you, however the example is functional!
-
@kshegunov said in QComboBox - filtering by typing:
@michaeldev said in QComboBox - filtering by typing:
Have you actually loaded it in your IDE and given it a try?
I have and it works. There a couple of GUI tweaks to be done to it, which I imagine are left to you, however the example is functional!
Thanks a lot. Даже так: спасибо, друг! ))
-
@VRonin said in QComboBox - filtering by typing:
Does this do what you want?
#include <QApplication> #include <QStringListModel> #include <QPushButton> #include <QComboBox> #include <QSortFilterProxyModel> int main(int argc, char **argv) { QApplication app(argc, argv); QStringList modleList; for(int i=1;i<1000;++i) modleList << QStringLiteral("%1%2").arg(QLatin1Char('a'+(i%26))).arg(i,3,10,QLatin1Char('0')); QStringListModel model(modleList); QSortFilterProxyModel filterModel; filterModel.setSourceModel(&model); QComboBox w; w.setModel(&filterModel); w.setEditable(true); w.setCompleter(nullptr); QObject::connect(&w, &QComboBox::editTextChanged, &filterModel, [&filterModel](const QString& input){filterModel.setFilterRegExp('^'+input);},Qt::QueuedConnection); w.show(); app.exec(); return 0; }
This code does. After changing filtering code to
filterModel.setFilterRegExp(QRegExp(input, Qt::CaseInsensitive, QRegExp::FixedString))
I have situation nearly to my target. Why "nearly" : I have to press twice filtering symbol in edit. After first pressing - all item appears in edit. And list are being filtered by this item, so - only one item in list. After second pressing - everything is OK. There are filter substring in edit and appropriate items in list.
-
@JonB said in QComboBox - filtering by typing:
@michaeldev said in QComboBox - filtering by typing:
There isn't filtration by content. Am I wrong?
What does the line:
QObject::connect(&w, &QComboBox::editTextChanged, &filterModel, [&filterModel](const QString& input){filterModel.setFilterRegExp('^'+input);},Qt::QueuedConnection);
do?
It connects the
editTextChanged
signal to a lambda to which a reference to filterModel is passed (the content of the square brackets), that will be called with a QString parameter (matching the signature of the signal). The lambda body updates the regular expression used byfilterModel
. -
@SGaist said in QComboBox - filtering by typing:
@JonB said in QComboBox - filtering by typing:
@michaeldev said in QComboBox - filtering by typing:
There isn't filtration by content. Am I wrong?
What does the line:
QObject::connect(&w, &QComboBox::editTextChanged, &filterModel, [&filterModel](const QString& input){filterModel.setFilterRegExp('^'+input);},Qt::QueuedConnection);
do?
It connects the
editTextChanged
signal to a lambda to which a reference to filterModel is passed (the content of the square brackets), that will be called with a QString parameter (matching the signature of the signal). The lambda body updates the regular expression used byfilterModel
.It's clear.
-
@SGaist
My question was purely a rhetorical one! In reply to @michaeldev'sThere isn't filtration by content. Am I wrong?
I was trying to draw his attention to the
connect()
line with the lambda containing the regular expression as doing the filtering when he said he couldn't see anything which would be doing that. -
The best option I found is with QCompleter class
combo->setEditable(true); // make placeholder editable combo->setCurrentIndex(-1); // focus on placeholder combo->lineEdit()->setPlaceholderText("Enter keywords..."); combo->setInsertPolicy(QComboBox::NoInsert); // make QComboBox not insertable, but still editable combo->completer()->setCompletionMode(QCompleter::PopupCompletion); // popup list below with possible options combo->completer()->setCaseSensitivity(Qt::CaseInsensitive); combo->completer()->setFilterMode(Qt::MatchContains); // Finding any matches in text
-
come from py, with pyside6, the worked code should be:
from PySide6.QtWidgets import QComboBox, QCompleter, QWidget from PySide6.QtCore import Qt, QStringListModel class Selector(QComboBox): def __init__(self, item_list: list | tuple, parent: QWidget = None, filter: bool = True): super().__init__(parent) self.item_list = item_list self.setEditable(True); self.setInsertPolicy(self.InsertPolicy.NoInsert) self.addItems(item_list) if filter: completer = self._init_completer() self.setCompleter(completer) self.editTextChanged.connect(self.on_text_changed) def _init_completer(self) -> QCompleter: comp = QCompleter(self) comp.setFilterMode(Qt.MatchFlag.MatchContains) comp.setCompletionMode(QCompleter.CompletionMode.PopupCompletion) comp.setCaseSensitivity(Qt.CaseSensitivity.CaseInsensitive) return comp def on_text_changed(self, text): filtered_items = [item for item in self.item_list if text.lower() in item.lower()] model = QStringListModel(filtered_items, self) self.completer().setModel(model)
Referenced from @TENK228 code.
(this problem troubled me, a newer, for a few days.)