gpt4 book ai didi

filtering - PySide - QSortFilterProxyModel 和 QListView - indexWidget 指针在过滤时被删除

转载 作者:行者123 更新时间:2023-12-05 07:58:20 28 4
gpt4 key购买 nike

我在尝试制作自定义 QListView 时遇到问题,这里是问题所在:

我正在使用 QListView 通过 QListView.setIndexWidget(index,widget) 显示 QWidget 列表。

这工作得很好,但现在我想使用 QSortFilterProxyModel() 过滤项目模型使用 .setFilterWildcard()

效果不是很好,因为第二次过滤了模型我得到这样的错误:

RuntimeError:内部 C++ 对象 (PySide.QtGui.QLabel) 已删除。

在不使用filteringQSortFilterProxyModel 的情况下,一切正常,但似乎我遗漏了与过滤操作有关的东西, indexWidget() 在使用过滤时被删除:(

这里有一个示例代码,您可以在其中重现错误,当显示 ListView 时,按 1、2 或 3 键盘激活过滤的键(退格键将过滤设置为空以显示所有项目)

这里是重现问题的示例代码:

import PySide.QtGui as QtGui
import PySide.QtCore as QtCore


_DEFAULT_ITEM_SIZE = QtCore.QSize(100, 85)
_USER_ROLE = QtGui.QStandardItem.UserType + 1

class CustomItemWidget(QtGui.QWidget):
def __init__(self, parent=None):
super(CustomItemWidget, self).__init__(parent=parent)

#self.setAutoFillBackground(True)
self.main_layout = QtGui.QVBoxLayout(self)

self.label = QtGui.QLabel(self)

self.main_layout.addWidget(self.label)

def paintEvent(self, event):
painter = QtGui.QPainter(self)
painter.setRenderHint(QtGui.QPainter.Antialiasing)

# Default brush and pen
bg_brush = QtGui.QBrush(QtGui.QColor("#8C8C8C"))
pen = QtCore.Qt.NoPen

painter.save()
painter.setPen(pen)
painter.setBrush(bg_brush)
painter.drawRoundedRect(self.rect(), 12, 12)
painter.restore()

def setData(self, role, value):
if role == QtCore.Qt.DisplayRole:
self.label.setText(value)



class CustomItem(QtGui.QStandardItem):
def __init__(self):
super(CustomItem, self).__init__()

self.number = None
self.item_widget = CustomItemWidget()
self.setSelectable(True)

def type(self):
return _USER_ROLE

def data(self, role):
if role == QtCore.Qt.DisplayRole:
value = "DATA %s" % str(self.number)
self.item_widget.setData(role, value)

return value

if role == QtCore.Qt.SizeHintRole:
return _DEFAULT_ITEM_SIZE

return QtGui.QStandardItem.data(self, role)



class CustomItemDelegate(QtGui.QStyledItemDelegate):
def __init__(self, parent=None):
super(CustomItemDelegate, self).__init__(parent=parent)


class CustomItemModel(QtGui.QStandardItemModel):
def __init__(self, parent=None):
super(CustomItemModel, self).__init__(parent)

def flags(self, index):
return QtCore.Qt.ItemIsEnabled | \
QtCore.Qt.ItemIsSelectable | \
QtCore.Qt.ItemIsDragEnabled | \
QtCore.Qt.ItemIsDropEnabled


class CustomItemFilterProxyModel(QtGui.QSortFilterProxyModel):
def __init__(self, parent=None):
super(CustomItemFilterProxyModel, self).__init__(parent)

self.setDynamicSortFilter(True)
self.setFilterCaseSensitivity(QtCore.Qt.CaseInsensitive)
self.setFilterKeyColumn(0)


class CustomView(QtGui.QListView):
def __init__(self, parent=None):
super(CustomView, self).__init__(parent=parent)

self.setIconSize(_DEFAULT_ITEM_SIZE)
self.setMovement(QtGui.QListView.Static)
self.setSelectionMode(QtGui.QAbstractItemView.ExtendedSelection)
self.setSelectionBehavior(QtGui.QAbstractItemView.SelectItems)
self.setViewMode(QtGui.QListView.IconMode)
self.setUniformItemSizes(True)
self.setFlow(QtGui.QListView.LeftToRight)
self.setResizeMode(QtGui.QListView.Adjust)

self.data_model = CustomItemModel(self)
self.proxy_model = CustomItemFilterProxyModel(self)

self.proxy_model.setSourceModel(self.data_model)
self.setModel(self.proxy_model)

def keyPressEvent(self, event):
if event.key() == QtCore.Qt.Key_1:
self.proxy_model.setFilterWildcard("*1*")
print self.proxy_model.filterRegExp()
if event.key() == QtCore.Qt.Key_2:
self.proxy_model.setFilterWildcard("*2*")
print self.proxy_model.filterRegExp()
if event.key() == QtCore.Qt.Key_3:
self.proxy_model.setFilterWildcard("*3*")
print self.proxy_model.filterRegExp()
if event.key() == QtCore.Qt.Key_Backspace:
self.proxy_model.setFilterFixedString("")
print self.proxy_model.filterRegExp()
if event.key() == QtCore.Qt.Key_Plus:
self.addNewItem()

QtGui.QListView.keyPressEvent(self, event)

def addNewItem(self):
item = CustomItem()
item.number = self.data_model.rowCount()

self.addItem(item)

def addItem(self, item):
self.data_model.appendRow(item)
proxy_index = self.proxy_model.mapFromSource(item.index())

self.setIndexWidget(proxy_index, item.item_widget)


if __name__ == '__main__':
import sys
qapplication = QtGui.QApplication(sys.argv)

layout = QtGui.QVBoxLayout()
window = QtGui.QDialog()
window.setLayout(layout)

view = CustomView(window)
view.resize(800, 600)

layout.addWidget(view)

for i in range(0, 10):
item = CustomItem()
item.number = i
view.addItem(item)


window.show()

sys.exit(qapplication.exec_())

或此处的示例代码:

https://gist.github.com/66e29df303d1f1825a53

有人可以帮我解决这个问题吗?这是一个已知的错误 ?或者我做的完全错了 :P

预先感谢您的帮助。

最佳答案

这是一个老问题,但由于我在类似问题上苦苦挣扎了很长一段时间,这里是我找到的解决方案和可能的解释:

我没有缓存模型项上的自定义小部件,而是缓存了创建小部件所需的数据。就我而言,我想使用带有 html 的自定义标签,以便能够以不同颜色格式化部分文本。因此,我在项目上缓存了 html 字符串。

然后,在项目委托(delegate)的 initStyleOption 方法中,如果小部件尚不存在或在过滤后消失了,我将重新创建它:

  label = self.parent().indexWidget(modelIndex)
if not label:
label = CustomLabel(item.html)
self.parent().setIndexWidget(modelIndex, label)

过滤删除缓存在item上的widget的原因如下,我认为:widget只能“存在”在一个地方。当它作为 indexWidget 放置时,它“存在”在 View 的一行中,不再存在于模型的项目中。当过滤从 View 中删除行时,这些行上的小部件将被删除。 - 一个糟糕的解释,但如果我忘记克隆元素,在使用 JavaScript 操作 html 元素时,我经常会遇到类似的惊喜。

关于filtering - PySide - QSortFilterProxyModel 和 QListView - indexWidget 指针在过滤时被删除,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/24995936/

28 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com