在其他文件中将Qt小部件引用到其他Python类中

时间:2019-04-11 19:41:50

标签: python pyqt pyqt5

我有两个不同的Python文件。一种是具有GUI详细信息,另一种是具有使用Watchdog API在Folder上进行监视的代码

GUI 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 __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代码文件

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)

在此文件中,您可以看到我使用了实际上是将数据追加到Excel文件中的函数“ Append_Function”(如果需要,我将进行编辑以添加功能代码)。

我的问题

在看门狗实现文件中,您可以看到该DataFrameTableWidget类中有一个自定义Pyslot。当生成数据帧时,它变为活动状态。因此,当DataFrameTableWidget类继承QTableWidget时,来自数据帧的数据将显示在QWidget表中。

现在您可以看到,我为具有表窗口小部件的应用程序制作了单独的GUI。我希望将来自熊猫数据框的数据显示在我的GUI表小部件中,而不是显示在我的WatchDog实现文件中的DataFrameTableWidget类继承的QTableWidget中。

我在想用GUI的QTableWidget初始化DataFrameTableWidget类是可行的。但是我不确定是否可以将QTableWidget传递给DataFrameTaleWidget类初始化(即 init )函数,以便可以将GUI表Widget引用到我的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 个答案:

答案 0 :(得分:1)

您的代码具有以下错误:

  • 在行w = DataFrameTableWidget(self.tableWidget)中,您仅指出数据框qTableWidget是QTableWidget的子级(也就是说,它将被放置在小部件内),并且不会替换它。

  • watcher = Watcher(self.file_Name)是一个局部变量,在完成执行start_button_click后将被删除。

假设您的代码在添加GUI之前可以工作,我将进行以下修改:

  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_())