写一个class Worker(QtCore.QRunnable):,用它调用函数并传入参数运行,运行时显示一个进度条窗口,函数运行结束后进度条关闭。一开始在run方法中创建进度条窗口,窗口无法显示。应当在__init__中创建窗口,确保在实例化时就创建了窗口:
from PyQt5 import QtCore, QtWidgets
class Worker(QtCore.QRunnable):
result_signal = QtCore.pyqtSignal(object) # 定义一个信号,用于发送结果
def __init__(self, function, *args, **kwargs):
super(Worker, self).__init__()
self.function = function
self.args = args
self.kwargs = kwargs
# 在init中创建进度条窗口,确保在 Worker 实例化时就创建了进度条窗口
self.progress_dialog = QtWidgets.QProgressDialog()
self.progress_dialog.setRange(0, 0)
self.progress_dialog.setLabelText("Running...")
self.progress_dialog.show()
def run(self):
# 调用函数并获取结果
result = self.function(*self.args, **self.kwargs)
# 发射结果信号
self.result_signal.emit(result)
self.progress_dialog.close()
# 示例带参数的函数
def example_function_with_args(arg1, arg2):
import time
time.sleep(5)
return f"Function completed with args: {arg1}, {arg2}" # 返回一个带参数的示例结果
# 在主函数中使用Worker类来调用带参数的函数并处理结果
if __name__ == "__main__":
import sys
app = QtWidgets.QApplication(sys.argv)
worker = Worker(example_function_with_args, "arg1_value", "arg2_value")
worker.result_signal.connect(lambda result: print(f"Result: {result}")) # 连接信号到处理函数
QtCore.QThreadPool.globalInstance().start(worker)
sys.exit(app.exec_())
然而,这样的写法在具有主窗口的GUI界面有可能会导致进度条窗口卡死。通过断点设置,查到是在self.progress_dialog.close()处卡死,这可能是因为在非主线程中尝试操作 GUI 元素导致的问题。在 PyQt 中,GUI 元素应该只能在主线程中进行操作,否则会导致程序出现不可预测的行为。为了解决这个问题,可以使用信号与槽机制来在工作线程中发出信号,然后在主线程中接收信号并关闭进度条窗口。这样就可以避免在非主线程中操作 GUI 元素导致的问题。
以下是一个使用信号与槽机制来关闭进度条窗口的示例代码:
from PyQt5 import QtCore, QtWidgets
class Worker(QtCore.QRunnable):
result_signal = QtCore.pyqtSignal(object) # 定义一个信号,用于发送结果
close_signal = QtCore.pyqtSignal() # 定义一个信号,用于关闭进度条窗口
def __init__(self, function, *args, **kwargs):
super(Worker, self).__init__()
self.function = function
self.args = args
self.kwargs = kwargs
self.progress_dialog = QtWidgets.QProgressDialog()
self.progress_dialog.setRange(0, 0)
self.progress_dialog.setLabelText("Running...")
self.progress_dialog.show()
def run(self):
# 调用函数并获取结果
result = self.function(*self.args, **self.kwargs)
# 发射结果信号
self.result_signal.emit(result)
# 发射关闭信号
self.close_signal.emit()
# 示例带参数的函数
def example_function_with_args(arg1, arg2):
return f"Function completed with args: {arg1}, {arg2}" # 返回一个带参数的示例结果
# 在主函数中使用Worker类来调用带参数的函数并处理结果
if __name__ == "__main__":
import sys
app = QtWidgets.QApplication(sys.argv)
worker = Worker(example_function_with_args, "arg1_value", "arg2_value")
worker.result_signal.connect(lambda result: print(f"Result: {result}")) # 连接结果信号到处理函数
worker.close_signal.connect(worker.progress_dialog.close) # 连接关闭信号到关闭进度条窗口函数
QtCore.QThreadPool.globalInstance().start(worker)
sys.exit(app.exec_())