PyQt:在 QStyledItemDelegate 中使用 QTextEdit 作为编辑器
Posted
技术标签:
【中文标题】PyQt:在 QStyledItemDelegate 中使用 QTextEdit 作为编辑器【英文标题】:PyQt: Using QTextEdit as editor in a QStyledItemDelegate 【发布时间】:2015-06-03 08:46:44 【问题描述】:我正在寻找在我的 QStyledItemDelegate 中使用多行文本编辑的简洁方式。通过返回 QTextEdit 实例,createEditor 实现非常简单
def createEditor(self, parent, option, index):
return QtGui.QTextEdit("Some text")
但是setModelData
期望从QWidget
派生的编辑小部件作为参数而不是QTextEdits
基QScrollArea
。 Qt 文档还 tells me(至少在 PyQt Doc 中)setModelData
函数试图从 QWidget UserData 字段中获取数据。但是如果没有从QWidget
派生的编辑小部件,则无法设置数据。目前它会抛出一个AttributeError
,因为它在编辑器上找不到text()
。
是否有一些行之有效的方法来使用非 QWidget 编辑器?还是我只是缺少一些小部件来做到这一点?
目前我通过使用来自toPlainText()
的QTextEdit
数据实例化QLineEdit
并将其传递给setModelData
来快速解决此问题。非常哈克!我也可以使用鸭子类型并在QTextEdit
派生类上实现text()
方法。但仍然不是一个好方法,不是吗?在 C++ 中有什么方法可以做到这一点?
【问题讨论】:
是的,你是对的。我改变了它。我也犯了一个错误,声称QTextEdit
不是从QWidget
派生的——实际上它是通过QFrame
派生的
【参考方案1】:
item-delegate 的最低要求非常简单。您需要做的就是重新实现createEditor
、setEditorData
和setModelData
:
class Delegate(QStyledItemDelegate):
def createEditor(self, parent, options, index):
return QtGui.QTextEdit(parent)
def setEditorData(self, editor, index):
editor.setText(index.data())
def setModelData(self, editor, model, index):
model.setData(index, editor.toPlainText())
使用此解决方案,可以轻松地通过同一个委托支持多种不同类型的编辑器。例如,isinstance
检查可用于决定使用哪种类型的编辑器:
def setModelData(self, editor, model, index):
if isinstance(editor, QtGui.QTextEdit):
model.setData(index, editor.toPlainText())
elif isinstance(editor, QtGui.QComboBox):
model.setData(index, editor.currentText())
else:
super(Delegate, self).setModelData(editor, model, index)
有关一些 C++ 示例,请参阅 Model/View Overview 中的 A Simple Delegate 部分。
【讨论】:
这是一种非常直接的方法。谢谢。我希望这不会陷入一般性讨论,但是通过跳过基类超级函数我是否有可能错过发出一些信号或其他一些调用? @DonHolio。重新实现的函数完全按照它们的名字所暗示的那样做,仅此而已。如果不是这种情况,Qt 的设计将是非常糟糕的。QItemDelegate
专门设计为高度可定制的(它的大部分功能都是虚拟的)。我已经澄清了我的答案,以便分别处理多种编辑器类型的想法。【参考方案2】:
所以我花了一些时间深入研究了这个问题。实际上有多种更清洁的解决方案:
实现属性
我通过在 QTextEdit
的子类上实现 QProperty 使其正常工作,它将 text
属性作为 USER 属性添加到对象中。这是我的代码:
class DelegatableTextEdit(QtGui.QTextEdit):
@pyqtProperty(str, user=True)
def text(self):
return self.toPlainText()
@text.setter
def text(self, text):
self.setText(text)
使用工厂
似乎有一种方法可以通过使用 Delegates setDefaultFactory()
方法来解决此问题,该方法然后采用 QItemEditorFactory
,该方法已使用 registerEditor()
函数注册了自定义编辑器创建者。您可以在那里注册 QItemEditorCreatorBase
类的自定义实现,该类具有覆盖的 createWidget
方法(如果需要,还可以使用 valuePropertyName
函数)。不过这个我还没试过
我决定采用第一个解决方案,它只需要自定义 QTextEdit
和覆盖的 createEditor()
函数。两者都应该在 C++ 中工作
【讨论】:
以上是关于PyQt:在 QStyledItemDelegate 中使用 QTextEdit 作为编辑器的主要内容,如果未能解决你的问题,请参考以下文章