qt – 如何将自定义QStandardItem拖放到QListView中

我试图使用自定义QStandardItem在两个QListViews之间拖放工作.
除了this document之外,我找不到我需要的在线信息,这有点帮助但是现在我卡住了.

当我使用QStandardItem来保存我的数据时,从一个QListView拖放到另一个工作正常,但是当我使用自定义项目时遇到麻烦,因为接收模型/视图在删除自定义项目时创建QStandardItem.

理想情况下,我可以告诉接收模型使用我的自定义项目作为默认项目,否则只是做它的事情,但我想它不会那么容易?!
似乎一切都是开箱即用的,除了QStandardItem的下降,而不是我的自定义项目,所以我希望我不必重新发明(拖放)轮只是为了得到那一部分对?!

如果我必须重新发明轮子并实现视图的dropEvent然后手动附加传入的项目,我会遇到另一个奇怪的问题.这是我的测试代码(包括一些用于解码我在网上找到的丢弃数据的代码):

from PySide import QtCore, QtGui

class MyItem(QtGui.QStandardItem):
    '''This is the item I'd like to drop into the view'''

    def __init__(self, parent=None):
        super(MyItem, self).__init__(parent)
        self.testAttr = 'test attribute value'

class ReceivingView(QtGui.QListView):
    '''Custom view to show the problem - i.e. the dropEvent produces a QStandardItem rather than MyItem'''

    def __init__(self, parent=None):
        super(ReceivingView, self).__init__(parent)

    def decode_data(self, bytearray):
        '''Decode byte array to receive item back'''
        data = []
        item = {}

        ds = QtCore.QDataStream(bytearray)
        while not ds.atEnd():

            row = ds.readInt32()
            column = ds.readInt32()

            map_items = ds.readInt32()
            for i in range(map_items):

                key = ds.readInt32()

                value = MyItem()
                ds >> value
                #item[QtCore.Qt.ItemDataRole(key)] = value
                item = value

            data.append(item)

        return data

    def dropEvent(self, event):    
        byteArray = event.mimeData().data('application/x-qabstractitemmodeldatalist')
        for item in self.decode_data(byteArray):
            copiedItem = MyItem(item)
            newItem = MyItem('hello')
            print copiedItem
            print newItem
            self.model().appendRow(copiedItem) # the copied item does not show up, even though it is appended to the model
            #self.model().appendRow(newItem) # this works as expected

        event.accept()

        item = self.model().item(self.model().rowCount() - 1)
        print item

if __name__ == "__main__":
    import sys

    app = QtGui.QApplication(sys.argv)

    mw = QtGui.QMainWindow()
    w = QtGui.QSplitter()
    mw.setCentralWidget(w)

    # models
    model1 = QtGui.QStandardItemModel()
    model2 = QtGui.QStandardItemModel()

    for i in xrange(5):
        #item = QtGui.QStandardItem()
        item = MyItem()
        item.setData(str(i), QtCore.Qt.DisplayRole)
        model1.appendRow(item)

    # views
    view1 = QtGui.QListView()
    view2 = ReceivingView()
    for v in (view1, view2):
        v.setViewMode(QtGui.QListView.IconMode)

    view1.setModel(model1)
    view2.setModel(model2) 

    w.addWidget(view1)
    w.addWidget(view2)

    mw.show()
    mw.raise_()
    sys.exit(app.exec_())

我们的想法是解码丢弃的数据以接收原始项目,然后制作副本并将该副本附加到接收模型.
自定义项目将附加到模型中,但在放置事件后不会显示在视图中.如果我在drop drop中创建一个新的自定义项并追加它,一切都按预期工作.

所以我对上面提到了两个问题:

>这种方法是否能够实现自定义项目的删除或是否更容易?
>为什么上述代码中自定义项的副本在删除后不会显示在视图中?

提前致谢,
坦率

看起来你想要setItemPrototype.这为模型提供了一个项目工厂,因此它会在必要时隐式使用你的自定义类.

您需要做的就是在item类中重新实现clone():

class MyItem(QtGui.QStandardItem):
    '''This is the item I'd like to drop into the view'''

    def __init__(self, parent=None):
        super(MyItem, self).__init__(parent)
        self.testAttr = 'test attribute value'

    def clone(self):
        return MyItem()

然后将该类的实例设置为接收模型上的原型:

    # models
    model1 = QtGui.QStandardItemModel()
    model2 = QtGui.QStandardItemModel()
    model2.setItemPrototype(MyItem())

你可以忘记所有数据流的东西.

PS:

我想我应该指出,Qt显然对在项目生命周期中可能已设置的任何python数据属性一无所知,因此在拖放操作期间传输项目时不会序列化这些属性.如果要保留这样的数据,请将setData()与自定义角色一起使用:

class MyItem(QtGui.QStandardItem):
    _TestAttrRole = QtCore.Qt.UserRole + 2

    def clone(self):
        item = MyItem()
        item.testArr = 'test attribute value'
        return item

    @property
    def testAttr(self):
        return self.data(self._TestAttrRole)

    @testAttr.setter
    def testAttr(self, value):
        self.setData(value, self._TestAttrRole)
https://stackoverflow.com/questions/39584001/how-to-drop-a-custom-qstandarditem-into-a-qlistview

转载注明原文:qt – 如何将自定义QStandardItem拖放到QListView中