Ссылка на виджет Qt в другом классе Python в другом файле - PullRequest
0 голосов
/ 11 апреля 2019

У меня есть два разных файла Python.Один из них имеет детали графического интерфейса, а другой - код для отслеживания папки с использованием Watchdog API

GUI Py File:

# -*- coding: utf-8 -*-

# Form implementation generated from reading ui file 'csvExcel.ui'
#
# Created by: PyQt5 UI code generator 5.11.3
#
# WARNING! All changes made in this file will be lost!

from PyQt5 import QtCore, QtGui, QtWidgets
import os
from Main_File import Watcher, DataFrameTableWidget


class Ui_MainWindow(object):

    def __init__(self):

        self.file_Name = None

    def setupUi(self, MainWindow):
        MainWindow.setObjectName("MainWindow")
        MainWindow.resize(800, 600)
        self.centralwidget = QtWidgets.QWidget(MainWindow)
        self.centralwidget.setObjectName("centralwidget")
        self.gridLayout = QtWidgets.QGridLayout(self.centralwidget)
        self.gridLayout.setObjectName("gridLayout")
        self.gridLayout_2 = QtWidgets.QGridLayout()
        self.gridLayout_2.setObjectName("gridLayout_2")
        self.start_button = QtWidgets.QPushButton(self.centralwidget)
        self.start_button.setAutoFillBackground(False)
        self.start_button.setAutoDefault(False)
        self.start_button.setDefault(False)
        self.start_button.setFlat(False)
        self.start_button.setObjectName("start_button")
        self.start_button.clicked.connect(lambda: self.start_button_click())
        self.gridLayout_2.addWidget(self.start_button, 0, 0, 1, 1)
        self.Br_button = QtWidgets.QPushButton(self.centralwidget)
        self.Br_button.setObjectName("Br_button")
        self.Br_button.clicked.connect(lambda: self.browse_button())
        self.gridLayout_2.addWidget(self.Br_button, 2, 0, 1, 1)
        self.label = QtWidgets.QLabel(self.centralwidget)
        font = QtGui.QFont()
        font.setPointSize(14)
        font.setBold(True)
        font.setWeight(75)
        self.label.setFont(font)
        self.label.setObjectName("label")
        self.gridLayout_2.addWidget(self.label, 2, 1, 1, 1, QtCore.Qt.AlignHCenter)
        self.tableWidget = QtWidgets.QTableWidget(self.centralwidget)
        self.tableWidget.setEditTriggers(QtWidgets.QAbstractItemView.NoEditTriggers)
        self.tableWidget.setObjectName("tableWidget")
        self.tableWidget.setColumnCount(0)
        self.tableWidget.setRowCount(0)
        self.gridLayout_2.addWidget(self.tableWidget, 3, 0, 1, 2)
        self.gridLayout.addLayout(self.gridLayout_2, 0, 0, 1, 1)
        MainWindow.setCentralWidget(self.centralwidget)

        self.retranslateUi(MainWindow)
        QtCore.QMetaObject.connectSlotsByName(MainWindow)

    def retranslateUi(self, MainWindow):
        _translate = QtCore.QCoreApplication.translate
        MainWindow.setWindowTitle(_translate("MainWindow", "MainWindow"))
        self.start_button.setToolTip(_translate("MainWindow", "Start The Program"))
        self.start_button.setText(_translate("MainWindow", "Start"))
        self.Br_button.setToolTip(_translate("MainWindow", "Browse the File Location to Watch on"))
        self.Br_button.setText(_translate("MainWindow", "Browse"))
        self.label.setText(_translate("MainWindow", "Sensor CSV To Excel"))

    def start_button_click(self):
        watcher = Watcher(self.file_Name)
        if self.start_button.text() == "Start":
            self.start_button.setText("Stop")
            w = DataFrameTableWidget(self.tableWidget)
            watcher.emitter.newDataFrameSignal.connect(w.append_dataframe)
            watcher.run()
        elif self.start_button.text() == "Stop":
            self.start_button.setText("Start")
            watcher.stop_watcher()

    def browse_button(self):
        self.file_Name = QtWidgets.QFileDialog.getExistingDirectory(None, 'Open working directory', os.getcwd(), QtWidgets.QFileDialog.ShowDirsOnly)
        print(self.file_Name)


