【问题标题】:How do I Filter the PyQt QCombobox Items based on the text input?如何根据文本输入过滤 PyQt QCombobox 项?
【发布时间】:2011-06-17 03:59:24
【问题描述】:

我需要一个 QCombox,它根据文本输入过滤项目。如果我将 QCombobox 设置为可编辑,则用户可以插入文本并自动创建 QCompleter。但是项目没有被过滤,我不希望用户添加新项目。

是否有可能将此功能添加到 QCombobox?

【问题讨论】:

    标签: python qt pyqt qcombobox


    【解决方案1】:

    试试这个代码,这是我在我的一个项目中使用的东西

    import sys
    from PyQt4.QtGui import QComboBox, QApplication, QCompleter, QSortFilterProxyModel, QStandardItemModel, QStandardItem
    from PyQt4.QtCore import Qt
    
    class ExtendedCombo( QComboBox ):
        def __init__( self,  parent = None):
            super( ExtendedCombo, self ).__init__( parent )
    
            self.setFocusPolicy( Qt.StrongFocus )
            self.setEditable( True )
            self.completer = QCompleter( self )
    
            # always show all completions
            self.completer.setCompletionMode( QCompleter.UnfilteredPopupCompletion )
            self.pFilterModel = QSortFilterProxyModel( self )
            self.pFilterModel.setFilterCaseSensitivity( Qt.CaseInsensitive )
    
    
    
            self.completer.setPopup( self.view() )
    
    
            self.setCompleter( self.completer )
    
    
            self.lineEdit().textEdited[unicode].connect( self.pFilterModel.setFilterFixedString )
            self.completer.activated.connect(self.setTextIfCompleterIsClicked)
    
        def setModel( self, model ):
            super(ExtendedCombo, self).setModel( model )
            self.pFilterModel.setSourceModel( model )
            self.completer.setModel(self.pFilterModel)
    
        def setModelColumn( self, column ):
            self.completer.setCompletionColumn( column )
            self.pFilterModel.setFilterKeyColumn( column )
            super(ExtendedCombo, self).setModelColumn( column )
    
    
        def view( self ):
            return self.completer.popup()
    
        def index( self ):
            return self.currentIndex()
    
        def setTextIfCompleterIsClicked(self, text):
          if text:
            index = self.findText(text)
            self.setCurrentIndex(index)
    
    if __name__ == "__main__":
        app = QApplication(sys.argv)
    
        model = QStandardItemModel()
    
        for i,word in enumerate( ['hola', 'adios', 'hello', 'good bye'] ):
            item = QStandardItem(word)
            model.setItem(i, 0, item)
    
    
    
        combo = ExtendedCombo()
        combo.setModel(model)
        combo.setModelColumn(0)
    
        combo.show()
    
        sys.exit(app.exec_())
    

    【讨论】:

    • THX,这正是我锁定的目的。
    • 它像宣传的那样工作。我遇到的一个小问题是,当我过滤复选框并通过鼠标单击选择一个选项时,不会立即发送 currentIndexChanged 信号,我必须先单击其他位置。
    • 我还想补充一点,为了让它在 PySide 中工作,我必须先用父参数初始化完成器,然后用 self.completer.setModel(self.pFilterModel) 设置模型。这让我发疯,但我在写一个问题时终于想通了,所以我记录了这个here
    【解决方案2】:

    在组合框内搜索。终于有了一个好的解决方案。谢谢你们!!这对我帮助很大。

    这里是调整后的 PyQt5 代码:

    #!/usr/bin/env python
    # -*- coding: utf-8 -*-
    from PyQt5 import QtCore, QtGui, QtWidgets
    from PyQt5.QtCore import Qt, QSortFilterProxyModel
    from PyQt5.QtWidgets import QCompleter, QComboBox
    
    class ExtendedComboBox(QComboBox):
        def __init__(self, parent=None):
            super(ExtendedComboBox, self).__init__(parent)
    
            self.setFocusPolicy(Qt.StrongFocus)
            self.setEditable(True)
    
            # add a filter model to filter matching items
            self.pFilterModel = QSortFilterProxyModel(self)
            self.pFilterModel.setFilterCaseSensitivity(Qt.CaseInsensitive)
            self.pFilterModel.setSourceModel(self.model())
    
            # add a completer, which uses the filter model
            self.completer = QCompleter(self.pFilterModel, self)
            # always show all (filtered) completions
            self.completer.setCompletionMode(QCompleter.UnfilteredPopupCompletion)
            self.setCompleter(self.completer)
    
            # connect signals
            self.lineEdit().textEdited.connect(self.pFilterModel.setFilterFixedString)
            self.completer.activated.connect(self.on_completer_activated)
    
    
        # on selection of an item from the completer, select the corresponding item from combobox 
        def on_completer_activated(self, text):
            if text:
                index = self.findText(text)
                self.setCurrentIndex(index)
                self.activated[str].emit(self.itemText(index))
    
    
        # on model change, update the models of the filter and completer as well 
        def setModel(self, model):
            super(ExtendedComboBox, self).setModel(model)
            self.pFilterModel.setSourceModel(model)
            self.completer.setModel(self.pFilterModel)
    
    
        # on model column change, update the model column of the filter and completer as well
        def setModelColumn(self, column):
            self.completer.setCompletionColumn(column)
            self.pFilterModel.setFilterKeyColumn(column)
            super(ExtendedComboBox, self).setModelColumn(column)    
    
    
    if __name__ == "__main__":
        import sys
        from PyQt5.QtWidgets import QApplication
        from PyQt5.QtCore import QStringListModel
    
        app = QApplication(sys.argv)
    
        string_list = ['hola muchachos', 'adios amigos', 'hello world', 'good bye']
    
        combo = ExtendedComboBox()
    
        # either fill the standard model of the combobox
        combo.addItems(string_list)
    
        # or use another model
        #combo.setModel(QStringListModel(string_list))
    
        combo.resize(300, 40)
        combo.show()
    
        sys.exit(app.exec_())
    

    【讨论】:

      【解决方案3】:

      感谢您的好回答,我遇到了同样的问题。 它工作得很好,但迫使您提供一个外部模型,这是不必要的。 我扩展了代码以使用组合框已经提供的内部标准模型。 还进行了一些清理和记录...

      #!/usr/bin/env python
      # -*- coding: utf-8 -*-
      from PyQt4.QtCore import Qt
      from PyQt4.QtGui import QCompleter, QComboBox, QSortFilterProxyModel
      
      class ExtendedComboBox(QComboBox):
          def __init__(self, parent=None):
              super(ExtendedComboBox, self).__init__(parent)
      
              self.setFocusPolicy(Qt.StrongFocus)
              self.setEditable(True)
      
              # add a filter model to filter matching items
              self.pFilterModel = QSortFilterProxyModel(self)
              self.pFilterModel.setFilterCaseSensitivity(Qt.CaseInsensitive)
              self.pFilterModel.setSourceModel(self.model())
      
              # add a completer, which uses the filter model
              self.completer = QCompleter(self.pFilterModel, self)
              # always show all (filtered) completions
              self.completer.setCompletionMode(QCompleter.UnfilteredPopupCompletion)
              self.setCompleter(self.completer)
      
              # connect signals
              self.lineEdit().textEdited[unicode].connect(self.pFilterModel.setFilterFixedString)
              self.completer.activated.connect(self.on_completer_activated)
      
      
          # on selection of an item from the completer, select the corresponding item from combobox 
          def on_completer_activated(self, text):
              if text:
                  index = self.findText(text)
                  self.setCurrentIndex(index)
      
      
          # on model change, update the models of the filter and completer as well 
          def setModel(self, model):
              super(ExtendedComboBox, self).setModel(model)
              self.pFilterModel.setSourceModel(model)
              self.completer.setModel(self.pFilterModel)
      
      
          # on model column change, update the model column of the filter and completer as well
          def setModelColumn(self, column):
              self.completer.setCompletionColumn(column)
              self.pFilterModel.setFilterKeyColumn(column)
              super(ExtendedComboBox, self).setModelColumn(column)
      
      
      
      if __name__ == "__main__":
          import sys
          from PyQt4.QtGui import QStringListModel, QApplication
      
          app = QApplication(sys.argv)
      
          string_list = ['hola muchachos', 'adios amigos', 'hello world', 'good bye']
      
          combo = ExtendedComboBox()
      
          # either fill the standard model of the combobox
          combo.addItems(string_list)
      
          # or use another model
          #combo.setModel(QStringListModel(string_list))
      
          combo.resize(300, 40)
          combo.show()
      
          sys.exit(app.exec_())
      

      【讨论】:

        【解决方案4】:

        发布的两个答案都是正确的,但是它们有一个小错误,其中通过键入然后单击选择来过滤组合框中的选项不会导致激活信号触发。您可以通过将self.activated[str].emit(self.itemText(index)) 放在on_completer_activated 中,在self.setCurrentIndex(index) 之后的行上来解决此问题。

        当您从完成程序中选择一个项目时,这会触发一个激活信号,其中包含被单击项目的名称。

        【讨论】:

          【解决方案5】:

          如果有人感兴趣:pyqt5 的相同代码

              #!/usr/bin/python
              
              import sys
              
              from PyQt5.QtWidgets import QComboBox, QApplication, QCompleter
              from PyQt5.QtCore import QSortFilterProxyModel, Qt
              from PyQt5.Qt import QStringListModel
              
              
              class ExtendedComboBox(QComboBox):
                  def __init__(self, parent=None):
                      super(ExtendedComboBox, self).__init__(parent)
              
                      self.setFocusPolicy(Qt.StrongFocus)
                      self.setEditable(True)
              
                      # add a filter model to filter matching items
                      self.pFilterModel = QSortFilterProxyModel(self)
                      self.pFilterModel.setFilterCaseSensitivity(Qt.CaseInsensitive)
                      self.pFilterModel.setSourceModel(self.model())
              
                      # add a completer, which uses the filter model
                      self.completer = QCompleter(self.pFilterModel, self)
                      # always show all (filtered) completions
                      self.completer.setCompletionMode(QCompleter.UnfilteredPopupCompletion)
                      self.setCompleter(self.completer)
              
                      # connect signals
                      self.lineEdit().textEdited[str].connect(self.pFilterModel.setFilterFixedString)
                      self.completer.activated.connect(self.on_completer_activated)
              
              
                  # on selection of an item from the completer, select the corresponding item from combobox
                  def on_completer_activated(self, text):
                      if text:
                          index = self.findText(text)
                          self.setCurrentIndex(index)
                          self.activated[str].emit(self.itemText(index))
              
              
                  # on model change, update the models of the filter and completer as well
                  def setModel(self, model):
                      super(ExtendedComboBox, self).setModel(model)
                      self.pFilterModel.setSourceModel(model)
                      self.completer.setModel(self.pFilterModel)
              
              
                  # on model column change, update the model column of the filter and completer as well
                  def setModelColumn(self, column):
                      self.completer.setCompletionColumn(column)
                      self.pFilterModel.setFilterKeyColumn(column)
                      super(ExtendedComboBox, self).setModelColumn(column)
              
              
              
              if __name__ == "__main__":
              
              
                  app = QApplication(sys.argv)
              
                  string_list = ['hola muchachos', 'adios amigos', 'hello world', 'good bye']
              
                  combo = ExtendedComboBox()
              
                  # either fill the standard model of the combobox
                  combo.addItems(string_list)
              
                  # or use another model
                  #combo.setModel(QStringListModel(string_list))
              
                  combo.resize(300, 40)
                  combo.show()
              
                  sys.exit(app.exec_())
          

          【讨论】:

            猜你喜欢
            • 1970-01-01
            • 1970-01-01
            • 1970-01-01
            • 2020-10-07
            • 2018-07-19
            • 1970-01-01
            • 2014-05-12
            • 2021-12-18
            • 2015-11-16
            相关资源
            最近更新 更多