PyQt树拖放事件。奇怪的行动

时间:2013-09-05 04:52:09

标签: python qt drag-and-drop tree pyqt

我有一个Widget窗口包含两个QtTree Widgets。当我将项目从一个树窗口小部件拖放到另一个树窗口小部件时,它工作正常。但是,如果我拖动一个项目并将其拖放到相同的树窗口小部件(这不是所需的行为,因此我禁用代码中的接受删除),树窗口小部件将忽略我的下一次鼠标按下事件。

要重现此问题,请运行代码

1.从左侧树中拖动一个项目并将其放在相同的树小部件中。

2.单击左侧树窗口小部件上的任何项目,您将注意到没有任何更改

3.再次单击相同或其他项目,选择将更改。

另外,请在放下项目后点击小费用图标。无论你多少次点击小费用图标,都没有活动。

from PyQt4 import QtGui, QtCore
import cPickle

class MyTreeItem(QtGui.QTreeWidgetItem):
    def __init__(self, parent=None):
        super(MyTreeItem, self).__init__(parent)
        self.setFlags(QtCore.Qt.ItemIsDragEnabled | QtCore.Qt.ItemIsSelectable | QtCore.Qt.ItemIsUserCheckable | QtCore.Qt.ItemIsEnabled | QtCore.Qt.ItemIsDropEnabled)


    def getPath(self):
        """
        Rebuild path from the tree.
        """
        if isinstance(self.parent(), MyTreeItem):
           path = '{0}/{1}'.format(self.parent().getPath() ,str(self.text(0)))
        #The top level item
        else:
           path = '/{0}'.format(str(self.text(0)))

        return path


    def getParents(self):
        """
        Get all the parents to the top level.
        """
        parents = []

        while self:
            self = self.parent()
            if isinstance(self, MyTreeItem):
                parents.append(self)

        return parents


    def getChildren(self):
        """
        Get all the children(flatten).
        """
        children = []
        if not self:
            return children

        childrenCount = self.childCount()

        if childrenCount == 0:
            return children

        for idx in range(childrenCount):
            citem = self.child(idx)
            if citem:
                children.append(citem)
                children.extend(citem.getChildren())

        return children

class MyTreeWidget(QtGui.QTreeWidget):
    def __init__(self, parent = None):
        super(MyTreeWidget, self).__init__(parent)
        self.setDragEnabled(True)
        self.setAcceptDrops(True)
        self.setHeaderLabels(["Select Members"])
        self.setSelectionMode(QtGui.QAbstractItemView.ExtendedSelection)
        self.mousePressPos = QtCore.QPoint(0,0)


    def mousePressEvent(self, event):
        super(MyTreeWidget, self).mousePressEvent(event)
        #if event.button() == QtCore.Qt.LeftButton:
        #    self.mousePressPos = event.pos()


    def mouseMoveEvent(self, event):
        super(MyTreeWidget, self).mouseMoveEvent(event)
        #length = (event.pos() - self.mousePressPos).manhattanLength()

        #if length < QtGui.QApplication.startDragDistance():
        #    return

        self.setAcceptDrops(False)
        drag = QtGui.QDrag(self)
        mime_data = QtCore.QMimeData()
        passme = []
        for sel in self.selectedItems():
            dnddict = {}
            dnddict['disp'] = sel.getPath()
            dnddict['val'] = sel.getPath()

            passme.append(dnddict)

        bstream = cPickle.dumps(passme)
        mime_data.setData("application/x-ltreedata", bstream)
        drag.setMimeData(mime_data)
        self.setAcceptDrops(True)
        action = drag.exec_()


    def mouseReleaseEven(self, event):
        self.setAcceptDrop(True)
        event.accept()


    def dragMoveEvent(self, event):
        if event.mimeData().hasFormat("application/x-ltreedata"):
            event.accept()
        else:
            event.ignore()


    def dragEnterEvent(self, event):
        if event.mimeData().hasFormat("application/x-ltreedata"):
            event.accept()
        else:
            event.ignore()


    def dropEvent(self, event):
        if event.source() == self:
            event.ignore()
        else:
            for item in event.source().selectedItems():
                print item.text(0)

    def addItems(self, itemList):
        """
        Take a list of path-like strings
        """
        for item in itemList:
            self.addItem(item)


    def addItem(self, item):
        """
        Convert each item to a tree item
        """
        joints = item.strip('/').split('/')

        joint = None
        while joints:
            joint = self.addTreeJoint(joints.pop(0), joint)


    def addTreeJoint(self, jointName, parent=None):
        """
        Add item to the tree widget
        """
        returnItem = None
        #If it the top of the tree
        if not parent:
            #Find existing item
            for item in self.findItems(QtCore.QString(jointName),QtCore.Qt.MatchExactly):
                if jointName == item.text(0):

                    return item
            #Create new top level item
            returnItem = MyTreeItem(self)
            returnItem.setText(0, jointName)

        #We search all the children of this tree level and figure out if
        #we need to create a new tree item.
        else:
            for idx in range(parent.childCount()):
                if parent.childCount() == 0:
                    break
                if jointName == parent.child(idx).text(0):
                    return parent.child(idx)

            #Create new item
            returnItem = MyTreeItem(parent)
            returnItem.setText(0, jointName)

        return returnItem