if __name__ == "__main__":
    import sys
    app = QtWidgets.QApplication(sys.argv)
    MainWindow = QtWidgets.QMainWindow()
    ui = Ui_MainWindow()
    ui.setupUi(MainWindow)
    MainWindow.show()

    sys.exit(app.exec_())

Python Code File с реализацией Watchdog

import os
import pandas as pd
from PyQt5 import QtCore, QtWidgets
from watchdog.events import PatternMatchingEventHandler
from watchdog.observers import Observer
import time
from Append_Function import append_df_to_excel


class Emitter(QtCore.QObject):
    newDataFrameSignal = QtCore.pyqtSignal(pd.DataFrame)


class Watcher:
    def __init__(self, filename):
        self.watch_dir = os.getcwd()
        self.directory_to_watch = os.path.join(self.watch_dir, filename)
        self.emitter = Emitter()
        self.observer = Observer()
        self.event_handler = Handler(
            emitter=self.emitter,
            patterns=["*.CSV"],
            ignore_patterns=["*.tmp"],
            ignore_directories=True
        )

    def run(self):
        self.observer.schedule(self.event_handler, self.directory_to_watch, recursive=False)
        self.observer.start()

    def stop_watcher(self):
        self.observer.stop()


class Handler(PatternMatchingEventHandler):
    def __init__(self, *args, emitter=None, **kwargs):
        super(Handler, self).__init__(*args, **kwargs)
        self._emitter = emitter
        self.file_name = time.strftime("%Y%m%d-%H%M%S")+".xlsx"

    def on_any_event(self, event):

        if event.is_directory:
            return None
        elif event.event_type == 'created':
            # Take any action here when a file is first created.
            print("Received created event - %s." % event.src_path)

            if os.path.isfile(os.path.join(os.getcwd(), self.file_name)):

                append_df_to_excel(os.path.join(os.getcwd(), self.file_name),
                                   pd.read_csv(event.src_path, header=1, index_col=0))
                df = pd.read_csv(event.src_path, header=1)

            else:
                append_df_to_excel(os.path.join(os.getcwd(), self.file_name),
                                   pd.read_csv(event.src_path, header=0, index_col=0))
                df = pd.read_csv(event.src_path, header=0)

            self._emitter.newDataFrameSignal.emit(df.copy())
            df.set_index(df.columns.values.tolist()[0], inplace=True)

        elif event.event_type == 'modified':
            print("Modified created event - %s." % event.src_path)

            if os.path.isfile(os.path.join(os.getcwd(), self.file_name)):

                append_df_to_excel(os.path.join(os.getcwd(), self.file_name),
                                   pd.read_csv(event.src_path, header=1, index_col=0))
                df = pd.read_csv(event.src_path, header=1)

            else:

                append_df_to_excel(os.path.join(os.getcwd(), self.file_name),
                                   pd.read_csv(event.src_path, header=0, index_col=0))
                df = pd.read_csv(event.src_path, header=0)

            self._emitter.newDataFrameSignal.emit(df.copy())
            df.set_index(df.columns.values.tolist()[0], inplace=True)


class DataFrameTableWidget(QtWidgets.QTableWidget):

    @QtCore.pyqtSlot(pd.DataFrame)
    def append_dataframe(self, df):
        df = df.copy()
        if df.columns.size > self.columnCount():
            self.setColumnCount(df.columns.size)
        r = self.rowCount()
        self.insertRow(r)
        for c, column in enumerate(df):
            it = QtWidgets.QTableWidgetItem(column)

            self.setItem(r, c, it)
        i = self.rowCount()
        for r, row in df.iterrows():
            self.insertRow(self.rowCount())
            for c, (column, value) in enumerate(row.iteritems()):
                it = QtWidgets.QTableWidgetItem(str(value))
                self.setItem(i+r, c, it)

