Skip to content
  • Categories
  • Recent
  • Tags
  • Popular
  • Users
  • Groups
  • Search
  • Get Qt Extensions
  • Unsolved
Collapse
Brand Logo
  1. Home
  2. Qt Development
  3. General and Desktop
  4. QComboBox - filtering by typing
Forum Updated to NodeBB v4.3 + New Features

QComboBox - filtering by typing

Scheduled Pinned Locked Moved Unsolved General and Desktop
27 Posts 9 Posters 12.1k Views 3 Watching
  • Oldest to Newest
  • Newest to Oldest
  • Most Votes
Reply
  • Reply as topic
Log in to reply
This topic has been deleted. Only users with topic management privileges can see it.
  • M Offline
    M Offline
    michaeldev
    wrote on last edited by
    #12

    Right now my code :

    #ifndef MYCOMBOBOX_H
    #define MYCOMBOBOX_H
    
    #include <QComboBox>
    #include <QtSql>
    
    class MyComboBox : public QComboBox
    {
    
        Q_OBJECT
    
    public:
        explicit MyComboBox(QWidget *parent);
        virtual void showPopup();
        void focusOutEvent(QFocusEvent* event);
        void init(const QSqlRelationalTableModel *model,
                  const int idx,
                  const QString &relFiled);
    
    private:
        int relFieldIdx;
    };
    
    #endif // MYCOMBOBOX_H
    
    
    #include "mycombobox.h"
    
    #include <QCompleter>
    #include <QApplication>
    
    MyComboBox::MyComboBox(QWidget *parent) :
        QComboBox(parent)
    {
    }
    
    //Better do this in constructor, but - file ui
    void MyComboBox::init(const QSqlRelationalTableModel *model,
                          const int idx,
                          const QString &relFiled)
    {
        QSqlTableModel *relModel = model->relationModel(idx);
    
        relFieldIdx = relModel->fieldIndex(relFiled);
    
        setModel(relModel);
        setModelColumn(relFieldIdx);
        setEditable(false);
    }
    
    void MyComboBox::showPopup()
    {
        setEditable(true);
    
        QCompleter *completer = new QCompleter(model(), this);
        completer->setCompletionMode(QCompleter::PopupCompletion);
        completer->setCompletionColumn(relFieldIdx);
        setCompleter(completer);
    
        QComboBox::showPopup();
    }
    
    void MyComboBox::focusOutEvent(QFocusEvent* event) {
    
        //This code (probably) should be done differently
        if ((QApplication::focusWidget() != this) && (QApplication::focusWidget() != view()))
            setEditable(false);
        //
    
        QComboBox::focusOutEvent(event);
    }
    
    

    I don't have filtering by typing "by containing", only "by first symbols". But there is only one widget - MyComboBox. Maybe later I will make filtering in "God's regime ))
    Using - first call init(...)

    1 Reply Last reply
    0
    • VRoninV Offline
      VRoninV Offline
      VRonin
      wrote on last edited by VRonin
      #13

      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;
      }
      

      "La mort n'est rien, mais vivre vaincu et sans gloire, c'est mourir tous les jours"
      ~Napoleon Bonaparte

      On a crusade to banish setIndexWidget() from the holy land of Qt

      M 2 Replies Last reply
      3
      • VRoninV VRonin

        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;
        }
        
        M Offline
        M Offline
        michaeldev
        wrote on last edited by
        #14

        @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?

        kshegunovK JonBJ 2 Replies Last reply
        0
        • M michaeldev

          @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?

          kshegunovK Offline
          kshegunovK Offline
          kshegunov
          Moderators
          wrote on last edited by
          #15

          Looking at the code I'm pretty sure there is. Have you actually loaded it in your IDE and given it a try?

          Read and abide by the Qt Code of Conduct

          M 1 Reply Last reply
          1
          • kshegunovK kshegunov

            Looking at the code I'm pretty sure there is. Have you actually loaded it in your IDE and given it a try?

            M Offline
            M Offline
            michaeldev
            wrote on last edited by
            #16

            @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.

            1 Reply Last reply
            0
            • M michaeldev

              @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?

              JonBJ Offline
              JonBJ Offline
              JonB
              wrote on last edited by
              #17

              @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?

              M SGaistS 2 Replies Last reply
              0
              • JonBJ JonB

                @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?

                M Offline
                M Offline
                michaeldev
                wrote on last edited by
                #18

                @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?

                JonBJ kshegunovK 2 Replies Last reply
                0
                • M michaeldev

                  @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?

                  JonBJ Offline
                  JonBJ Offline
                  JonB
                  wrote on last edited by
                  #19

                  @michaeldev
                  No, I don't have an IDE or a C++ compiler.

                  1 Reply Last reply
                  0
                  • M michaeldev

                    @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?

                    kshegunovK Offline
                    kshegunovK Offline
                    kshegunov
                    Moderators
                    wrote on last edited by
                    #20

                    @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!

                    Read and abide by the Qt Code of Conduct

                    M 1 Reply Last reply
                    1
                    • kshegunovK kshegunov

                      @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!

                      M Offline
                      M Offline
                      michaeldev
                      wrote on last edited by michaeldev
                      #21

                      @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. Даже так: спасибо, друг! ))

                      1 Reply Last reply
                      0
                      • VRoninV VRonin

                        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;
                        }
                        
                        M Offline
                        M Offline
                        michaeldev
                        wrote on last edited by michaeldev
                        #22

                        @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.

                        1 Reply Last reply
                        0
                        • JonBJ JonB

                          @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?

                          SGaistS Offline
                          SGaistS Offline
                          SGaist
                          Lifetime Qt Champion
                          wrote on last edited by
                          #23

                          @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 by filterModel.

                          Interested in AI ? www.idiap.ch
                          Please read the Qt Code of Conduct - https://forum.qt.io/topic/113070/qt-code-of-conduct

                          M JonBJ 2 Replies Last reply
                          2
                          • SGaistS SGaist

                            @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 by filterModel.

                            M Offline
                            M Offline
                            michaeldev
                            wrote on last edited by
                            #24

                            @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 by filterModel.

                            It's clear.

                            1 Reply Last reply
                            0
                            • SGaistS SGaist

                              @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 by filterModel.

                              JonBJ Offline
                              JonBJ Offline
                              JonB
                              wrote on last edited by JonB
                              #25

                              @SGaist
                              My question was purely a rhetorical one! In reply to @michaeldev's

                              There 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.

                              1 Reply Last reply
                              0
                              • T Offline
                                T Offline
                                TENK228
                                wrote on last edited by
                                #26

                                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
                                
                                1 Reply Last reply
                                6
                                • V Offline
                                  V Offline
                                  viTes
                                  wrote on last edited by
                                  #27

                                  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.)

                                  1 Reply Last reply
                                  0

                                  • Login

                                  • Login or register to search.
                                  • First post
                                    Last post
                                  0
                                  • Categories
                                  • Recent
                                  • Tags
                                  • Popular
                                  • Users
                                  • Groups
                                  • Search
                                  • Get Qt Extensions
                                  • Unsolved