我在左侧布局上有一个文件夹 TreeView,我想从那里拖动一个 .txt 文件并将其拖放到另一个布局中。希望我想将删除的文件的数据加载到变量上。
对于代码的需求,到目前为止(对于我的“真实”代码)我使用 np.loadtxt() 来加载数据,所以我也想在这里使用它。 如果重要的话,.txt 文件包含 4 列(坐标)。
我发布了我的代码。当我删除文件时,程序将关闭。
提前致谢!
import sys, time, os
from PyQt5.QtWidgets import *
from PyQt5.QtGui import *
from PyQt5.QtCore import *
import numpy as np
import pylab as pl
import random
class Example(QMainWindow):
def __init__(self):
super().__init__()
self.initUI()
def initUI(self):
self.central_widget = QWidget()
self.setCentralWidget(self.central_widget)
self.folderLayout = QWidget();
self.pathRoot = QDir.rootPath()
self.dirmodel = QFileSystemModel(self)
self.dirmodel.setRootPath(QDir.currentPath())
self.indexRoot = self.dirmodel.index(self.dirmodel.rootPath())
self.folder_view = QTreeView();
self.folder_view.setDragEnabled(True)
self.folder_view.setModel(self.dirmodel)
self.folder_view.setRootIndex(self.indexRoot)
self.selectionModel = self.folder_view.selectionModel()
self.left_layout = QVBoxLayout()
self.left_layout.addWidget(self.folder_view)
self.folderLayout.setLayout(self.left_layout)
splitter_filebrowser = QSplitter(Qt.Horizontal)
splitter_filebrowser.addWidget(self.folderLayout)
splitter_filebrowser.addWidget(Figure_Canvas(self))
splitter_filebrowser.setStretchFactor(1, 1)
hbox = QHBoxLayout(self)
hbox.addWidget(splitter_filebrowser)
self.centralWidget().setLayout(hbox)
self.setWindowTitle('Simple drag & drop')
self.setGeometry(750, 100, 600, 500)
class Figure_Canvas(QWidget):
def __init__(self, parent):
super().__init__(parent)
self.setAcceptDrops(True)
blabla = QLineEdit()
self.right_layout = QVBoxLayout()
self.right_layout.addWidget(blabla)
self.buttonLayout = QWidget()
self.buttonLayout.setLayout(self.right_layout)
def dragEnterEvent(self, e):
if e.mimeData().hasFormat('text/uri-list'):
e.accept()
else:
e.ignore()
def dropEvent(self, e):
print("something")
data = np.loadtxt(e.mimeData())
print(data)
if __name__ == '__main__':
app = QApplication(sys.argv)
ex = Example()
ex.show()
app.exec_()
从哪里拖放
.txt
文件,该文件的内容并不重要。问题的核心是:如何通过拖放来打开PyQt
中的文件?.
这是所需功能的简单实现;即,拖放:
"""
Adapted from a ZetCode PyQt6 tutorial
and the Calculator tutorial by RealPython
This simple program demonstrates the mechanism
to read the contents of a .txt file by merely
dragging and dropping a given file onto the field
set to accept drags and drops.
Tested using:
Python 3.11.0
PyQt6 6.6.0
BONUS TIP:
If you would like to check which version of PyQt6 you
have installed, run the following commend from the
virtual environment in your terminal:
py -m pip show PyQt6
If you are not using a virtual environment yet,
simply run the command.
"""
import sys
from PyQt6.QtCore import Qt
from PyQt6.QtWidgets import QMainWindow
from PyQt6.QtWidgets import (
QPushButton,
QWidget,
QLabel,
QTextEdit,
QApplication,
QHBoxLayout,
)
class DragDropTXTWidget(QWidget):
def __init__(self, parent, *args, **kwargs):
super().__init__(parent, *args, **kwargs)
self.setAcceptDrops(True)
def dragEnterEvent(self, event):
if event.mimeData().hasUrls():
event.accept()
else:
event.ignore()
def dropEvent(self, event):
for url in event.mimeData().urls():
path_to_file = url.path()[1:]
if path_to_file.endswith("txt"):
with open(path_to_file, encoding="utf-8") as f:
print(f.read())
class Window(QMainWindow):
def __init__(self) -> None:
super().__init__()
# Set up the main window's name and size:
self.setWindowTitle("Drag and Drop a .txt File")
self.setGeometry(300, 300, 300, 150)
# Set up the layout for the DragDropTXTWidget
# and add the DragDropTXTWidget as the main
# window's central widget:
self.generalLayout = QHBoxLayout()
dragDropWidget = DragDropTXTWidget(self)
dragDropWidget.setLayout(self.generalLayout)
self.setCentralWidget(dragDropWidget)
# Additional UI components:
self._addLabel()
def _addLabel(self) -> None:
"""Create a label to identify the drag/drop field.
"""
statement = """
Drag and drop a .txt file onto this field.
The results will be printed to the console.
"""
dragDropLabel = QLabel(statement)
# Add some style: center-alignment and
# a faded look for the text:
dragDropLabel.setObjectName("label")
dragDropLabel.setStyleSheet("QLabel#label { color: gray }")
dragDropLabel.setAlignment(Qt.AlignmentFlag.AlignCenter)
self.generalLayout.addWidget(dragDropLabel)
def main():
app = QApplication([])
window = Window()
window.show()
sys.exit(app.exec())
if __name__ == "__main__":
main()
在
DragDropTXTWidget
类中,我们继承了基本QWidget的属性并重写了两个方法:dragEnterEvent()
和dropEvent()
。
在本节中...
def dragEnterEvent(self, event):
if event.mimeData().hasUrls():
event.accept()
else:
event.ignore()
...
if
/else
块确保至少有 一个 URL 要打开。
这一段代码...
def dropEvent(self, event):
for url in event.mimeData().urls():
path_to_file = url.path()[1:]
if path_to_file.endswith("txt"):
with open(path_to_file, encoding="utf-8") as f:
print(f.read())
...做实际工作。它循环访问
event
的 mimeData()
方法中存储的 URL。
至于这一行:
path_to_file = url.path()[1:]
,这个示例是在Windows 11机器上测试的,而不是Linux。在被切片之前,路径是这样开始的:/C://...
。第一个/
必须跳过。
if
语句确保仅打开.txt
文件;其他任何内容都将被跳过。
可以将其更改为需要打开的文件。
在本例中,我使用了
Python
的内置 open()
类 (with open(path_to_file, encoding="utf-8") as f:
),但任何可以打开 .txt
文件的东西都可以用来代替它。
当然,您绝不会仅仅将文件的内容打印到控制台。然而,如何处理内容超出了本答案的范围。
虽然这个答案使用
PyQt6
而不是 PyQt5
,但概念是相同的。