PySide2 自动完成:自定义结果
PySide2 AutoComplete: Customize the Result
我正在使用 QCompleter 在 QLineEdit 小部件上实现自动完成:
from PySide2 import QtGui
from PySide2.QtCore import Qt
from PySide2.QtGui import QStandardItem
from PySide2.QtWidgets import QCompleter, QWidget, QLineEdit, QFormLayout, QApplication
class SuggestionPlaceModel(QtGui.QStandardItemModel):
def __init__(self, parent=None):
super(SuggestionPlaceModel, self).__init__(parent)
def search(self, text):
self.clear()
data = [{'text': f"{text} {i}"} for i in range(10)]
for i, row in enumerate(data):
item = QStandardItem(row['text'])
self.appendRow(item)
class Completer(QCompleter):
def splitPath(self, path):
self.model().search(path)
return super(Completer, self).splitPath(path)
class Widget(QWidget):
def __init__(self, parent=None):
super(Widget, self).__init__(parent)
self._model = SuggestionPlaceModel(self)
completer = Completer(self)
completer.setCaseSensitivity(Qt.CaseInsensitive)
completer.setModel(self._model)
lineedit = QLineEdit()
lineedit.setCompleter(completer)
lay = QFormLayout(self)
lay.addRow("Location: ", lineedit)
if __name__ == '__main__':
import sys
app = QApplication(sys.argv)
w = Widget()
w.show()
sys.exit(app.exec_())
结果如下:
问题:如何自定义 SuggestionPlaceModel
class 以便搜索结果可以包括图标、水平分隔符、不同的字体、不同的字体大小等?
一个可能的解决方案是在设置图标的地方使用自定义委托,在这种情况下html您可以使用支持富文本的QLabel。
import random
from PySide2 import QtCore, QtGui, QtWidgets
class Delegate(QtWidgets.QStyledItemDelegate):
def initStyleOption(self, option, index):
super(Delegate, self).initStyleOption(option, index)
option.text = ""
def paint(self, painter, option, index):
if isinstance(option.widget, QtWidgets.QAbstractItemView):
option.widget.openPersistentEditor(index)
super(Delegate, self).paint(painter, option, index)
def createEditor(self, parent, option, index):
editor = QtWidgets.QLabel(index.data(), parent)
editor.setContentsMargins(0, 0, 0, 0)
editor.setText(index.data(QtCore.Qt.UserRole))
return editor
class SuggestionPlaceModel(QtGui.QStandardItemModel):
def search(self, text):
self.clear()
for i in range(10):
html = f"{text}-{i} <b>Stack</b> <i>Overflow</i>"
plain = QtGui.QTextDocumentFragment.fromHtml(html).toPlainText()
pixmap = QtGui.QPixmap(128, 128)
pixmap.fill(QtGui.QColor(*random.sample(range(255), 4)))
item = QtGui.QStandardItem(plain)
item.setData(html, QtCore.Qt.UserRole)
item.setIcon(QtGui.QIcon(pixmap))
self.appendRow(item)
class Completer(QtWidgets.QCompleter):
def splitPath(self, path):
self.model().search(path)
return super(Completer, self).splitPath(path)
class Widget(QtWidgets.QWidget):
def __init__(self, parent=None):
super(Widget, self).__init__(parent)
self._model = SuggestionPlaceModel(self)
completer = Completer(self)
completer.setCaseSensitivity(QtCore.Qt.CaseInsensitive)
completer.setModel(self._model)
delegate = Delegate(completer.popup())
completer.popup().setItemDelegate(delegate)
lineedit = QtWidgets.QLineEdit()
lineedit.setCompleter(completer)
lay = QtWidgets.QFormLayout(self)
lay.addRow("Location: ", lineedit)
if __name__ == "__main__":
import sys
app = QtWidgets.QApplication(sys.argv)
w = Widget()
w.show()
sys.exit(app.exec_())
我正在使用 QCompleter 在 QLineEdit 小部件上实现自动完成:
from PySide2 import QtGui
from PySide2.QtCore import Qt
from PySide2.QtGui import QStandardItem
from PySide2.QtWidgets import QCompleter, QWidget, QLineEdit, QFormLayout, QApplication
class SuggestionPlaceModel(QtGui.QStandardItemModel):
def __init__(self, parent=None):
super(SuggestionPlaceModel, self).__init__(parent)
def search(self, text):
self.clear()
data = [{'text': f"{text} {i}"} for i in range(10)]
for i, row in enumerate(data):
item = QStandardItem(row['text'])
self.appendRow(item)
class Completer(QCompleter):
def splitPath(self, path):
self.model().search(path)
return super(Completer, self).splitPath(path)
class Widget(QWidget):
def __init__(self, parent=None):
super(Widget, self).__init__(parent)
self._model = SuggestionPlaceModel(self)
completer = Completer(self)
completer.setCaseSensitivity(Qt.CaseInsensitive)
completer.setModel(self._model)
lineedit = QLineEdit()
lineedit.setCompleter(completer)
lay = QFormLayout(self)
lay.addRow("Location: ", lineedit)
if __name__ == '__main__':
import sys
app = QApplication(sys.argv)
w = Widget()
w.show()
sys.exit(app.exec_())
结果如下:
问题:如何自定义 SuggestionPlaceModel
class 以便搜索结果可以包括图标、水平分隔符、不同的字体、不同的字体大小等?
一个可能的解决方案是在设置图标的地方使用自定义委托,在这种情况下html您可以使用支持富文本的QLabel。
import random
from PySide2 import QtCore, QtGui, QtWidgets
class Delegate(QtWidgets.QStyledItemDelegate):
def initStyleOption(self, option, index):
super(Delegate, self).initStyleOption(option, index)
option.text = ""
def paint(self, painter, option, index):
if isinstance(option.widget, QtWidgets.QAbstractItemView):
option.widget.openPersistentEditor(index)
super(Delegate, self).paint(painter, option, index)
def createEditor(self, parent, option, index):
editor = QtWidgets.QLabel(index.data(), parent)
editor.setContentsMargins(0, 0, 0, 0)
editor.setText(index.data(QtCore.Qt.UserRole))
return editor
class SuggestionPlaceModel(QtGui.QStandardItemModel):
def search(self, text):
self.clear()
for i in range(10):
html = f"{text}-{i} <b>Stack</b> <i>Overflow</i>"
plain = QtGui.QTextDocumentFragment.fromHtml(html).toPlainText()
pixmap = QtGui.QPixmap(128, 128)
pixmap.fill(QtGui.QColor(*random.sample(range(255), 4)))
item = QtGui.QStandardItem(plain)
item.setData(html, QtCore.Qt.UserRole)
item.setIcon(QtGui.QIcon(pixmap))
self.appendRow(item)
class Completer(QtWidgets.QCompleter):
def splitPath(self, path):
self.model().search(path)
return super(Completer, self).splitPath(path)
class Widget(QtWidgets.QWidget):
def __init__(self, parent=None):
super(Widget, self).__init__(parent)
self._model = SuggestionPlaceModel(self)
completer = Completer(self)
completer.setCaseSensitivity(QtCore.Qt.CaseInsensitive)
completer.setModel(self._model)
delegate = Delegate(completer.popup())
completer.popup().setItemDelegate(delegate)
lineedit = QtWidgets.QLineEdit()
lineedit.setCompleter(completer)
lay = QtWidgets.QFormLayout(self)
lay.addRow("Location: ", lineedit)
if __name__ == "__main__":
import sys
app = QtWidgets.QApplication(sys.argv)
w = Widget()
w.show()
sys.exit(app.exec_())