В этом файле вы можете видеть, что я использовал функцию «Append_Function», которая на самом деле для добавления данных в файл Excel (я буду редактировать, чтобы добавить код функции, если необходимо).

Моя проблема

В файле реализации Watchdog вы можете видеть, что в этом классе DataFrameTableWidget есть пользовательский Pyslot.Активируется, когда создается кадр данных.и, соответственно, данные из фрейма данных отображаются в таблице QWidget, поскольку класс DataFrameTableWidget наследует QTableWidget.

Теперь, как вы можете видеть, я сделал отдельный графический интерфейс для моего приложения, имеющего виджет таблицы.Я хочу, чтобы данные из фрейма данных pandas отображались в моем графическом виджете таблицы вместо отображения в QTableWidget, который был унаследован классом DataFrameTableWidget в моем файле реализации WatchDog.

Я думаю, что каким-то образом инициализируется DataFrameTableWidgetКласс с QTableWidget из GUI может работать.Но я не уверен, смогу ли я передать QTableWidget в функцию инициализации класса DataFrameTaleWidget (т. Е. init ), чтобы я мог сослаться с моим виджетом таблицы GUI в мой файл реализации Watchdog.

Я пыталсямое лучшее, чтобы быть ясным с моей проблемой здесь.Но если при понимании все еще возникают проблемы, я отредактирую их и попытаюсь прояснить.

Спасибо!

Обновить версию кода

csvExcelGUI.py

from PyQt5 import QtCore, QtGui, QtWidgets
import os
from Main_File import Watcher, DataFrameTableWidget


class Ui_MainWindow(object):

    def __init__(self):

        self.file_Name = None

    def setupUi(self, MainWindow):
        MainWindow.setObjectName("MainWindow")
        MainWindow.resize(800, 600)
        self.centralwidget = QtWidgets.QWidget(MainWindow)
        self.centralwidget.setObjectName("centralwidget")
        self.gridLayout = QtWidgets.QGridLayout(self.centralwidget)
        self.gridLayout.setObjectName("gridLayout")
        self.gridLayout_2 = QtWidgets.QGridLayout()
        self.gridLayout_2.setObjectName("gridLayout_2")
        self.start_button = QtWidgets.QPushButton(self.centralwidget)
        self.start_button.setAutoFillBackground(False)
        self.start_button.setAutoDefault(False)
        self.start_button.setDefault(False)
        self.start_button.setFlat(False)
        self.start_button.setObjectName("start_button")
        #self.start_button.clicked.connect(lambda: self.start_button_click())
        self.gridLayout_2.addWidget(self.start_button, 0, 0, 1, 1)
        self.Br_button = QtWidgets.QPushButton(self.centralwidget)
        self.Br_button.setObjectName("Br_button")
        self.Br_button.clicked.connect(lambda: self.browse_button())
        self.gridLayout_2.addWidget(self.Br_button, 2, 0, 1, 1)
        self.label = QtWidgets.QLabel(self.centralwidget)
        font = QtGui.QFont()
        font.setPointSize(14)
        font.setBold(True)
        font.setWeight(75)
        self.label.setFont(font)
        self.label.setObjectName("label")
        self.gridLayout_2.addWidget(self.label, 2, 1, 1, 1, QtCore.Qt.AlignHCenter)
        #self.tableWidget = QtWidgets.QTableWidget(self.centralwidget)
        self.tableWidget = DataFrameTableWidget(self.centralwidget)
        self.tableWidget.setEditTriggers(QtWidgets.QAbstractItemView.NoEditTriggers)
        self.tableWidget.setObjectName("tableWidget")
        self.tableWidget.setColumnCount(0)
        self.tableWidget.setRowCount(0)
        self.gridLayout_2.addWidget(self.tableWidget, 3, 0, 1, 2)
        self.gridLayout.addLayout(self.gridLayout_2, 0, 0, 1, 1)
        MainWindow.setCentralWidget(self.centralwidget)

        self.retranslateUi(MainWindow)
        QtCore.QMetaObject.connectSlotsByName(MainWindow)

    def retranslateUi(self, MainWindow):
        _translate = QtCore.QCoreApplication.translate
        MainWindow.setWindowTitle(_translate("MainWindow", "MainWindow"))
        self.start_button.setToolTip(_translate("MainWindow", "Start The Program"))
        self.start_button.setText(_translate("MainWindow", "Start"))
        self.Br_button.setToolTip(_translate("MainWindow", "Browse the File Location to Watch on"))
        self.Br_button.setText(_translate("MainWindow", "Browse"))
        self.label.setText(_translate("MainWindow", "Sensor CSV To Excel"))


