将文件拖入QtGui.QLineEdit()以设置url文本

时间:2012-08-08 19:52:36

标签: python drag-and-drop pyside

我使用pySide Qt绑定在python脚本中创建了一个QtGui.LineEdit()小部件,我希望能够将文件从桌面拖到QLineEdit中,将QLineEdit中的文本设置为路径的文件。我已经完成了QLineEdit.setDragEnabled(True)来启用拖放操作,但我对于如何从这里进行操作失去了机器人。有谁知道如何实现这个目标?

3 个答案:

答案 0 :(得分:4)

使用上面提到的eventFilter机制确实有效,如下所示:

from PyQt4.QtCore import QObject, QEvent


class QLineEditDropHandler(QObject):

    def __init__(self, parent=None):
        QObject.__init__(self, parent)

    def eventFilter(self, obj, 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():
                for url in md.urls():
                    obj.setText(url.path())
                    break
            event.accept()
        return QObject.eventFilter(self, obj, event)

现在,可以在没有子类化的任何行编辑中使用drop handler:

lineEdit.installEventFilter(QLineEditDropHandler(self))

答案 1 :(得分:2)

通常,对于事件,您可以使用QObject.eventFilter和QObject.installEventFilter来拦截事件并处理它们。然而,它似乎不适用于QDrag / QDrop事件(如果我错了 - 别人请告诉我,因为我已经把我所有的头发拉出来试图想办法让它与它一起工作滤波)。

我知道如何操作的最佳方式是,您必须继承QLineEdit并重载dragEnterEvent,dragMoveEvent和dropEvent方法以检查拖入您的类的内容是否有效。类似的东西:

    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)

答案 2 :(得分:2)

一个略微改进的版本(我希望)的Erics答案将是一个简短的注入器实现,可以添加拖放功能到现有的objet。这在用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)

将上述内容保存在单独的文件中 - (例如file_lineEdit.py) 然后以下列方式使用它 -     #usage示例:

#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_())