【问题标题】:drag a file into QtGui.QLineEdit() to set url text将文件拖入 QtGui.QLineEdit() 以设置 url 文本
【发布时间】:2012-08-06 00:18:47
【问题描述】:

我使用 pySide Qt 绑定在 python 脚本中创建了一个QtGui.LineEdit() 小部件,我希望能够将文件从桌面拖到 QLineEdit 中,以将 QLineEdit 中的文本设置为文件。我已经完成QLineEdit.setDragEnabled(True) 以启用拖放操作,但我是一个不知道如何从这里开始的机器人。有谁知道如何做到这一点?

【问题讨论】:

    标签: python drag-and-drop pyside


    【解决方案1】:

    通常,对于事件,您可以使用 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)
    

    【讨论】:

    • 您可以使用 url.toLocalFile() 删除前导斜杠
    【解决方案2】:

    使用上面提到的 eventFilter 机制确实有效,当像这样使用时:

    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)
    

    现在,可以在任何行编辑中使用 drop 处理程序而无需子类化:

    lineEdit.installEventFilter(QLineEditDropHandler(self))
    

    【讨论】:

    • 这对我不起作用 - 虽然 url 确实打印正确,但由于某种原因,当它设置 editText 的文本时,它输出字符串的乱码版本,格式为:part_of_path /path file://same_path_with_doubled//strings// /rest_of/first/path
    • 对我有用,但以 / 开头。为了解决这个问题,根据另一个答案中的评论,我将obj.setText(url.path()) 更改为obj.setText(url.toLocalFile())。这也适用于本地网络路径。谢谢!
    • @MaVCArt 当事件随后由普通事件过滤器处理时,也会发生这种情况。在 drop 事件中返回 True 可以解决此问题。更新了答案。
    • 类中的objurl 在哪里定义?
    • watched.setText(url.toLocalFile()) 使 obj 部分正常工作。仍然不确定他们从哪里得到url,但我在设置md 后用for url in event.mimeData().urls(): 抓住它
    【解决方案3】:

    Erics 答案的一个稍微改进的版本(我希望)将是一个简短的注入器实现,它可以将拖放功能添加到现有的对象。这有助于我使用 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) 然后按以下方式使用它 - #用法示例:

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

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2020-10-26
      • 2011-02-24
      • 2023-03-08
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多