class MainWindow(QtWidgets.QMainWindow, Ui_MainWindow):
    def __init__(self, parent=None):
        super(MainWindow, self).__init__(parent)
        self.setupUi(self)
        self.start_button.clicked.connect(self.start_button_click)
        self.watcher = Watcher()
        self.watcher.emitter.newDataFrameSignal.connect(self.tableWidget.append_dataframe)
        self.file_Name = ""

    def start_button_click(self):
        self.watcher.set_filename(self.file_Name)
        if self.start_button.text() == "Start":
            self.start_button.setText("Stop")
            self.watcher.run()
        elif self.start_button.text() == "Stop":
            self.start_button.setText("Start")
            self.watcher.stop_watcher()

    def browse_button(self):
        self.file_Name = QtWidgets.QFileDialog.getExistingDirectory(None, 'Open working directory', os.getcwd(), QtWidgets.QFileDialog.ShowDirsOnly)
        print(self.file_Name)


if __name__ == "__main__":
    import sys
    app = QtWidgets.QApplication(sys.argv)
    # MainWindow = QtWidgets.QMainWindow()
    # ui = Ui_MainWindow()
    # ui.setupUi(MainWindow)
    # MainWindow.show()
    w = MainWindow()
    w.show()

    sys.exit(app.exec_())

Main_File.py

import os
import pandas as pd
from PyQt5 import QtCore, QtWidgets
from watchdog.events import PatternMatchingEventHandler
from watchdog.observers import Observer
import time
from Append_Function import append_df_to_excel


class Emitter(QtCore.QObject):
    newDataFrameSignal = QtCore.pyqtSignal(pd.DataFrame)


class Watcher:
    def __init__(self):
        self.watch_dir = os.getcwd()
        self.directory_to_watch = None
        self.emitter = Emitter()
        self.observer = Observer()
        self.event_handler = Handler(
            emitter=self.emitter,
            patterns=["*.CSV"],
            ignore_patterns=["*.tmp"],
            ignore_directories=True
        )

    def set_filename(self, filename):
        self.directory_to_watch = os.path.join(self.watch_dir, filename)

    def run(self):
        self.observer.schedule(self.event_handler, self.directory_to_watch, recursive=False)
        self.observer.start()

    def stop_watcher(self):
        self.observer.stop()


