2011-01-28 86 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、それはまさに私がロックしていたものです。 –

+0

広告として扱われます。 1つのマイナーな問題は、チェックボックスにフィルタをかけてマウスクリックで1つのオプションを選択すると、currentIndexChangedシグナルがすぐに送信されないため、他の場所を最初にクリックする必要があることです。 – ilpoldo

+0

これをPySideで動作させるために追加したいと思います。最初に親の引数でコンプリータを初期化してから、 'self.completer.setModel(self.pFilterModel)'でモデルを設定する必要がありました。これはナッツを運転していましたが、私は最終的にこれを文書化しましたので、私はこれを文書化しました[ここ](http://stackoverflow.com/questions/24456460/qcombobox-with-autocompletion-works-in-pyqt4-but- pysideではない)。 – flutefreak7

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

これはまさに私が探していたものでした、ありがとう! – Cryptite

4

どちらの答えは、しかし、彼らは活性化を起こさない選択をクリックし、次に入力して、コンボボックス内のオプションをフィルタリングすることを特徴と小さなバグがあり、正確です発射する信号。これは、の後の行にself.activated[str].emit(self.itemText(index))on_completer_activatedに置くことで解決できます。

コンプリータからアイテムを選択すると、アクティブになった信号が発生します。この信号には、クリックされたアイテムの名前が含まれています。

関連する問題