使用QSortFilterProxyModel删除QAbstractListModel中的PyQt QWidget

时间:2013-07-25 10:02:53

标签: pyqt qwidget qsortfilterproxymodel qabstractlistmodel

我需要使用小部件填充listview,然后使用自定义代理过滤器。 如果没有过滤器,它可以很好地工作,当它处于活动状态时,它似乎会删除附加到模型的小部件。

它显示正常显示所有项目,过滤工作但是当擦除过滤器时,当隐藏的小部件应该再次显示后会抛出错误:

custom_widget.setGeometry(option.rect) RuntimeError:基础C / C ++对象已被删除

尝试不使用QVariant并进入internalPointer路线但在相同位置断开。

感谢您一看!

设定:

def __init__(self, *args): 
    QtGui.QWidget.__init__(self, *args) 

    # create temp data
    self.list_data = []
    for x in xrange(500):
        widget = ListItemWidget(text=str(x), parent=self)
        self.list_data.append((str(x), widget)) # testing to put in inmut tuple

    # create listviewmodel
    self.lm = ListViewModel(parent=self)

    # create listview widget
    self.lv = QtGui.QListView()

    # create filter proxy     
    self.proxy_model = ListViewFilterProxyModel()
    self.proxy_model.setFilterPattern('')
    self.proxy_model.setSourceModel(self.lm)

    # set model of listview to filter proxy
    self.lv.setModel(self.proxy_model)

    # set delegate for column 0
    self.lv.setItemDelegateForColumn(0, CustomWidgetDelegate(self.lv))

    self.lm.updateData(self.list_data)
    self.proxy_model.invalidate()

    self.connect(self.filter_edit, QtCore.SIGNAL("textChanged(QString)"), self.update_filter)

    def update_filter(self, pattern):
        self.proxy_model.setFilterPattern(pattern)
        self.proxy_model.invalidate()

自定义小部件

class ListItemWidget(QtGui.QWidget):
    def __init__(self, text=None, parent=None):
        QtGui.QWidget.__init__(self)      
        self.text = text

    @QtCore.pyqtProperty(QtCore.QString)
    def text(self):
        return self.__text

    @text.setter
    def text(self, value):
        self.__text = value

委托绘制视图

    class CustomWidgetDelegate(QtGui.QItemDelegate):
        def __init__(self, parent=None):
            super(CustomWidgetDelegate, self).__init__(parent)

        def paint(self, painter, option, index):   
            custom_widget = index.model().data(index, QtCore.Qt.DisplayRole).toPyObject()[1]
>>>>>>      custom_widget.setGeometry(option.rect)
            if not self.parent().indexWidget(index):
                self.parent().setIndexWidget(index, custom_widget)

列表视图模型:

class ListViewModel(QtCore.QAbstractListModel): 
    def __init__(self, parent=None, *args): 
        QtCore.QAbstractListModel.__init__(self, parent, *args)
        self.listdata = []

    def rowCount(self, parent=QtCore.QModelIndex()): 
        return len(self.listdata) 

    def data(self, index, role): 
        if role == QtCore.Qt.SizeHintRole:
            return QtCore.QSize(80, 80)
        if index.isValid() and role == QtCore.Qt.DisplayRole:
            return QtCore.QVariant(self.listdata[index.row()]).toPyObject()
        return QtCore.QVariant()    

    def updateData(self, listdata):
        self.listdata = listdata
        index = len(self.listdata)
        return True

最后是过滤器代理模型:

class ListViewFilterProxyModel(QtGui.QSortFilterProxyModel):
    def __init__(self, parent=None):
        self.filter_str = None
        QtGui.QSortFilterProxyModel.__init__(self, parent)

    def setFilterPattern(self, pattern):
        self.filter_str = QtCore.QString(pattern)

    def filterAcceptsRow(self, sourceRow, sourceParent):
        if self.filter_str is None:
            return True
        index = self.sourceModel().index(sourceRow, 0, sourceParent)  
        # just testing on the str here...
        text = index.data().toPyObject()[0]
        if not str(self.filter_str) in text:
            return False
        return True

0 个答案:

没有答案