我有一个 Widget 窗口包含两个 QtTree Widget。当我将项目从一个树小部件拖放到另一个树小部件时,它工作正常。但是,如果我将一个项目拖放到同一个树小部件(这不是所需的行为,所以我在代码中禁用了接受放置),树小部件会忽略我的下一次鼠标按下事件。
要重现该问题,请运行代码并
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()