2011-01-28 99 views
4

我需要一个QCombox,其中的项目根据文本输入进行过滤。如果我将QCombobox设置为可编辑,用户可以插入文本并自动创建QCompleter。但项目不被过滤,我不希望用户添加新的项目。如何根据文本输入过滤PyQt QCombobox项目?

有没有可能将此功能添加到QCombobox?

回答

10

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

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_()) 
+0

THX,这正是我锁定的。 – 2011-01-28 17:24:16

+0

它像广告中那样工作。我遇到的一个小问题是,当我过滤复选框并通过鼠标点击选择一个选项时,currentIndexChanged信号不会立即发送,我必须先点击其他地方。 – ilpoldo 2011-07-14 15:09:56

8

感谢漂亮的答案,我有同样的问题。 它很好地工作,但迫使你提供一个不必要的外部模型。 我扩展了代码,以使用组合框已经提供的内部标准模型。 也有一些清理和文件已经做了...

#!/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

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

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