如何在PyQt/PySide中获取被拖放的文件名

14 投票
1 回答
14423 浏览
提问于 2025-04-17 08:40

我正在尝试设置一个应用程序,让用户可以把文件拖放到里面。所以,我想找个方法来提取文件被拖放时的路径。

现在,我已经在应用程序的右侧启用了拖放功能,可以接受文本的拖放,但我不知道怎么处理文件的拖放。

我使用的是:

def PTE_dragEnterEvent(self, e):
    if e.mimeData().hasFormat('text/plain'):
        e.accept()
    else:
        e.ignore() 

def PTE_dropEvent(self, e):
    newText = self.ui.fileListPTE.toPlainText() + '\n\n' + e.mimeData().text()
    self.ui.fileListPTE.setPlainText(newText)

这个代码是稍微修改了Zetcode的拖放教程中的代码。


我没能完全让@ekhumoro的回答对我有效,但它让我找到了更多的方向,后来我发现了将文件拖放到QListWidget的内容,这对我有帮助。

除了ekhumoro的建议,我还需要实现拖动移动事件。最后我使用的代码看起来像这样:

def dragEnterEvent(self, event):
    if event.mimeData().hasUrls:
        event.accept()
    else:
        event.ignore()
        
def dragMoveEvent(self, event):
    if event.mimeData().hasUrls:
        event.setDropAction(QtCore.Qt.CopyAction)
        event.accept()
    else:
        event.ignore()

def dropEvent(self, event):
    if event.mimeData().hasUrls:
        event.setDropAction(QtCore.Qt.CopyAction)
        event.accept()
        
        newText = self.ui.fileListPTE.toPlainText()
        for url in event.mimeData().urls():
            newText += '\n' + str(url.toLocalFile())
        self.ui.fileListPTE.setPlainText(newText)
        self.emit(QtCore.SIGNAL("dropped"))
    else:
        event.ignore()

1 个回答

20

QMimeData 类有一些方法可以处理拖放的链接。下面是一个简单的示例:

# from PyQt4.QtGui import QApplication, QLabel
# from PySide2.QtWidgets import QApplication, QLabel
from PyQt5.QtWidgets import QApplication, QLabel

class Window(QLabel):
    def __init__(self):
        super().__init__()
        self.setAcceptDrops(True)

    def dragEnterEvent(self, event):
        print('drag-enter')
        if event.mimeData().hasUrls():
            print('has urls')
            event.accept()
        else:
            event.ignore()

    def dropEvent(self, event):
        lines = []
        for url in event.mimeData().urls():
            lines.append('dropped: %r' % url.toLocalFile())
        self.setText('\n'.join(lines))
    
app = QApplication(['Drag & Drop'])
window = Window()
window.setGeometry(50, 100, 400, 300)
window.show()
app.exec_()

更新

关于问题的补充:

有些控件(和上面提到的 QLabel 不同)默认的 dragMoveEvent 实现会忽略大部分事件。例如,基于 QAbstractItemView 的类可能只处理某些特定类型的内部移动事件,而忽略其他所有事件。在这种情况下,需要重新实现 dragMoveEvent,以明确接受那些需要特别处理的事件:

class MyView(QTableView):
    ...
    def dragMoveEvent(self, event):
        if event.mimeData().hasUrls():
            event.accept()
        else:
            super().dragMoveEvent(event)

撰写回答