如何让自定义 QCompleter 与自定义项目委托一起工作?

时间:2021-01-27 04:14:11

标签: python pyside2 qlineedit qstyleditemdelegate qcompleter

我有一个自定义的 qcompleter(匹配字符串的任何部分)和一个自定义的 QStyledItemDelegate(在 qcompleter 返回的下拉选项上显示不同的格式)应用于 QLineEdit,它们都单独工作,但是 QStyledItemDelegate 没有当我同时应用它们时不起作用。

import sys
from PySide2.QtWidgets import QApplication, QMainWindow, QLineEdit, QCompleter, QStyledItemDelegate
from PySide2.QtCore import Qt, QSortFilterProxyModel, QStringListModel
from PySide2.QtGui import QColor, QPalette

Qcompleter 项目委托:

class CompleterItemDelegate(QStyledItemDelegate):
    def initStyleOption(self, option, index):
        super(CompleterItemDelegate, self).initStyleOption(option, index)
        option.backgroundBrush = QColor("red")
        option.palette.setBrush(QPalette.Text, QColor("blue"))
        option.displayAlignment = Qt.AlignCenter

自定义 QCompleter:

class CustomQCompleter(QCompleter):
    def __init__(self, parent=None):
        super(CustomQCompleter, self).__init__(parent)
        self.local_completion_prefix = ""
        self.source_model = None

    def setModel(self, model):
        self.source_model = model
        super(CustomQCompleter, self).setModel(self.source_model)

    def updateModel(self):
        local_completion_prefix = self.local_completion_prefix
        class InnerProxyModel(QSortFilterProxyModel):
            def filterAcceptsRow(self, sourceRow, sourceParent):
                index0 = self.sourceModel().index(sourceRow, 0, sourceParent)
                searchStr = local_completion_prefix.lower()
                searchStr_list = searchStr.split()
                modelStr = self.sourceModel().data(index0,Qt.DisplayRole).lower()
                for string in searchStr_list:
                    if not string in modelStr:
                        return False
                return True

        proxy_model = InnerProxyModel()
        proxy_model.setSourceModel(self.source_model)
        super(CustomQCompleter, self).setModel(proxy_model)

    def splitPath(self, path):
        self.local_completion_prefix = str(path)
        self.updateModel()
        return ""

主要内容:

class MainWindow(QMainWindow):
    def __init__(self):
        super(MainWindow, self).__init__()

        model = QStringListModel()
        model.setStringList(['Tom', 'Tommy Stevens', 'Steven'])

        # ITEM DELEGATE ONLY - WORKS
        # completer = QCompleter()
        # completer.setModel(model)
        # delegate = CompleterDelegate()
        # completer.popup().setItemDelegate(delegate)

        # QCOMPLETER DELEGATE ONLY - WORKS
        # completer = CustomQCompleter(self)
        # completer.setModel(model)

        # ITEM DELEGATE AND QCOMPLETER DELEGATE - ITEM DELEGATE DOESNT WORK
        completer = CustomQCompleter(self)
        completer.setModel(model)
        delegate = CompleterItemDelegate()
        completer.popup().setItemDelegate(delegate)

        self.lineEdit = QLineEdit()
        self.lineEdit.setCompleter(completer)

        self.setCentralWidget(self.lineEdit)
        self.show()

if __name__ == '__main__':
    app  = QApplication(sys.argv)
    p = MainWindow()
    p.show()
    sys.exit(app.exec_())
  1. 有没有办法让这段代码正常工作?
  2. 是否有更好的方法来实现为 qcompleter 选择完成规则和格式化弹出结果?

2 个答案:

答案 0 :(得分:0)

如果模型是在之后设置的,则在弹出窗口上设置委托将不起作用,因为 setModel() 还会调用 setPopup(),后者又会设置一个 new item delegate

所以,你要么:

  • 确保在完成器上设置模型之后设置委托;
  • 子类化完成器并覆盖 setModel(),方法是调用基本实现,然后然后恢复委托,或者 complete() 通过恢复委托 before基本实现调用;请注意,这在您的情况下不起作用,因为您在 updateModel() 中调用了基本实现,这显然会忽略覆盖;

答案 1 :(得分:0)

移动

props.history.push('/')

进入 CustomQCompleter updateModel 函数解决了musicamante 指出的问题。