PyQt – 通过拖放从 .txt 文件加载数据

问题描述 投票:0回答:1

我在左侧布局上有一个文件夹 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_()             
qt drag-and-drop pyqt pyqt5 qtreeview
1个回答
0
投票

澄清问题

从哪里拖放

.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
,但概念是相同的。

© www.soinside.com 2019 - 2024. All rights reserved.