我想让用户通过将项目从 PyQt 拖到系统文件资源管理器来创建文件。由于某些文件非常大,我还需要延迟将数据设置为用户完成放置时,而不是立即开始拖动。
这个例子似乎就是我所需要的:https://doc.qt.io/archives/4.6/draganddrop-delayedencoding.html
我尝试将其转换为简单的 PyQt5 版本,其中将 QPushButton 拖到文件夹中将创建一个纯文本文件,但它对我不起作用...当我运行它时,删除不会执行任何操作,我的光标如下所示:
import sys
from PyQt5 import QtCore, QtGui, QtWidgets
import typing
import time
class MimeData(QtCore.QMimeData):
dataRequested = QtCore.pyqtSignal(str)
def formats(self) -> typing.List[str]:
return QtCore.QMimeData.formats(self) + ["text/plain"]
def retrieveData(self, mime_type: str, preferred_type: QtCore.QVariant.Type):
self.dataRequested.emit(mime_type)
return QtCore.QMimeData.retrieveData(self, mime_type, preferred_type)
class SourceWidget(QtWidgets.QWidget):
mimeData: MimeData = None
def __init__(self, parent=None):
super().__init__(parent)
layout = QtWidgets.QVBoxLayout()
button = QtWidgets.QPushButton("Drag Me")
button.pressed.connect(self.start_drag)
layout.addWidget(button)
self.setLayout(layout)
@QtCore.pyqtSlot()
def create_data(self, mime_type):
if mime_type == "text/plain":
time.sleep(0.25) # Simulate large file
self.mimeData.setData("text/plain", b"my text file contents")
@QtCore.pyqtSlot()
def start_drag(self):
self.mimeData = MimeData()
self.mimeData.dataRequested.connect(self.create_data)
drag = QtGui.QDrag(self)
drag.setMimeData(self.mimeData)
drag.exec(QtCore.Qt.CopyAction)
if __name__ == "__main__":
app = QtWidgets.QApplication.instance() or QtWidgets.QApplication(sys.argv)
w = SourceWidget()
w.show()
app.exec_()
最佳答案
这就是我将文件从 PyQt5 拖放到文件资源管理器中的结果,并且只有在释放鼠标以完成放置时才写入文件。
import time
from PyQt5 import QtCore, QtGui, QtWidgets
from PyQt5.QtCore import Qt
import tempfile
import os
# Use win32api on Windows because the pynput and mouse packages cause lag
# https://github.com/moses-palmer/pynput/issues/390
if os.name == 'nt':
import win32api
def mouse_pressed():
return win32api.GetKeyState(0x01) not in [0, 1]
else:
import mouse
def mouse_pressed():
return mouse.is_pressed()
class DelayedMimeData(QtCore.QMimeData):
def __init__(self):
super().__init__()
self.callbacks = []
def add_callback(self, callback):
self.callbacks.append(callback)
def retrieveData(self, mime_type: str, preferred_type: QtCore.QVariant.Type):
mp = mouse_pressed()
if not mp:
for callback in self.callbacks.copy():
self.callbacks.remove(callback)
callback()
return QtCore.QMimeData.retrieveData(self, mime_type, preferred_type)
class Navigator(QtWidgets.QTreeWidget):
def __init__(self):
super().__init__()
self.setHeaderLabels(["Name"])
QtWidgets.QTreeWidgetItem(self, ['Test1'])
QtWidgets.QTreeWidgetItem(self, ['Test2'])
QtWidgets.QTreeWidgetItem(self, ['Test3'])
self.setAcceptDrops(True)
self.setDragEnabled(True)
self.setDragDropMode(self.DragDrop)
self.setDefaultDropAction(Qt.MoveAction)
self.setSelectionMode(self.ExtendedSelection)
self.setSelectionBehavior(self.SelectRows)
self.setContextMenuPolicy(Qt.CustomContextMenu)
def startDrag(self, actions):
drag = QtGui.QDrag(self)
names = [item.text(0) for item in self.selectedItems()]
mime = DelayedMimeData()
path_list = []
for name in names:
path = os.path.join(tempfile.gettempdir(), 'DragTest', name + '.txt')
os.makedirs(os.path.dirname(path), exist_ok=True)
print(path)
def write_to_file(path=path, name=name, widget=self):
with open(path, 'w+') as f:
print("Writing large file(s)...")
time.sleep(2) # Sleep to simulate long file write
f.write(f"Contents of {name}")
mime.add_callback(write_to_file)
path_list.append(QtCore.QUrl.fromLocalFile(path))
mime.setUrls(path_list)
mime.setData('application/x-qabstractitemmodeldatalist',
self.mimeData(self.selectedItems()).data('application/x-qabstractitemmodeldatalist'))
drag.setMimeData(mime)
drag.exec_(Qt.MoveAction)
super().startDrag(actions)
app = QtWidgets.QApplication([])
nav = Navigator()
nav.show()
app.exec_()
关于python - PyQt5 拖放到系统文件资源管理器中(带有延迟编码)?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/64252654/