简体   繁体   中英

drag a file into QtGui.QLineEdit() to set url text

I've made a QtGui.LineEdit() widget in a python script using pySide Qt bindings and I'd like to be able to drag a file from the desktop into the QLineEdit to set the text in the QLineEdit to the path of the file. I've done QLineEdit.setDragEnabled(True) to enable drag and drop operations but I'm a bot lost about how to procede from here. Does anyone know how to achieve this?

Using the eventFilter mechanism, mentioned above, does work, when used like this:

from PyQt4.QtCore import QObject, QEvent


class QLineEditDropHandler(QObject):    
    def eventFilter(self, watched, event):
        if event.type() == QEvent.DragEnter:
            # we need to accept this event explicitly to be able to receive QDropEvents!
            event.accept()
        if event.type() == QEvent.Drop:
            md = event.mimeData()
            if md.hasUrls():
                obj.setText(url.toLocalFile())
                return True
        return super().eventFilter(watched, event)

Now, one can use the drop handler on any line edit without subclassing:

lineEdit.installEventFilter(QLineEditDropHandler(self))

Usually, for events you can use the QObject.eventFilter and QObject.installEventFilter to do intercept events and process them. However, it does not seem to work for QDrag/QDrop events (and if I'm wrong on this - someone else please let me know as I've about pulled all my hair out trying to figure the way to get it to work with filtering).

The best way I know how to do it, you have to subclass the QLineEdit and overload the dragEnterEvent, dragMoveEvent and dropEvent methods to check to see if what is being dragged into your class is valid. Something like:

    from PySide.QtGui import QLineEdit

    class FileEdit(QLineEdit):
        def __init__( self, parent ):
            super(FileEdit, self).__init__(parent)

            self.setDragEnabled(True)

        def dragEnterEvent( self, event ):
            data = event.mimeData()
            urls = data.urls()
            if ( urls and urls[0].scheme() == 'file' ):
                event.acceptProposedAction()

        def dragMoveEvent( self, event ):
            data = event.mimeData()
            urls = data.urls()
            if ( urls and urls[0].scheme() == 'file' ):
                event.acceptProposedAction()

        def dropEvent( self, event ):
            data = event.mimeData()
            urls = data.urls()
            if ( urls and urls[0].scheme() == 'file' ):
                # for some reason, this doubles up the intro slash
                filepath = str(urls[0].path())[1:]
                self.setText(filepath)

a slightly improved version (i hope) of Erics answer would be a short implementation of an injector that enables adding drag&drop functionality to exsiting objet. this helped me while designing with QtDesigner -

from PyQt4.QtGui import QLineEdit

# reference taken from : http://stackoverflow.com/questions/11872141/drag-a-file-into-qtgui-qlineedit-to-set-url-text

class lineEdit_dragFile_injector():
    def __init__(self, lineEdit, auto_inject = True):
        self.lineEdit = lineEdit
        if auto_inject:
            self.inject_dragFile()

    def inject_dragFile( self ):
        self.lineEdit.setDragEnabled(True)
        self.lineEdit.dragEnterEvent = self._dragEnterEvent
        self.lineEdit.dragMoveEvent = self._dragMoveEvent
        self.lineEdit.dropEvent = self._dropEvent

    def _dragEnterEvent( self, event ):
        data = event.mimeData()
        urls = data.urls()
        if ( urls and urls[0].scheme() == 'file' ):
            event.acceptProposedAction()

    def _dragMoveEvent( self, event ):
        data = event.mimeData()
        urls = data.urls()
        if ( urls and urls[0].scheme() == 'file' ):
            event.acceptProposedAction()

    def _dropEvent( self, event ):
        data = event.mimeData()
        urls = data.urls()
        if ( urls and urls[0].scheme() == 'file' ):
            # for some reason, this doubles up the intro slash
            filepath = str(urls[0].path())[1:]
            self.lineEdit.setText(filepath)

save the above in a separated file - (eg file_lineEdit.py) and then use it the following way - #usage example:

#in the main APP file, just add:

import file_lineEdit            

  ...

if __name__ == "__main__":
    app = QApplication(sys.argv)
    window = QDialog()
    ui = Ui_Dialog()
    ui.setupUi(window)
    file_lineEdit.lineEdit_dragFile_injector(ui.lineEdit)
    file_lineEdit.lineEdit_dragFile_injector(ui.lineEdit_2)
    file_lineEdit.lineEdit_dragFile_injector(ui.lineEdit_3)

    window.show()
    sys.exit(app.exec_())

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM