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

How to get a Custom QCompleter to work with a custom item delegate?

我有一个自定义的 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 的完成规则和格式化弹出结果?

如果之后设置模型,则在弹出窗口中设置委托将不起作用,因为 setModel() also calls setPopup(), which in turn sets a new item delegate

所以,你要么:

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

移动

delegate = CompleterItemDelegate()
self.popup().setItemDelegate(delegate)

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