Custom dropEvent in TreeWidget: how to find target item (tree item under mouse?)
-
PyQt4 / Python 3
I'm dragging text from a listwidget to a treewidget, but I need to override the default drag-and-drop behavior because I'm using a custom TreeWidgetItem class. I cannot figure out how to find the tree item currently under the mouse during a dropEvent. Any help would be much appreciaed!
A simple sample code is below:
@
import sys
from PyQt4.QtGui import *
from PyQt4.QtGui import *class EditScreen(QWidget):
def init(self):
super(EditScreen, self).init()
self.initUI()def initUI(self): global tree global listbox self.vbox = QVBoxLayout() self.hbox = QHBoxLayout() listbox = QListWidget() listbox.setDragEnabled(True) listbox.setSelectionMode(QAbstractItemView.ExtendedSelection) for x in range(1,10): item = 'Thing' + str(x) listbox.addItem(item) tree = MyTreeWidget() tree.setAcceptDrops(True) tree.setSelectionMode(QAbstractItemView.ExtendedSelection) for x in range(1,5): addnewtreeitem = MyTreeItemClass('Category ' + str(x), toplevel=True) addnewtreeitem.setExpanded(True) question = 'Double-clicking a category in the treewidget (right) calls my "addHere" function,' question += '\nwhich adds the selected items (from the left) to the treeview after messing with them a bit.' question += '\n\nI would like to drag items over from the listwidget, with exactly the same functionality as the double-click.' question += '\nbut I do not understand how to find the target item (underneath the mouse) during a dropEvent.' question += '\nI need this target item in order to call my "addHere" function.' question += '\n\nI cannot use the standard drag-and-drop behavior because I must use a custom TreeWidgetItem class.' questionlabel = QLabel(question) self.hbox.addWidget(listbox) self.hbox.addWidget(tree) self.vbox.addWidget(questionlabel) self.vbox.addLayout(self.hbox) self.setLayout(self.vbox) self.setWindowTitle('How can I make drag-and-drop perform my "addHere" function?') self.show() def keyPressEvent(self, e): if e.key() == Qt.Key_Delete: #print('pressed delete key') tree.delButtonPressed()
class MyTreeWidget(QTreeWidget):
def init(self):
QTreeWidget.init(self)
self.itemDoubleClicked.connect(self.addHere)def delButtonPressed(self): for item in self.selectedItems(): if item.deletable: item.parent.removeChild(item) MyTreeItemClass.child_list.remove(item) def addHere(self, clickeditem, column): global listbox for x in listbox.selectedItems(): if clickeditem.can_add_here == True: print('Adding item(s) here', clickeditem.treetext) itemtext = x.text() newtreeitem = MyTreeItemClass(itemtext, parent=clickeditem) clickeditem.setExpanded(False) # need to use false to counter-act the double-clicking action? else: print('cannot add to this item')
class MyTreeItemClass(QTreeWidgetItem):
global tree
toplevel_list = []
child_list = []
def init(self, treetext, toplevel=False, parent=None):
self.treetext = treetext
QTreeWidgetItem.init(self, [self.treetext])if parent: self.parentitem=parent if toplevel == True: self.deletable = False self.can_add_here = True MyTreeItemClass.toplevel_list.append(self) tree.addTopLevelItem(self) else: self.deletable = True self.can_add_here = False itemnum = int(self.treetext[-1]) if itemnum % 2 == 0: self.setForeground(0,QBrush(Qt.blue)) else: self.setForeground(0,QBrush(Qt.red)) if itemnum % 3 == 0: self.setBackground(0,QBrush(Qt.lightGray)) if itemnum % 4 == 0: self.setBackground(0,QBrush(Qt.black)) self.setForeground(0,QBrush(Qt.white)) MyTreeItemClass.child_list.append(self) self.parentitem.addChild(self)
def main():
app = QApplication(sys.argv)
editscreen = EditScreen()
sys.exit(app.exec_())main()
@ -
"QTreeWidget.itemAt":http://doc.qt.digia.com/qt/qtreewidget.html#itemAt is what your looking for. Try adding the following to your MyTreeWidget class:
@
def dropEvent(self, e):
item=self.itemAt(e.pos())
if item: self.addHere(item)
e.accept()
@You might also want to do the following in the constructor to stop the default expand behavior:
@
self.setExpandsOnDoubleClick(False)
@Hope this helps ;o)