import sys
import time
from PyQt6.QtWidgets import QApplication, QDialog, QLabel, QVBoxLayout
from PyQt6.QtCore import QThread, pyqtSignal
import pandas as pd
class ExcelReaderThread(QThread):
data_read = pyqtSignal(pd.DataFrame)
def __init__(self, file_path):
super().__init__()
self.file_path = file_path
def run(self):
# 读取Excel文件
df = pd.read_excel(self.file_path)
# 发送数据读取信号
self.data_read.emit(df)
class DataProcessorThread(QThread):
data_processed = pyqtSignal(pd.DataFrame)
def __init__(self, data):
super().__init__()
self.data = data
def run(self):
# 处理数据,这里简单地将所有字符串转换为大写
df = self.data.applymap(lambda x: x.upper() if isinstance(x, str) else x)
# 发送数据处理信号
self.data_processed.emit(df)
class DataDisplayerThread(QThread):
data_displayed = pyqtSignal(pd.DataFrame)
def __init__(self, data):
super().__init__()
self.data = data
def run(self):
# 模拟展示数据的过程,这里简单地打印数据
print(self.data)
# 发送数据展示信号
self.data_displayed.emit(self.data)
class MainWindow(QDialog):
def __init__(self):
super().__init__()
self.file_path = "example.xlsx"
self.setWindowTitle("Excel Data Display")
self.status_label = QLabel("Loading data...")
self.data_label = QLabel("")
layout = QVBoxLayout()
layout.addWidget(self.status_label)
layout.addWidget(self.data_label)
self.setLayout(layout)
self.reader_thread = ExcelReaderThread(self.file_path)
self.reader_thread.data_read.connect(self.process_data)
self.processor_thread = DataProcessorThread(None)
self.processor_thread.data_processed.connect(self.display_data)
self.displayer_thread = DataDisplayerThread(None)
self.displayer_thread.data_displayed.connect(self.show_data)
self.reader_thread.start()
def process_data(self, data):
self.status_label.setText("Processing data...")
self.processor_thread.data = data
self.processor_thread.start()
def display_data(self, data):
self.status_label.setText("Displaying data...")
self.displayer_thread.data = data
self.displayer_thread.start()
def show_data(self, data):
self.status_label.setText("Data displayed.")
self.data_label.setText(str(data))
if __name__ == "__main__":
app = QApplication(sys.argv)
window = MainWindow()
window.show()
sys.exit(app.exec())
以上代码主要是使用了QThread和pyqtSignal来解决这个问题。
一、QThread类提供了一种在单独的线程中执行耗时操作的方法,从而避免阻塞主线程,提高了应用程序的响应速度和用户体验,MainWindow为主线程。
二、pyqtSignal 信号用来传递变量pd.DataFrame。
在PyQt中,pyqtSignal是一个信号/槽机制,用于在不同对象之间传递消息。可以将一个自定义的pyqtSignal信号与一个槽函数连接起来,当信号发射时,槽函数会自动被调用。在这个特定的用法中,pyqtSignal(pd.DataFrame)定义了一个可以传递pd.DataFrame类型数据的信号,在需要传递pd.DataFrame类型数据时,可以使用该信号进行传递。
三、DataProcessorThread(None) 初始化的时候不传入data,在self.processor_thread.data_processed.connect 中通过信号传入data数据。
举例
以上为什么不需要传递result参数
在PyQt的信号槽机制中,当信号连接到一个槽函数时,信号会自动将传递的参数列表传递给槽函数。在前面的例子中,当DataProcessor类中的dataProcessed信号发射时,该信号会自动将传递的pd.DataFrame类型数据作为参数传递给showResult槽函数。因此,在定义showResult槽函数时,不需要显式地指定result参数。
具体来说,在定义showResult槽函数时,可以将result参数作为槽函数的一个参数进行定义。当dataProcessed信号发射时,该信号会自动将传递的pd.DataFrame类型数据作为参数传递给showResult槽函数,从而在槽函数中可以直接访问该数据。
例如,可以将showResult槽函数定义为如下形式:
class MainWindow(QWidget):
def __init__(self):
super().__init__()
self.dataProcessor = DataProcessor()
self.dataProcessor.dataProcessed.connect(self.showResult)
...
def showResult(self, result: pd.DataFrame):
# 在GUI界面上显示结果
# result是传递过来的pd.DataFrame类型数据
...
在该定义中,showResult槽函数有一个result参数,用于接收传递的pd.DataFrame类型数据。当dataProcessed信号发射时,该信号会自动将传递的pd.DataFrame类型数据作为参数传递给showResult槽函数,从而在槽函数中可以直接访问该数据。
需要注意的是,当定义槽函数时,参数列表的类型和顺序需要与信号传递的参数列表的类型和顺序一致,否则会导致传递的参数无法被正确接收和处理。
四、pd.DataFrame类型数据作为参数传递时,实际上传递的是数据。在Python中,pd.DataFrame是pandas库中用于处理表格数据的主要数据结构之一。pd.DataFrame可以包含不同类型的数据,通常被表示为一个二维的表格,其中每一列可以是不同的数据类型,例如数值、字符串、日期等。
当pd.DataFrame类型数据作为参数传递时,实际上传递的是数据的引用。即使数据非常大,也不会在传递过程中进行复制,而是直接传递数据的引用。这样可以避免数据的不必要的复制和内存占用。在槽函数中,可以直接访问传递的数据,进行相应的处理和显示。