ウィジェット ウィンドウに 2 つの QtTree ウィジェットが含まれています。あるツリー ウィジェットから別のツリー ウィジェットにアイテムをドラッグ アンド ドロップすると、問題なく動作します。しかし、項目をドラッグして同じツリー ウィジェットにドロップすると (これは望ましい動作ではないため、コードでドロップの受け入れを無効にします)、ツリー ウィジェットは次のマウス プレス イベントを無視します。
問題を再現するには、コードを実行してください。
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()