class Handler(PatternMatchingEventHandler):
    def __init__(self, *args, emitter=None, **kwargs):
        super(Handler, self).__init__(*args, **kwargs)
        self._emitter = emitter
        self.file_name = time.strftime("%Y%m%d-%H%M%S")+".xlsx"

    def on_any_event(self, event):

        if event.is_directory:
            return None
        elif event.event_type == 'created':
            # Take any action here when a file is first created.
            print("Received created event - %s." % event.src_path)

            if os.path.isfile(os.path.join(os.getcwd(), self.file_name)):

                append_df_to_excel(os.path.join(os.getcwd(), self.file_name),
                                   pd.read_csv(event.src_path, header=1, index_col=0))
                df = pd.read_csv(event.src_path, header=1)

            else:
                append_df_to_excel(os.path.join(os.getcwd(), self.file_name),
                                   pd.read_csv(event.src_path, header=0, index_col=0))
                df = pd.read_csv(event.src_path, header=0)

            self._emitter.newDataFrameSignal.emit(df.copy())
            df.set_index(df.columns.values.tolist()[0], inplace=True)

        elif event.event_type == 'modified':
            print("Modified created event - %s." % event.src_path)

            if os.path.isfile(os.path.join(os.getcwd(), self.file_name)):

                append_df_to_excel(os.path.join(os.getcwd(), self.file_name),
                                   pd.read_csv(event.src_path, header=1, index_col=0))
                df = pd.read_csv(event.src_path, header=1)

            else:

                append_df_to_excel(os.path.join(os.getcwd(), self.file_name),
                                   pd.read_csv(event.src_path, header=0, index_col=0))
                df = pd.read_csv(event.src_path, header=0)

            self._emitter.newDataFrameSignal.emit(df.copy())
            df.set_index(df.columns.values.tolist()[0], inplace=True)


class DataFrameTableWidget(QtWidgets.QTableWidget):

    @QtCore.pyqtSlot(pd.DataFrame)
    def append_dataframe(self, df):
        df = df.copy()
        if df.columns.size > self.columnCount():
            self.setColumnCount(df.columns.size)
        r = self.rowCount()
        self.insertRow(r)
        for c, column in enumerate(df):
            it = QtWidgets.QTableWidgetItem(column)

            self.setItem(r, c, it)
        i = self.rowCount()
        for r, row in df.iterrows():
            self.insertRow(self.rowCount())
            for c, (column, value) in enumerate(row.iteritems()):
                it = QtWidgets.QTableWidgetItem(str(value))
                self.setItem(i+r, c, it)

1 Ответ

1 голос
/ 11 апреля 2019

Ваш код содержит следующие ошибки:

  • В строке: w = DataFrameTableWidget(self.tableWidget) вы указываете только на то, что фрейм данных qTableWidget является дочерним для QTableWidget (то есть он будет помещен внутри виджета) и не заменит его.

  • watcher = Watcher(self.file_Name) - это локальная переменная, которая будет удалена по завершении выполнения start_button_click.

Предполагая, что ваш код работает до добавления графического интерфейса, я внесу следующие изменения:

  1. Измените self.tableWidget = QtWidgets.QTableWidget(self.centralwidget) на self.tableWidget = DataFrameTableWidget(self.centralwidget), если бы у вас был .ui, он научил бы вас, как устанавливать новые виджеты через Qt Designer.
  2. Реализуйте метод set_filename, чтобы не нужно было создавать новый объект Watcher при каждом нажатии кнопки.
  3. Сделать объект членом-наблюдателем объекта класса.

Main_File.py

# ...

class Watcher:
    def __init__(self):
        self.watch_dir = os.getcwd()
        self.emitter = Emitter()
        self.observer = Observer()
        self.event_handler = Handler(
            emitter=self.emitter,
            patterns=["*.CSV"],
            ignore_patterns=["*.tmp"],
            ignore_directories=True
        )
    def set_filename(self, filename):
        self.directory_to_watch = os.path.join(self.watch_dir, filename)

    # ...

main.py

# -*- coding: utf-8 -*-

# Form implementation generated from reading ui file 'csvExcel.ui'
#
# Created by: PyQt5 UI code generator 5.11.3
#
# WARNING! All changes made in this file will be lost!

from PyQt5 import QtCore, QtGui, QtWidgets
import os
from Main_File import Watcher, DataFrameTableWidget


