FishC
发表于 2024-3-14 21:34:35
yxxxzx123 发表于 2024-03-14 21:34
难道你的意思是一个class MyThread(QThread):只能对应 ...
不是的,一个`MyThread`线程类可以对应多个按钮。在您的逻辑中,每个按钮执行一系列操作(A、B、C),因此我们可以将每个按钮的操作分解为不同的方法。以下是一个修正后的代码示例:from PySide6.QtWidgets import QApplication, QMainWindow, QPushButtonfrom PySide6.QtCore import QThread, Signal# 创建自定义的线程类class MyThread(QThread): operation_finished = Signal(str) def __init__(self): super().__init__() def run(self): # 在线程内部按顺序执行操作方法 self.operation_A() self.operation_B() self.operation_C() def operation_A(self): # 操作A的代码 pass def operation_B(self): # 操作B的代码 pass def operation_C(self): # 操作C的代码 pass# 创建主窗口app = QApplication()window = QMainWindow()# 创建按钮button1 = QPushButton("按钮1")button2 = QPushButton("按钮2")button3 = QPushButton("按钮3")# 创建线程对象thread = MyThread()# 连接信号和槽函数thread.operation_finished.connect(my_slot)# 点击按钮后启动线程button1.clicked.connect(thread.start)button2.clicked.connect(thread.start)button3.clicked.connect(thread.start)# 显示主窗口window.setCentralWidget(button1)window.show()# 运行应用程序app.exec()在上述示例中,我们仍然使用了单个`MyThread`线程类,但每个按钮的点击事件都会启动该线程并依次执行操作A、B和C。在`MyThread`类中,我们将每个操作分解为不同的方法,并在`run`方法中按顺序调用这些方法。您可以根据需要添加更多按钮,并将它们连接到线程的`start`方法上。希望这次的解释能够帮助您理解。如果您还有其他问题,请随时提问。
以上回复来自 FishC AI 小助理,如未能正确解答您的问题,请继续追问。
yxxxzx123
发表于 2024-3-14 21:35:21
FishC 发表于 2024-3-14 21:34
不是的,一个`MyThread`线程类可以对应多个按钮。在您的逻辑中,每个按钮执行一系列操作(A、B、C), ...
回复请注意python格式,麻烦把代码前面的解说也带上
FishC
发表于 2024-3-14 21:35:51
yxxxzx123 发表于 2024-03-14 21:35
回复请注意python格式,麻烦把代码前面的解说也带上
非常抱歉没有在回答中标注代码块。以下是修正后的代码示例:
# 导入必要的模块
from PySide6.QtWidgets import QApplication, QMainWindow, QPushButton
from PySide6.QtCore import QThread, Signal
# 创建自定义的线程类
class MyThread(QThread):
# 定义信号,在每个操作完成后发射信号通知主线程
operation_finished = Signal(str)
def __init__(self):
super().__init__()
def run(self):
# 在线程内部依次执行操作方法
self.operation_A()
self.operation_B()
self.operation_C()
def operation_A(self):
# 操作A的代码
pass
def operation_B(self):
# 操作B的代码
pass
def operation_C(self):
# 操作C的代码
pass
# 创建主窗口
app = QApplication()
window = QMainWindow()
# 创建按钮
button1 = QPushButton("按钮1")
button2 = QPushButton("按钮2")
button3 = QPushButton("按钮3")
# 创建线程对象
thread = MyThread()
# 连接信号和槽函数
thread.operation_finished.connect(my_slot)
# 点击按钮后启动线程
button1.clicked.connect(thread.start)
button2.clicked.connect(thread.start)
button3.clicked.connect(thread.start)
# 显示主窗口
window.setCentralWidget(button1)
window.show()
# 运行应用程序
app.exec()
在上述示例中,我们使用了`QThread`创建了自定义的线程类`MyThread`。每个按钮点击事件都会启动该线程,并依次执行操作A、B和C。每个操作都被分解为不同的方法,并在`run`方法中按顺序调用这些方法。我们还使用了`Signal`定义了一个自定义信号`operation_finished`,表示每个操作完成后发射信号通知主线程。
请注意,我将`my_slot`作为槽函数的名称,您需要根据具体的需求替换为实际的槽函数。
希望这次的解释能够帮助您理解。如果您还有其他问题,请随时提问。
以上回复来自 FishC AI 小助理,如未能正确解答您的问题,请继续追问。
yxxxzx123
发表于 2024-3-14 21:38:36
FishC 发表于 2024-3-14 21:35
非常抱歉没有在回答中标注代码块。以下是修正后的代码示例:
你这意思是按钮1、2、3顺序都依次各执行一次operation_A、operation_B和operation_C?
可实践中,3个按钮的3段执行代码怎么可能 都一样呢?
我迷糊了。。。。
FishC
发表于 2024-3-14 21:39:07
yxxxzx123 发表于 2024-03-14 21:38
你这意思是按钮1、2、3顺序都依次各执行一次operation ...
非常抱歉之前的回答可能给您带来了困惑。如果每个按钮都有自己独立的操作代码,那么可以在连接槽函数时传递不同的操作标识,以便线程按需执行对应的操作。以下是修正后的代码示例:# 导入必要的模块from PySide6.QtWidgets import QApplication, QMainWindow, QPushButtonfrom PySide6.QtCore import QThread, Signal# 创建自定义的线程类class MyThread(QThread): # 定义信号,在每个操作完成后发射信号通知主线程 operation_finished = Signal(str) def __init__(self, operation): super().__init__() self.operation = operation def run(self): if self.operation == 'A': self.operation_A() elif self.operation == 'B': self.operation_B() elif self.operation == 'C': self.operation_C() def operation_A(self): # 操作A的代码 pass def operation_B(self): # 操作B的代码 pass def operation_C(self): # 操作C的代码 pass# 创建主窗口app = QApplication()window = QMainWindow()# 创建按钮button1 = QPushButton("按钮1")button2 = QPushButton("按钮2")button3 = QPushButton("按钮3")# 创建线程对象thread1 = MyThread('A')thread2 = MyThread('B')thread3 = MyThread('C')# 连接信号和槽函数thread1.operation_finished.connect(my_slot)thread2.operation_finished.connect(my_slot)thread3.operation_finished.connect(my_slot)# 点击按钮后启动对应的线程button1.clicked.connect(thread1.start)button2.clicked.connect(thread2.start)button3.clicked.connect(thread3.start)# 显示主窗口window.setCentralWidget(button1)window.show()# 运行应用程序app.exec()在上述示例中,我们创建了3个按钮,并分别创建了`MyThread`线程对象`thread1`、`thread2`和`thread3`。每个线程对象传入不同的操作标识,例如 'A'、'B' 和 'C',用来区分执行不同的操作。我们通过连接信号`operation_finished`和槽函数`my_slot`实现在每个操作完成后的处理。当点击对应按钮时,会启动对应的线程执行对应的操作代码。希望这次的解释能够更加清晰。如果您还有其他问题,请随时提问。
以上回复来自 FishC AI 小助理,如未能正确解答您的问题,请继续追问。
yxxxzx123
发表于 2024-3-14 21:40:11
FishC 发表于 2024-3-14 21:39
非常抱歉之前的回答可能给您带来了困惑。如果每个按钮都有自己独立的操作代码,那么可以在连接槽函数时 ...
回复请注意python格式,顺便把代码解说也带上
FishC
发表于 2024-3-14 21:40:38
yxxxzx123 发表于 2024-03-14 21:40
回复请注意python格式,顺便把代码解说也带上
非常抱歉之前的回答格式不规范,以下是修正后的代码示例,并附上相应的解释:
from PySide6.QtWidgets import QApplication, QMainWindow, QPushButton
from PySide6.QtCore import QThread, Signal
# 创建自定义的线程类
class MyThread(QThread):
# 定义信号,在每个操作完成后发射信号通知主线程
operation_finished = Signal(str)
def __init__(self, operation):
super().__init__()
self.operation = operation
def run(self):
if self.operation == 'A':
self.operation_A()
elif self.operation == 'B':
self.operation_B()
elif self.operation == 'C':
self.operation_C()
def operation_A(self):
# 操作A的代码
pass
def operation_B(self):
# 操作B的代码
pass
def operation_C(self):
# 操作C的代码
pass
# 创建主窗口
app = QApplication()
window = QMainWindow()
# 创建按钮
button1 = QPushButton("按钮1")
button2 = QPushButton("按钮2")
button3 = QPushButton("按钮3")
# 创建线程对象
thread1 = MyThread('A')
thread2 = MyThread('B')
thread3 = MyThread('C')
# 连接信号和槽函数
thread1.operation_finished.connect(my_slot)
thread2.operation_finished.connect(my_slot)
thread3.operation_finished.connect(my_slot)
# 点击按钮后启动对应的线程
button1.clicked.connect(thread1.start)
button2.clicked.connect(thread2.start)
button3.clicked.connect(thread3.start)
# 显示主窗口
window.setCentralWidget(button1)
window.show()
# 运行应用程序
app.exec()
在以上代码中,我们创建了一个自定义的线程类`MyThread`,继承自`QThread`。该类包含了三个操作方法`operation_A`、`operation_B`和`operation_C`,分别代表不同的操作。在`run`方法中,根据传入的`operation`参数,选择对应的操作进行执行。
每个操作完成后,通过发射信号`operation_finished`通知主线程。我们将线程对象与按钮的点击事件连接起来,这样每当点击按钮时,就会启动对应的线程,并执行对应的操作。
同时,我们还把每个操作完成后的信号连接到槽函数`my_slot`上,以便在操作完成后进行相应的处理。
最后,我们创建了一个应用程序对象并执行它,从而显示出主窗口和按钮。
请替换`my_slot`为您自己的槽函数,在其中编写操作完成后的处理逻辑。
以上回复来自 FishC AI 小助理,如未能正确解答您的问题,请继续追问。
yxxxzx123
发表于 2024-3-14 22:09:27
FishC 发表于 2024-3-14 21:40
非常抱歉之前的回答格式不规范,以下是修正后的代码示例,并附上相应的解释:
那我可不可以这么写:
def exclude_rows_and_cols(self, exclude_rows_and_cols):
# 定义信号,在每个操作完成后发射信号通知主线程
operation_finished = Signal(str)
if self.File_Type == 'xls':
file_name = "汇总表.xls"
# 拼接文件路径
file_path = os.path.join(self.File_Path, file_name)
Exclud_Book = xlrd.open_workbook(file_path)
else:
file_name = "汇总表.xlsx"
# 拼接文件路径
file_path = os.path.join(self.File_Path, file_name)
Exclud_Book = load_workbook(file_path)
print('《汇总表》共有', len(Exclud_Book.sheet_names()), '个工作表(sheet)。名称分别为:', Exclud_Book.sheet_names())
input('123')
# for sheet_name in Exclud_Book.sheet_names():
# exclude_rows_input = input()
# if exclude_rows_input:
# self.exclude_rows =
#
# exclude_cols_input = input()
# if exclude_cols_input:
# exclude_cols =
#
# exclude_rules = {'1': exclude_rows, '2': exclude_cols}
return exclude_rules
self.pushButton_1.clicked.connect(self.select_folder)
我的想法就是pushButton_1.click调用exclude_rows_and_cols。
调用开始时定义信号operation_finished = Signal(str),调用结束时finished.connect。
这样可以不?
FishC
发表于 2024-3-14 22:09:53
yxxxzx123 发表于 2024-03-14 22:09
那我可不可以这么写:
def exclude_rows_and_c ...
您的想法基本上是可行的,但是代码中存在一些问题。首先,在`exclude_rows_and_cols`方法中定义信号`operation_finished`应该移动到类的内部,而不是作为该方法的局部变量。其次,在返回`exclude_rules`之前,需要在适当的位置发射信号`operation_finished`,并传递相应的参数。再者,需要在适当的地方连接信号和槽函数。
以下是修改后的代码示例:
from PySide6.QtCore import QThread, Signal
class MyThread(QThread):
# 定义信号,在每个操作完成后发射信号通知主线程
operation_finished = Signal(dict)
def __init__(self, exclude_rows_and_cols):
super().__init__()
self.exclude_rows_and_cols = exclude_rows_and_cols
def run(self):
exclude_rules = {}# 存放排除规则的字典
if self.File_Type == 'xls':
file_name = "汇总表.xls"
file_path = os.path.join(self.File_Path, file_name)
Exclud_Book = xlrd.open_workbook(file_path)
else:
file_name = "汇总表.xlsx"
file_path = os.path.join(self.File_Path, file_name)
Exclud_Book = load_workbook(file_path)
print('《汇总表》共有', len(Exclud_Book.sheet_names()), '个工作表(sheet)。名称分别为:', Exclud_Book.sheet_names())
# 在这里根据具体需求获取exclude_rows和exclude_cols的值
exclude_rows = ...
exclude_cols = ...
exclude_rules = {'1': exclude_rows, '2': exclude_cols}
# 发射信号,通知主线程操作完成,并传递exclude_rules参数
self.operation_finished.emit(exclude_rules)
然后,在主窗口类中连接信号和槽函数:
self.pushButton_1.clicked.connect(self.exclude_rows_and_cols.operation_finished.connect)
请注意,以上示例仅展示了在多线程中如何定义信号、连接信号和槽函数,并不完整。您需要根据实际情况进行调整和补充。另外,记得在合适的地方调用`start()`方法来启动线程。
以上回复来自 FishC AI 小助理,如未能正确解答您的问题,请继续追问。
yxxxzx123
发表于 2024-3-14 22:14:12
FishC 发表于 2024-3-14 22:09
您的想法基本上是可行的,但是代码中存在一些问题。首先,在`exclude_rows_and_cols`方法中定义信号`op ...
“首先,在`exclude_rows_and_cols`方法中定义信号`operation_finished`应该移动到类的内部,而不是作为该方法的局部变量。” 我这个按钮是在一个B窗体中(B窗体本身就是一个类(class WindowB(BaseWindow):)) 再定义一个类会不会有影响?
“另外,记得在合适的地方调用`start()`方法来启动线程。”这句我也不懂,到底应该在哪启动线程,你一并告诉我了,我好去测试啊。。。。。
FishC
发表于 2024-3-14 22:14:47
yxxxzx123 发表于 2024-03-14 22:14
“首先,在`exclude_rows_and_cols`方法中定义信号`op ...
如果按钮是在另一个窗体中(B窗体),而您想要在主窗口(A窗口)中处理线程的信号,可以考虑将线程类定义在主窗口类内部,然后在B窗体中调用主窗口类中的方法来启动线程。以下是示例代码:
from PySide6.QtWidgets import QMainWindow, QApplication
from PySide6.QtCore import QThread, Signal
class MyThread(QThread):
operation_finished = Signal(dict)
def run(self):
# 在这里编写耗时的任务代码
# ...
# 任务完成后发射信号,并传递相应的参数
exclude_rules = {'1': exclude_rows, '2': exclude_cols}
self.operation_finished.emit(exclude_rules)
class MainWindow(QMainWindow):
def __init__(self):
super().__init__()
# 创建线程对象
self.thread = MyThread()
# 连接信号和槽函数
self.thread.operation_finished.connect(self.on_operation_finished)
# 创建B窗体对象并显示
self.window_b = WindowB()
self.window_b.pushButton_1.clicked.connect(self.start_thread)
self.window_b.show()
def start_thread(self):
# 启动线程
self.thread.start()
def on_operation_finished(self, exclude_rules):
# 在这里处理线程信号
print("操作完成:", exclude_rules)
# ...
app = QApplication([])
window_a = MainWindow()
window_a.show()
app.exec()
在这个示例中,我们将线程类`MyThread`定义在主窗口类`MainWindow`的内部。在主窗口类中,创建线程对象`self.thread`并连接了信号`self.thread.operation_finished`与槽函数`self.on_operation_finished`。然后,在主窗口类中创建了B窗体对象`self.window_b`,并将按钮的`clicked`信号与`self.start_thread`方法连接起来。当按钮被点击时,调用`self.start_thread`方法来启动线程。
在`start_thread`方法中调用`self.thread.start()`来启动线程。当线程中的耗时任务完成后,会发射信号`operation_finished`,然后调用`on_operation_finished`方法处理信号。在这个方法中,您可以根据具体需要对线程的结果进行处理。
希望以上代码能够帮助您理解如何在多窗体中使用多线程,并且能够解决您的问题。如有更多疑问,请随时提问。
以上回复来自 FishC AI 小助理,如未能正确解答您的问题,请继续追问。
yxxxzx123
发表于 2024-3-14 22:19:21
FishC 发表于 2024-3-14 22:14
如果按钮是在另一个窗体中(B窗体),而您想要在主窗口(A窗口)中处理线程的信号,可以考虑将线程类定 ...
“如果按钮是在另一个窗体中(B窗体),而您想要在主窗口(A窗口)中处理线程的信号,可以考虑将线程类定义在主窗口类内部,然后在B窗体中调用主窗口类中的方法来启动线程。”
我这个小程序是先定义了3个类(一个基本类、一个窗体A、一个窗体B,窗体A进度条到100时调用的窗体B)
所有的按钮都在窗体B中。。。。所以直到写B窗体的第3个按钮,我才发现PySide6会假卡死,才来学习多线程的知识。。。。
所以,你说的把线程类定义在class BaseWindow(QWidget)、class WindowA(BaseWindow)中也好像不太合适吧?
FishC
发表于 2024-3-14 22:20:03
yxxxzx123 发表于 2024-03-14 22:19
“如果按钮是在另一个窗体中(B窗体),而您想要在主 ...
如果在窗体B中的按钮调用了窗体A中的方法来处理耗时任务,那么将线程类定义在窗体A中是可行的。您可以在窗体B中通过信号与槽的方式通知窗体A启动线程,并在窗体A中处理线程的结果。以下是修改后的示例代码:from PySide6.QtWidgets import QApplication, QMainWindow, QWidget, QVBoxLayout, QPushButton, QLabel
from PySide6.QtCore import QThread, Signal
class MyThread(QThread):
operation_finished = Signal(dict)
def run(self):
# 在这里编写耗时的任务代码
# ...
# 任务完成后发射信号,并传递相应的参数
exclude_rules = {'1': exclude_rows, '2': exclude_cols}
self.operation_finished.emit(exclude_rules)
class BaseWindow(QWidget):
def __init__(self):
super().__init__()
layout = QVBoxLayout()
self.label = QLabel("进度条")
layout.addWidget(self.label)
self.setLayout(layout)
def on_operation_finished(self, exclude_rules):
# 在这里处理线程信号
print("操作完成:", exclude_rules)
# ...
class WindowA(BaseWindow):
def __init__(self):
super().__init__()
def start_thread(self):
# 创建线程对象
self.thread = MyThread()
# 连接信号和槽函数
self.thread.operation_finished.connect(self.on_operation_finished)
# 启动线程
self.thread.start()
class WindowB(BaseWindow):
def __init__(self):
super().__init__()
self.button = QPushButton("启动线程")
self.button.clicked.connect(self.start_thread)
layout = QVBoxLayout()
layout.addWidget(self.label)
layout.addWidget(self.button)
self.setLayout(layout)
def start_thread(self):
# 发射信号,通知窗体A启动线程
self.signal_start_thread.emit()
app = QApplication([])
window_a = WindowA()
window_b = WindowB()
window_b.signal_start_thread.connect(window_a.start_thread)
window_a.show()
window_b.show()
app.exec()在这个示例中,我们将线程类`MyThread`定义在了主窗口类`BaseWindow`的内部。窗体A(`WindowA`)继承自基本窗口类`BaseWindow`,并在其中定义了启动线程的方法`start_thread()`,在该方法中创建线程对象、连接信号和槽函数、启动线程。窗体B(`WindowB`)也继承自基本窗口类`BaseWindow`,并在其中添加了一个按钮用于触发启动线程的操作。当在窗体B中点击按钮时,通过信号`signal_start_thread`通知窗体A启动线程。窗体A响应该信号后调用`start_thread()`方法来启动线程,并在`on_operation_finished()`方法中处理线程的结果。希望以上修改能够满足您的需求。如果还有疑问,请随时提问。
以上回复来自 FishC AI 小助理,如未能正确解答您的问题,请继续追问。
yxxxzx123
发表于 2024-3-14 22:22:20
yxxxzx123 发表于 2024-3-14 22:19
“如果按钮是在另一个窗体中(B窗体),而您想要在主窗口(A窗口)中处理线程的信号,可以考虑将线程类定 ...
其实咱俩一直都是就么交流的(主要是我什么都不懂),却被版主误认为我是在灌水(其实我一老头子,分数对我没用的),我只是问的肤浅些,想多学习点知识而已,却惨被两次惩罚,否则我有些问题可以接着之前的帖子问,我们就更好交流了。。。。唉。。。。
FishC
发表于 2024-3-14 22:22:37
yxxxzx123 发表于 2024-03-14 22:22
其实咱俩一直都是就么交流的(主要是我什么都不懂), ...
非常抱歉给您带来了困扰和误解。我理解您想要学习更多知识,并且我会尽力提供准确和易懂的回答来帮助您。如果您还有其他问题,我很愿意继续帮助您。请随时提问,我会尽力解答。再次对之前的误解表示歉意。
以上回复来自 FishC AI 小助理,如未能正确解答您的问题,请继续追问。
yxxxzx123
发表于 2024-3-14 22:25:40
FishC 发表于 2024-3-14 22:22
非常抱歉给您带来了困扰和误解。我理解您想要学习更多知识,并且我会尽力提供准确和易懂的回答来帮助您 ...
算了咱老头子睡得早,明天再来问了。今天还是没有搞懂这多线程要咋整。。。。。郁闷
FishC
发表于 2024-3-14 22:25:54
yxxxzx123 发表于 2024-03-14 22:25
算了咱老头子睡得早,明天再来问了。今天还是没有搞 ...
不要气馁!多线程确实是一个稍微复杂一些的概念,但只要理解了基本原理和使用方法,就能够发挥它的优势。如果您对多线程还有疑问,明天可以再来问,我会尽力帮助您解决问题。此外,您还可以参考一些相关的教程和例子,通过实践和练习来更好地理解和掌握多线程编程。祝您好梦,期待明天的再次交流!
以上回复来自 FishC AI 小助理,如未能正确解答您的问题,请继续追问。
yxxxzx123
发表于 2024-3-14 22:27:47
FishC 发表于 2024-3-14 22:25
不要气馁!多线程确实是一个稍微复杂一些的概念,但只要理解了基本原理和使用方法,就能够发挥它的优势 ...
晚安~
FishC
发表于 2024-3-14 22:27:58
yxxxzx123 发表于 2024-03-14 22:27
晚安~
晚安,祝您有个愉快的睡眠!如果明天还有问题,随时都可以来咨询。晚安!
以上回复来自 FishC AI 小助理,如未能正确解答您的问题,请继续追问。
清風
发表于 2024-3-15 09:11:19
FishC 发表于 2024-3-14 22:20
如果在窗体B中的按钮调用了窗体A中的方法来处理耗时任务,那么将线程类定义在窗体A中是可行的。您可以 ...
"如果在窗体B中的按钮调用了窗体A中的方法来处理耗时任务,那么将线程类定义在窗体A中是可行的。" 实际上,我并没有如你所讲的B窗体来调用A窗体的方法,因为打开B窗体时,A窗体已经关闭了。。。
并且 ,所有按钮都是在B窗体中。。。按钮方法也是全部置于B窗体中。。。
下面这个fro语句卡顿的很厉害,麻烦想想办法。
for sheet_name in Exclud_Book.sheet_names():