问题描述
我基本上是在重复 PyQt: 获取应用中文件的文件名 .
I am essentially repeating a question that was asked (but not answered) in the comments of PyQt: Getting file name for file dropped in app .
我希望能够做的是,在那个帖子中,转换 pyqt 中文件放置事件的输出,目前看起来像这样:/.file/id=6571367.661326 转换成实际文件路径(即/.Documents/etc./etc./myProject/fileNeeded.extension)
What I'd like to be able to do, a la that post, is convert an output from a file drop event in pyqt that currently looks like this: /.file/id=6571367.661326 into an actual file path (i.e. /.Documents/etc./etc./myProject/fileNeeded.extension)
这样我就可以使用尝试 QDropEvent 的文件.这个怎么做.有什么想法吗?
so that I can make use of the file that made the attempted QDropEvent. how to do this. Any thoughts?
正如下面评论中提到的,这似乎是一个特定于平台的问题.我正在运行 Mac OS X El Capitan (10.11.2)
As mentioned below in the comments, this appears to be a platform specific problem. I am running Mac OS X El Capitan (10.11.2)
推荐答案
我在翻译了http://www.51sjk.com/Upload/Articles/1/0/337/337742_20221130104205808.请注意,此解决方案仅适用于运行 OS X Yosemite 或更高版本且不运行 PyQt5(即在我的情况下运行 v.4.8)的 Mac.
I figured out the solution after translating Obj-C code found in http://www.51sjk.com/Upload/Articles/1/0/337/337742_20221130104216698.jpg Note that this solution is only necessary for Macs running OS X Yosemite or later AND not running PyQt5 (i.e. running v.4.8 in my case).
import objc import CoreFoundation as CF def getUrlFromLocalFileID(self, localFileID): localFileQString = QString(localFileID.toLocalFile()) relCFStringRef = CF.CFStringCreateWithCString( CF.kCFAllocatorDefault, localFileQString.toUtf8(), CF.kCFStringEncodingUTF8 ) relCFURL = CF.CFURLCreateWithFileSystemPath( CF.kCFAllocatorDefault, relCFStringRef, CF.kCFURLPOSIXPathStyle, False # is directory ) absCFURL = CF.CFURLCreateFilePathURL( CF.kCFAllocatorDefault, relCFURL, objc.NULL ) return QUrl(str(absCFURL[0])).toLocalFile()
要查看此在拖放情况下的工作情况,请参见下文:
To see this working in a drag and drop situation, see below:
import sys import objc import CoreFoundation as CF from PyQt4.QtGui import * from PyQt4.QtCore import * class MyListWidget(QListWidget): def __init__(self, parent): super(MyListWidget, self).__init__(parent) self.setAcceptDrops(True) self.setDragDropMode(QAbstractItemView.InternalMove) def getUrlFromLocalFileID(self, localFileID): localFileQString = QString(localFileID.toLocalFile()) relCFStringRef = CF.CFStringCreateWithCString( CF.kCFAllocatorDefault, localFileQString.toUtf8(), CF.kCFStringEncodingUTF8 ) relCFURL = CF.CFURLCreateWithFileSystemPath( CF.kCFAllocatorDefault, relCFStringRef, CF.kCFURLPOSIXPathStyle, False # is directory ) absCFURL = CF.CFURLCreateFilePathURL( CF.kCFAllocatorDefault, relCFURL, objc.NULL ) return QUrl(str(absCFURL[0])).toLocalFile() def dragEnterEvent(self, event): if event.mimeData().hasUrls(): event.acceptProposedAction() else: super(MyListWidget, self).dragEnterEvent(event) def dragMoveEvent(self, event): super(MyListWidget, self).dragMoveEvent(event) def dropEvent(self, event): if event.mimeData().hasUrls(): event.setDropAction(Qt.CopyAction) event.accept() links = [] for url in event.mimeData().urls(): if QString(url.toLocalFile()).startsWith('/.file/id='): url = self.getUrlFromLocalFileID(url) links.append(url) else: links.append(str(url.toLocalFile())) for link in links: self.addItem(link) else: super(MyListWidget,self).dropEvent(event) class MyWindow(QWidget): def __init__(self): super(MyWindow,self).__init__() self.setGeometry(100,100,300,400) self.setWindowTitle("Filenames") self.list = MyListWidget(self) layout = QVBoxLayout(self) layout.addWidget(self.list) self.setLayout(layout) if __name__ == '__main__': app = QApplication(sys.argv) app.setStyle("plastique") window = MyWindow() window.show() sys.exit(app.exec_())