Skip to content Skip to sidebar Skip to footer

PyQt Drop Event Without Subclassing?

This python pyqt code works how I intended. But, I don't like having to subclass QLineEdit so that I can detect file drop onto my QLineEdit field. I like the more elegant and simp

Solution 1:

No need to subclass: you can use an event filter:

import sys
from PyQt4 import QtGui, QtCore

class testDialog(QtGui.QDialog):
    def __init__(self, parent=None):
        super(testDialog, self).__init__(parent)

        form = QtGui.QFormLayout()
        form.setHorizontalSpacing(0)

        self.myedit = QtGui.QLineEdit()
        self.myedit.setDragEnabled(True)
        self.myedit.setAcceptDrops(True)
        self.myedit.installEventFilter(self)

        form.addWidget(self.myedit)

        self.setLayout(form)
        self.setGeometry(300, 300, 400, 0)
        self.setWindowTitle('drop test')

        self.myedit.textChanged.connect(self.editchange)   # new style signal slot connections

    @QtCore.pyqtSlot(str)   # int represent the column value
    def editchange(self,data):
        print "editchange:", data.toLatin1()

    def eventFilter(self, object, event):
        if (object is self.myedit):
            if (event.type() == QtCore.QEvent.DragEnter):
                if event.mimeData().hasUrls():
                    event.accept()   # must accept the dragEnterEvent or else the dropEvent can't occur !!!
                    print "accept"
                else:
                    event.ignore()
                    print "ignore"
            if (event.type() == QtCore.QEvent.Drop):
                if event.mimeData().hasUrls():   # if file or link is dropped
                    urlcount = len(event.mimeData().urls())  # count number of drops
                    url = event.mimeData().urls()[0]   # get first url
                    object.setText(url.toString())   # assign first url to editline
                    #event.accept()  # doesnt appear to be needed
            return False # lets the event continue to the edit
        return False

if __name__ == "__main__":

    app = QtGui.QApplication([])
    dl = testDialog()
    dl.exec_()
    sys.exit(app.closeAllWindows())

Solution 2:

I had the same issue today and has able to get it solved in a different (and maybe less orthodoxy) way. So, what can also be done is to remap the dropEvent function from the tree to another name, either internal to the instance or to the class that owns the instance, and assign a new custom function the dropEvent. This new function can call or not the original one, depending if you want to keep some of the functionallities, or just rewrite everything. Here is a snippet:

import sys
from PyQt5.QtWidgets import QTreeView
from PyQt5.QtGui import QDropEvent

class Demo: 

    def __init__(self):
        self.tree = QTreeView()
        self.tree.setDragEnabled(True)
        self.tree.setAcceptDrops(True)
        self.tree.original_dropEvent = self.dataView.dropEvent
        self.tree.dropEvent = self._dataview_dropevent

    def _tree_dropevent(self, event: QDropEvent):
        # do stuff ...
        self.tree.original_dropEvent(event)
        # maybe more stuff ..

.


Post a Comment for "PyQt Drop Event Without Subclassing?"