使用QSortFilterProxyModel自定义QCompleter

时间:2019-07-07 19:03:13

标签: python pyqt pyqt5

我想为QLineEditQCompleter启用通配符匹配。如果字符串模型是['abc', 'cba'],则当我键入ab*a*时,它应该显示abc。以下是我编写的代码,但仍表现得像常规匹配。知道我该如何解决吗?

from PyQt5.QtWidgets import *
from PyQt5.QtCore import *
from PyQt5.QtGui import *
import sys, random


class MyCompleter(QCompleter):
    def __init__(self, *args):
        super().__init__(*args)

    def setModel(self, model):
        self.proxyModel = QSortFilterProxyModel()
        self.proxyModel.setSourceModel(model)
        super().setModel(self.proxyModel)

    def updatePattern(self, patternStr):
        self.proxyModel.setFilterWildcard(patternStr)


class MyMain(QMainWindow):
    def __init__(self, *args):
        super().__init__(*args)
        self.initUI()

    def initUI(self):
        model = QStringListModel(['abc', 'cba'])

        completer = MyCompleter()
        completer.setModel(model)

        searchBar = QLineEdit(self)
        searchBar.setCompleter(completer)
        searchBar.textChanged.connect(lambda wildcard: completer.updatePattern(wildcard))

        vLayout = QVBoxLayout()
        vLayout.addWidget(searchBar, alignment=Qt.AlignCenter)

        self.setCentralWidget(QWidget())
        self.centralWidget().setLayout(vLayout)


if __name__ == '__main__':
    app = QApplication(sys.argv)
    mm = MyMain()
    mm.show()
    sys.exit(app.exec_())

1 个答案:

答案 0 :(得分:0)

尝试一下:

import sys
from PyQt5.QtWidgets import *
from PyQt5.QtCore import *
from PyQt5.QtGui import *


class LineEdit(QLineEdit):                                     # +++
    def __init__(self, *args, **kwargs):
        QLineEdit.__init__(self, *args, **kwargs)
        self.multipleCompleter = None

    def keyPressEvent(self, event):
        QLineEdit.keyPressEvent(self, event)
        if not self.multipleCompleter:
            return
        c = self.multipleCompleter

        if self.text() == "":                                    
            return
        c.setCompletionPrefix(self.cursorWord(self.text()))      

        if len(c.completionPrefix()) < 1:
            c.popup().hide()
            return
        c.complete()

    def cursorWord(self, sentence):
        p = sentence.rfind(" ")
        if p == -1:
            return sentence
        return sentence[p + 1:]

    def insertCompletion(self, text):                             
        p = self.text().rfind(" ")                                
        if p == -1:
            self.setText(text)                                    
        else:
            self.setText(self.text()[:p+1]+ text)           

    def setMultipleCompleter(self, completer):
        self.multipleCompleter = completer
        self.multipleCompleter.setWidget(self)
        completer.activated.connect(self.insertCompletion)


class MyCompleter(QCompleter):
    def __init__(self, *args):
        super().__init__(*args)

    def setModel(self, model):
        self.proxyModel = QSortFilterProxyModel()
        self.proxyModel.setSourceModel(model)
        super().setModel(self.proxyModel)

    def updatePattern(self, patternStr):
        print(f"patternStr-> {patternStr}")
        self.proxyModel.setFilterWildcard(patternStr)


class MyMain(QMainWindow):
    def __init__(self, *args):
        super().__init__(*args)
        self.initUI()

    def initUI(self):
        model = QStringListModel(['abc', 'cba'])

        completer = MyCompleter()
        completer.setModel(model)

#        searchBar = QLineEdit(self)
#        searchBar.setCompleter(completer)
#        searchBar.textChanged.connect(lambda wildcard: completer.updatePattern(wildcard))

        searchBar = LineEdit(self)                              # +++
        completer.setCaseSensitivity(Qt.CaseInsensitive)        # +++
        searchBar.setMultipleCompleter(completer)               # +++

        vLayout = QVBoxLayout()
        vLayout.addWidget(searchBar, alignment=Qt.AlignCenter)
        self.setCentralWidget(QWidget())
        self.centralWidget().setLayout(vLayout)


if __name__ == '__main__':
    app = QApplication(sys.argv)
    mm = MyMain()
    mm.show()
    sys.exit(app.exec_())

enter image description here