class GeometrySelector(QtGui.QWidget):
    accepted = QtCore.pyqtSignal(list)
    def __init__(self, parent = None):
        super(GeometrySelector, self).__init__(parent)


        self.treeWidget = MyTreeWidget(self)
        self.treeWidget.addItems(get_objs())

        button = QtGui.QPushButton('Add Members', self)
        button.setFocusPolicy(QtCore.Qt.NoFocus)
        button.clicked.connect(self.cb_accept)

        filterLabel = QtGui.QLabel(self)
        filterLabel.setText('Filter:')
        filterField = QtGui.QLineEdit(self)
        filterField.textChanged.connect(self.filterChanged)


        filterBox = QtGui.QHBoxLayout()
        filterBox.addWidget(filterLabel)
        filterBox.addWidget(filterField)

        mainLayout = QtGui.QGridLayout()
        mainLayout.addWidget(self.treeWidget,0,0)
        mainLayout.addLayout(filterBox,1,0)
        mainLayout.addWidget(button,2,0)
        self.setLayout(mainLayout)

        pal = self.palette()
        pal.setColor(QtGui.QPalette.Base, QtGui.QColor(80, 80, 80))
        pal.setColor(QtGui.QPalette.Text, QtGui.QColor(230, 230, 230))
        self.setPalette(pal)
        button.setPalette(pal)
        self.treeWidget.setPalette(pal)


    def filterChanged(self, filterStr):
        showedItem = []

        matchFlag = QtCore.Qt.MatchFlags(QtCore.Qt.MatchContains | QtCore.Qt.MatchRecursive | QtCore.Qt.MatchRegExp)
        allItems = self.treeWidget.findItems(QtCore.QString("*"),matchFlag)

        for item in allItems:
            if item in showedItem:
                continue

            if str(filterStr) in str(item.text(0)):
                showedItem.append(item)
                showedItem.extend(item.getParents())
                showedItem.extend(item.getChildren())

        for item in allItems:
            if item in showedItem:
                item.setHidden(False)
            else:
                item.setHidden(True)


    def cb_accept(self):
        selected_things = [str(item.getPath()) for item in self.treeWidget.selectedItems()]
        self.accepted.emit(selected_things)


class myWidget(QtGui.QWidget):
    def __init__(self, parent = None):
        super(myWidget, self).__init__(parent)
        s1 = GeometrySelector(self)
        s2 = GeometrySelector(self)

        filterBox = QtGui.QHBoxLayout()
        filterBox.addWidget(s1)
        filterBox.addWidget(s2)

        self.setLayout(filterBox)


def get_objs():
    obj = ['/home/someone/something/somewhere','/home/someone/something/somewhere1','/home/someone/something/somewhere2',
           '/home/someoneA/something/somewhere','/home/someoneA/somethingA/somewhere','/home/someoneA/somethingA/somewhere',
           '/home/someoneC/something/somewhere','/home/someoneC/something/somewhereC','/home/someoneC/something/somewhereA']
    return obj


def openUI():
    app = QtGui.QApplication.instance()
    if app is None:
        app = QtGui.QApplication([])
    dialog = myWidget()
    dialog.show()
    app.exec_()
openUI()

1 个答案:

答案 0 :(得分:0)

这只是一个猜测虽然在这里似乎是合适的。

一种奇怪的现象可能只发生在较旧的PC中,因为存储的某些比特似乎比其他比特更具持久性。这些位似乎更难以擦除或替换其他位。一个众所周知的文本编辑器(TextPad)会锁定并拒绝做任何事情,直到循环出去。它每隔几分钟自动保存一次。最终它似乎阻止了它恢复文件位置结束的能力。记忆问题似乎超出了当前的日期和时间。希望这可以帮助。