class Ui_MainWindow(object):
    def setupUi(self, MainWindow):
        MainWindow.setObjectName("MainWindow")
        MainWindow.resize(800, 600)
        self.centralwidget = QtWidgets.QWidget(MainWindow)
        self.centralwidget.setObjectName("centralwidget")
        self.gridLayout = QtWidgets.QGridLayout(self.centralwidget)
        self.gridLayout.setObjectName("gridLayout")
        self.gridLayout_2 = QtWidgets.QGridLayout()
        self.gridLayout_2.setObjectName("gridLayout_2")
        self.start_button = QtWidgets.QPushButton(self.centralwidget)
        self.start_button.setAutoFillBackground(False)
        self.start_button.setAutoDefault(False)
        self.start_button.setDefault(False)
        self.start_button.setFlat(False)
        self.start_button.setObjectName("start_button")
        self.gridLayout_2.addWidget(self.start_button, 0, 0, 1, 1)
        self.Br_button = QtWidgets.QPushButton(self.centralwidget)
        self.Br_button.setObjectName("Br_button")
        self.Br_button.clicked.connect(lambda: self.browse_button())
        self.gridLayout_2.addWidget(self.Br_button, 2, 0, 1, 1)
        self.label = QtWidgets.QLabel(self.centralwidget)
        font = QtGui.QFont()
        font.setPointSize(14)
        font.setBold(True)
        font.setWeight(75)
        self.label.setFont(font)
        self.label.setObjectName("label")
        self.gridLayout_2.addWidget(self.label, 2, 1, 1, 1, QtCore.Qt.AlignHCenter)
        self.tableWidget = DataFrameTableWidget(self.centralwidget)
        self.tableWidget.setEditTriggers(QtWidgets.QAbstractItemView.NoEditTriggers)
        self.tableWidget.setObjectName("tableWidget")
        self.tableWidget.setColumnCount(0)
        self.tableWidget.setRowCount(0)
        self.gridLayout_2.addWidget(self.tableWidget, 3, 0, 1, 2)
        self.gridLayout.addLayout(self.gridLayout_2, 0, 0, 1, 1)
        MainWindow.setCentralWidget(self.centralwidget)

        self.retranslateUi(MainWindow)
        QtCore.QMetaObject.connectSlotsByName(MainWindow)

    def retranslateUi(self, MainWindow):
        _translate = QtCore.QCoreApplication.translate
        MainWindow.setWindowTitle(_translate("MainWindow", "MainWindow"))
        self.start_button.setToolTip(_translate("MainWindow", "Start The Program"))
        self.start_button.setText(_translate("MainWindow", "Start"))
        self.Br_button.setToolTip(_translate("MainWindow", "Browse the File Location to Watch on"))
        self.Br_button.setText(_translate("MainWindow", "Browse"))
        self.label.setText(_translate("MainWindow", "Sensor CSV To Excel"))


class MainWindow(QtWidgets.QMainWindow, Ui_MainWindow):
    def __init__(self, parent=None):
        super(MainWindow, self).__init__(parent)
        self.setupUi(self)
        self.start_button.clicked.connect(self.start_button_click)
        self.watcher = Watcher()
        self.watcher.emitter.newDataFrameSignal.connect(self.tableWidget.append_dataframe)
        self.file_Name = ""

    def start_button_click(self):
        self.watcher.set_filename(self.file_Name)
        if self.start_button.text() == "Start":
            self.start_button.setText("Stop")
            self.watcher.run()
        elif self.start_button.text() == "Stop":
            self.start_button.setText("Start")
            self.watcher.stop_watcher()

    def browse_button(self):
        self.file_Name = QtWidgets.QFileDialog.getExistingDirectory(None, 'Open working directory', os.getcwd(), QtWidgets.QFileDialog.ShowDirsOnly)
        print(self.file_Name)


if __name__ == "__main__":
    import sys
    app = QtWidgets.QApplication(sys.argv)
    w = MainWindow()
    w.show()
    sys.exit(app.exec_())
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...