[Python] PyQt6 QTreeView Drag & Drop Indicator Not Showing After Overriding Drag Events

Discussão em 'Python' iniciado por Stack, Janeiro 1, 2025.

  1. Stack

    Stack Membro Participativo

    I'm trying to implement drag-and-drop functionality in a QTreeView widget in PyQt6. I have enabled drag-and-drop support using setDragEnabled(True), setAcceptDrops(True), and setDropIndicatorShown(True) to show the drop indicator when dragging items.

    However, after overriding the built-in drag and drop event functions (dragEnterEvent, dragMoveEvent, and dropEvent), the drop indicator (the line between rows where the dragged item can be dropped) no longer appears.

    How can I restore or properly display the drop indicator between items after overriding the drag-and-drop event functions in PyQt6's QTreeView?

    Here is the code I have so far:

    from PyQt6 import QtCore, QtGui, QtWidgets

    class ObjectTree(QtWidgets.QTreeView):
    def __init__(self):
    super().__init__()

    self.model = QtGui.QStandardItemModel()
    self.setModel(self.model)

    # Enable drag and drop
    self.setDragEnabled(True)
    self.setAcceptDrops(True)
    self.setDropIndicatorShown(True) # Show drop indicator

    self._populate_tree()

    def _populate_tree(self):
    root_item = QtGui.QStandardItem('Root')
    self.model.appendRow(root_item)
    for i in range(10):
    child_item = QtGui.QStandardItem(f'Child {i + 1}')
    root_item.appendRow(child_item)

    def dragEnterEvent(self, event):
    if event.mimeData().hasFormat('application/x-item'):
    event.acceptProposedAction()
    else:
    event.ignore()

    def dragMoveEvent(self, event):
    if event.mimeData().hasFormat('application/x-item'):
    event.acceptProposedAction()
    else:
    event.ignore()

    def dropEvent(self, event):
    if event.mimeData().hasFormat('application/x-item'):
    data = event.mimeData().data('application/x-item')
    stream = QtCore.QDataStream(data, QtCore.QIODevice.OpenModeFlag.ReadOnly)
    item_name = stream.readQString()
    print(f"Dropped item: {item_name}")
    event.acceptProposedAction()

    def startDrag(self, event):
    selected_indexes = self.selectedIndexes()
    if selected_indexes:
    selected_item = self.model.itemFromIndex(selected_indexes[0])
    mime_data = QtCore.QMimeData()
    data = QtCore.QByteArray()
    stream = QtCore.QDataStream(data, QtCore.QDataStream.OpenModeFlag.WriteOnly)
    stream.writeQString(selected_item.text())
    mime_data.setData('application/x-item', data)

    drag = QtGui.QDrag(self)
    drag.setMimeData(mime_data)
    drag.exec(event)

    class MainWindow(QtWidgets.QMainWindow):
    def __init__(self):
    super().__init__()

    self.object_tree = ObjectTree()
    self.setCentralWidget(self.object_tree)

    self.setWindowTitle("PyQt6 Drag and Drop Example")
    self.setGeometry(100, 100, 600, 400)

    if __name__ == "__main__":
    app = QtWidgets.QApplication([])
    window = MainWindow()
    window.show()
    app.exec()

    Continue reading...

Compartilhe esta Página