Следите за папкой для недавно добавленного файла и отображайте данные внутри этого файла в QTableView - PullRequest
0 голосов
/ 14 октября 2019

Я написал логику в PyQt5, которая считывает данные из недавнего файла CSV, который был добавлен в определенную папку при нажатии кнопки. Я хочу удалить функциональность нажатия кнопки тоже. Таким образом, как только в эту папку добавляется новый CSV-файл, содержимое внутри CSV-файла должно автоматически отображаться в TableView. Это код, который я использую:

from PyQt5 import QtCore, QtGui, QtWidgets
import numpy as np
import pandas as pd
import glob
import os
import csv
from itertools import combinations

class DataFrameModel(QtCore.QAbstractTableModel):
    DtypeRole = QtCore.Qt.UserRole + 1000
    ValueRole = QtCore.Qt.UserRole + 1001

    def __init__(self, df=pd.DataFrame(), parent=None):
        super(DataFrameModel, self).__init__(parent)
        self._dataframe = df

    def setDataFrame(self, dataframe):
        self.beginResetModel()
        self._dataframe = dataframe.copy()
        self.endResetModel()

    def dataFrame(self):
        return self._dataframe

    dataFrame = QtCore.pyqtProperty(pd.DataFrame, fget=dataFrame, fset=setDataFrame)

    @QtCore.pyqtSlot(int, QtCore.Qt.Orientation, result=str)
    def headerData(self, section: int, orientation: QtCore.Qt.Orientation, role: int = QtCore.Qt.DisplayRole):
        if role == QtCore.Qt.DisplayRole:
            if orientation == QtCore.Qt.Horizontal:
                return self._dataframe.columns[section]
            else:
                return str(self._dataframe.index[section])
        return QtCore.QVariant()

    def rowCount(self, parent=QtCore.QModelIndex()):
        if parent.isValid():
            return 0
        return len(self._dataframe.index)

    def columnCount(self, parent=QtCore.QModelIndex()):
        if parent.isValid():
            return 0
        return self._dataframe.columns.size

    def data(self, index, role=QtCore.Qt.DisplayRole):
        if not index.isValid() or not (0 <= index.row() < self.rowCount() \
            and 0 <= index.column() < self.columnCount()):
            return QtCore.QVariant()
        row = self._dataframe.index[index.row()]
        col = self._dataframe.columns[index.column()]
        dt = self._dataframe[col].dtype

        val = self._dataframe.iloc[row][col]
        if role == QtCore.Qt.DisplayRole:
            return str(val)
        elif role == DataFrameModel.ValueRole:
            return val
        if role == DataFrameModel.DtypeRole:
            return dt
        return QtCore.QVariant()

    def roleNames(self):
        roles = {
            QtCore.Qt.DisplayRole: b'display',
            DataFrameModel.DtypeRole: b'dtype',
            DataFrameModel.ValueRole: b'value'
        }
        return roles


class Ui_Rulepriority(object):
    def setupUi(self, Rulepriority):
        Rulepriority.setObjectName("Rulepriority")
        Rulepriority.resize(820, 480)
        self.verticalLayout = QtWidgets.QVBoxLayout(Rulepriority)
        self.verticalLayout.setObjectName("verticalLayout")
        self.OpenCsv = QtWidgets.QPushButton(Rulepriority)
        self.OpenCsv.setObjectName("OpenCsv")
        self.verticalLayout.addWidget(self.OpenCsv)
        self.OpenCsv.clicked.connect(self.file_open)
        self.tableView = QtWidgets.QTableView(Rulepriority)
        self.tableView.setSizeAdjustPolicy(QtWidgets.QAbstractScrollArea.AdjustToContents)
        self.tableView.setObjectName("tableView")
        self.verticalLayout.addWidget(self.tableView)

        self.retranslateUi(Rulepriority)
        self.OpenCsv.clicked.connect(self.tableView.show)
        QtCore.QMetaObject.connectSlotsByName(Rulepriority)

    def retranslateUi(self, Rulepriority):
        _translate = QtCore.QCoreApplication.translate
        Rulepriority.setWindowTitle(_translate("Rulepriority", "Error App"))
        self.OpenCsv.setText(_translate("Rulepriority", "Get recent data"))
        Rulepriority.setWindowIcon(QtGui.QIcon('favicon.ico'))

    def file_open(self):
        list_of_files = glob.glob('Folder for violation csv/Violations_*.csv')
        latest_file = max(list_of_files, key=os.path.getctime)

        df1 = pd.read_csv(latest_file)

        model = DataFrameModel(df1)
        self.tableView.setModel(model)

if __name__ == "__main__":
    import sys
    app = QtWidgets.QApplication(sys.argv)
    Rulepriority = QtWidgets.QDialog()
    ui = Ui_Rulepriority()
    ui.setupUi(Rulepriority)
    Rulepriority.show()
    sys.exit(app.exec_())

Я заимствовал class DataFrameModel из этого ответа Как отобразить фрейм данных Pandas с PyQt5 / PySide2

Вот как выглядит мой результат:

enter image description here

Я прочитал о QFileSystemWatcher, который, очевидно, следит за определенной папкой и уведомляет, если какой-либо файлсвязанные изменения происходят в этой папке, но я не знаю, отображает ли она данные внутри этого файла или нет. Если вы, ребята, могли бы помочь мне получить желаемый результат, я буду очень признателен.

1 Ответ

1 голос
/ 14 октября 2019

Вы действительно можете использовать объект QFileSystemWatcher для мониторинга каталога. Для автоматического обновления таблицы при изменении этого каталога, например, при добавлении или изменении файла, вы можете подключить сигнал QFileSystemWatcher.directoryChanged к Ui_Rulepriority.file_open, например,

class Ui_Rulepriority(object):
    def setupUi(self, Rulepriority):
        ....
        self.watcher = QtCore.QFileSystemWatcher(['Folder for violation csv'])
        self.watcher.directoryChanged.connect(self.file_open)
        self.file_open()
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...