0

I have a combobox

c = QCombobox(self)
c.addItem("001")
c.addItem("002")
c.addItem("003")
c.addItem("004")
c.addItem("010")
c.addItem("011")
c.addItem("012")

Is it possible, when user clicks the combobox c and the list is expanded and when he starts typing e.g. the sequence 011 to automatically select the item "011"? In a default state only the first number (letter) works to help to narrow the selection.

This code (suggested by V.K. author of HiFile) does not work.

c = qtw.QComboBox(self)
for key, value in self.c_dict.items():
    c.addItem(key)

c.setEditable(True)
completer = c.completer()
completer.setFilterMode(QtCore.Qt.MatchStartsWith)
completer.setCompletionMode(qtw.QCompleter.PopupCompletion)
xralf
  • 3,312
  • 45
  • 129
  • 200
  • 1
    The behaviour you describe is already supported by default. For me, typing `01` jumps straight to `010`. It only works if there's no long delay between typing each letter, though. – ekhumoro Apr 20 '22 at 17:03
  • The four lines which you showed are correct, there is not problem with them. There must be some problem in the rest of your code. Could you show more complete part of code? Btw. "it does not work" is not sufficient description. What does it do? Does it show the popup if you start writing? Or not? Does it show the values when you open the popup manually by clicking mouse button? – HiFile.app - best file manager Apr 21 '22 at 09:16
  • Maybe you should show minimum reproducible example. There must be something else going on in your code which breaks the functionality. – HiFile.app - best file manager Apr 21 '22 at 09:19
  • @V.K.authorofHiFile I pasted the relevant code before. – xralf Apr 21 '22 at 09:22

1 Answers1

3

Get a QCompleter object from your combo box using QComboBox::completer() and then set filter mode using QCompleter::setFilterMode(filterMode) where filterMode should be either Qt::MatchContains or Qt::MatchStartsWith, depending or your needs. You may also need to set QCompleter::setCompletionMode(QCompleter::PopupCompletion)... In simple cases everything should work out-of-the box after setting these. In more complex cases, there are lots of completer customizations possible, but be prepared that it is not easy and it does not have intuitive API. Combo boxes and completers are among the beginner-not-so-friendly parts of Qt.

Here is the minimalistic example which works for me. It is in C++ but you can certainly translate it to Python.

#include <QApplication>
#include <QComboBox>
#include <QCompleter>

int main(int argc, char *argv[])
{
    QApplication a(argc, argv);
    QComboBox w;
    w.setEditable(true);
    w.addItems({"10", "01", "11"});
    w.setCurrentText(QString());
    w.setInsertPolicy(QComboBox::NoInsert);
    w.completer()->setCompletionMode(QCompleter::PopupCompletion);
    w.show();
    return a.exec();
}

Actually I found that I do not need to set filter mode, because filter mode "StartsWith" is the default. But I needed to set the completion mode to popup. Also notice that I am not creating a competer, I am using the one which was created by Qt automatically in the combo box.

And it is also a good thing to change the insert policy, because the default value "insert at bottom" is just plain nonsense, which was left in Qt probably only for backward compatibility... (as I said above, combo box and completer API is a mess).

  • It doesn't work. Here is a code which does not complete in `startswith` mode. `c = qtw.QComboBox(self) for key, value in self.c_dict.items(): c.addItem(key) completer = qtw.QCompleter(self.c_dict.keys()) completer.setFilterMode(QtCore.Qt.MatchStartsWith) completer.setCompletionMode(qtw.QCompleter.PopupCompletion) c.setCompleter(completer) ` – xralf Apr 20 '22 at 11:22
  • It considers only the first typed letter. – xralf Apr 20 '22 at 11:25
  • It does not work because you created empty completer with no values. Instead of creating a completer, you should obtain completer from the combo box. I updated the answer so that you can see a minimalistic example which works for me. – HiFile.app - best file manager Apr 20 '22 at 11:47
  • According to [this](https://stackoverflow.com/questions/22125933/how-to-create-autocomplete-combobox-in-pyqt4) question I typed this. `completer = c.completer() completer.setFilterMode(QtCore.Qt.MatchStartsWith)` but it ends with error `AttributeError: 'NoneType' object has no attribute 'setFilterMode'` – xralf Apr 21 '22 at 05:33
  • 1
    Did you set the combo box as editable before that? You must call `c.setEditable(True)` before getting the completer. – HiFile.app - best file manager Apr 21 '22 at 06:49
  • This helped and the program runs, but it does not have the desired functionality. – xralf Apr 21 '22 at 07:07
  • Then you should update the original question ad show your current code. There must be some little stupid error somewhere. Because this is the standard functionality of combo boxes and I have never had any problem with it. – HiFile.app - best file manager Apr 21 '22 at 08:08