2

PyQt4でUIを作っています。それはtreeViewを持っており、私はそれを扱いたいと思っています。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.dragMoveEventメソッドとメソッドはどちらも、からQTreeView.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あることがわかり、ピクルできないため失敗します。この結果、オブジェクトは適切に初期化されず、ドラッグ イベントによって無視されます。treeModeldumps(data)dataPyMimeData

于 2011-12-08T20:14:28.503 に答える