2

我用 PyQt4 制作了一个 UI。它有一个treeView,我想处理它。树视图由模型库组成。我在 .py 文件中创建一个数据并将其导入。所以,我可以在我的 treeView 中看到数据树。但是我不能拖放它,所以不能改变顺序。我参考了一些文章,因此将其添加到我的脚本中,但它们无法正常工作。我种植了一些“印刷品”,所以我追逐了我的问题。我发现当拖动一个项目时,它会传输到 MIME 数据。但是当它被丢弃时,我找不到任何输出。脚本似乎没有调用“dropMimeData”方法。如何修复我的脚本?

from PyQt4 import QtCore, QtGui
from setting import *
from copy import deepcopy
from cPickle import dumps, load, loads
from cStringIO import StringIO

class PyMimeData(QtCore.QMimeData):
    MIME_TYPE = QtCore.QString('text/plain')

    def __init__(self, data=None):
        QtCore.QMimeData.__init__(self)

        self._local_instance = data

        if data is not None:
            try:
                pdata = dumps(data)
            except:
                return

            self.setData(self.MIME_TYPE, dumps(data.__class__) + pdata)

    @classmethod
    def coerce(cls, md):
        if isinstance(md, cls):
            return md
        if not md.hasFormat(cls.MIME_TYPE):
            return None
        nmd = cls()
        nmd.setData(cls.MIME_TYPE, md.data())

        return nmd

    def instance(self):
        if self._local_instance is not None:
            return self._local_instance

        io = StringIO(str(self.data(self.MIME_TYPE)))

        try:
            load(io)
            return load(io)
        except:
            pass

        return None

    def instanceType(self):
        if self._local_instance is not None:
            return self._local_instance.__class__

        try:
            return loads(str(self.data(self.MIME_TYPE)))
        except:
            pass
        return None

class treeItem(QtGui.QStandardItem):
    def __init__(self, data, parent=None):
        super(treeItem, self).__init__(data)
        self.parentItem = parent
        self.itemData = data
        self.childItems = []

    def appendChild(self, item):
        self.childItems.append(item)

    def parent(self):
        return self.parentItem

    def childAtRow(self, row): 
        return self.childItems[row]

    def rowOfChild(self, child):       
        for i, item in enumerate(self.childItems): 
            if item == child: 
                return i 
        return -1 


class treeModel(QtGui.QStandardItemModel):
    def __init__(self, name, parent=None):
        super(treeModel, self).__init__(parent)
        self.headerName = name
        self.childItems = []

    def appendChild(self, item):
        self.childItems.append(item)

    def removeRowAll(self):
        pass

    def addItemList(self, parent, elements):
        for text, children in elements:
            item = treeItem(text, parent)
            self.addItems(parent, item)

            if children:
                self.addItemList(item, children)

    def addItems(self, parent, inputItem):
        parent.appendRow(inputItem)
        parent.appendChild(inputItem)

    def headerData(self, section, orientation, role):
        if orientation == QtCore.Qt.Horizontal and role == QtCore.Qt.DisplayRole:
            return self.headerName


    def supportedDropActions(self):
        return QtCore.Qt.MoveAction | QtCore.Qt.CopyAction

    def flags(self, index): 
        defaultFlags = QtCore.QAbstractItemModel.flags(self, index) 

        if index.isValid():    
            return QtCore.Qt.ItemIsEditable | QtCore.Qt.ItemIsDragEnabled | QtCore.Qt.ItemIsDropEnabled | defaultFlags 

        else:     
            return QtCore.Qt.ItemIsDropEnabled | defaultFlags 

    def mimeTypes(self): 
        types = QtCore.QStringList() 
        types.append('text/plain') 
        return types 

    def mimeData(self, index):
        node = self.nodeFromIndex(index[0])
        mimeData = PyMimeData(node)        
        return mimeData

    def dropMimeData(self, mimedata, action, row, column, parentIndex):
        print mimedata, action, row, column, parentIndex
        if action == QtCore.Qt.IgnoreAction:
            return True

        dragNode = mimedata.instance()
        print dragNode
        parentNode = self.nodeFromIndex(parentIndex)

        # copy of node being moved
        newNode = deepcopy(dragNode)
        print newNode
        newNode.setParent(parentNode)
        self.insertRow(len(parentNode)-1, parentIndex)
        self.emit(QtCore.SIGNAL("dataChanged(QtCore.QModelIndex,QtCore.QModelIndex)"), parentIndex, parentIndex)
        return True

def nodeFromIndex(self, index):        
    ##return index.internalPointer() if index.isValid() else self.root        
    return index.model() if index.isValid() else self.parent()

def insertRow(self, row, parent): 
    return self.insertRows(row, 1, parent) 

def insertRows(self, row, count, parent): 
    self.beginInsertRows(parent, row, (row + (count - 1))) 
    self.endInsertRows() 
    return True 

def removeRow(self, row, parentIndex): 
    return self.removeRows(row, 1, parentIndex) 

def removeRows(self, row, count, parentIndex): 
    self.beginRemoveRows(parentIndex, row, row) 
    node = self.nodeFromIndex(parentIndex) 
    node.removeChild(row) 
    self.endRemoveRows() 
    return True

这里添加的脚本是ui创建(上面的脚本是在这个脚本中导入的)

class RigControlWindow(QtGui.QMainWindow, Ui_MainWindow):
    def __init__(self, parent = getMayaWindow()):
        super(RigControlWindow, self).__init__(parent)
        self.setupUi(self)

        self.bodyrig_treelist.setDragEnabled(1)
        self.bodyrig_treelist.setAcceptDrops(1)
        self.bodyrig_treelist.setDropIndicatorShown(1)
        self.bodyrig_treelist.setDragDropMode(QtGui.QAbstractItemView.InternalMove)
        QtCore.QObject.connect(self.finalize_button, QtCore.SIGNAL("clicked()"), self.AddData_treeList)

    def AddData_treeList(self):
        self.localtreeModel = treeModel("objects")
        self.bodyrig_treelist.setModel(self.localtreeModel)
        self.localtreeModel.addItemList(self.localtreeModel, data)

和数据是

data = [("root",[("upper",[("hand",[]),
                           ("head",[])
                           ]),
                 ("lower",[("leg",[]),
                           ("foot",[])
                           ])
                 ])
        ]
4

1 回答 1

2

QTreeView.dragMoveEventQTreeView.dragEnterEvent方法都检查返回的对象,event.mimeData()看它是否可以返回模型支持的任何格式的数据(即返回的那些model.mimeTypes())。

但是您的PyMimeData子类不支持任何格式,因为它从未成功设置传递给其构造函数的数据。

问题位于PyMimeData.__init__

...
try:
    pdata = dumps(data)
except:
    return
self.setData(self.MIME_TYPE, dumps(data.__class__) + pdata)

data是从方法传入的treeModel.mimeData

def mimeData(self, index):
    node = self.nodeFromIndex(index[0])
    mimeData = PyMimeData(node)
    return mimeData

但是,如果您检查类型,data/node您会发现它是一个treeModel实例,因此dumps(data)会失败,因为data无法腌制。因此,PyMimeData对象未正确初始化,因此被拖动事件忽略。

于 2011-12-08T20:14:28.503 回答