PyQt5跨文件Excel查询后数据传递报错:缺少self参数
解决PyQt5跨文件调用实例方法的参数错误问题
问题根源分析
你遇到的报错核心原因是:assign是Window类的实例方法,它的第一个参数必须是Window类的实例对象(也就是self),但你在file2里直接通过Window.assign(...)调用,这是把类本身当成了调用主体,导致你传入的第一个参数mg被当成了self,参数完全不匹配,所以触发错误。
另外你的代码里还有全局变量滥用的问题,这会让代码耦合度变高,也容易出问题,我们一起调整。
解决方案一:让查询函数返回结果,GUI层处理更新
这种方式更解耦,查询逻辑只负责获取数据,GUI自己处理界面更新。
修改file2(vind_gebruiker_zaterdag.py)的代码
把start函数改成返回查询到的数据(如果找到),没找到返回预设的空结果:
import openpyxl as xl wb = xl.load_workbook('mosselen 2020.xlsx', data_only=True) ws1 = wb['ZATERDAG'] ws2 = wb['ZONDAG'] def start(voornaam1, achternaam1): voornaam = voornaam1 if voornaam1 else None achternaam = achternaam1 if achternaam1 else None min_row = 5 max_row = ws1.max_row - 10 # 先查ZATERDAG工作表 for cell in ws1.iter_rows(min_row=min_row, min_col=4, max_col=5, max_row=max_row): if set((c.value for c in cell)) == {voornaam, achternaam}: row_index = cell[0].row found = "Gevonden" active_sheet = "ZATERDAG" for cell2 in ws1.iter_rows(min_row=row_index, min_col=6, max_col=33, max_row=row_index): # 处理空值 for cell3 in cell2: if cell3.value is None: cell3.value = "0" # 整理数据 betaald_status = 'al betaald' if cell2[9].value == 'j' else cell2[27].value result = { "found": found, "dag": active_sheet, "mg": cell2[0].value, "mgh": cell2[1].value, "mk": cell2[2].value, "mkh": cell2[3].value, "pg": cell2[4].value, "pgh": cell2[5].value, "pk": cell2[6].value, "pkh": cell2[7].value, "betaald": cell2[9].value, "bedrag": betaald_status } return result # 再查ZONDAG工作表 max_row = ws2.max_row - 10 for cell in ws2.iter_rows(min_row=min_row, min_col=4, max_col=5, max_row=max_row): if set((c.value for c in cell)) == {voornaam, achternaam}: row_index = cell[0].row found = "Gevonden" active_sheet = "ZONDAG" for cell2 in ws2.iter_rows(min_row=row_index, min_col=6, max_col=33, max_row=row_index): for cell3 in cell2: if cell3.value is None: cell3.value = "0" betaald_status = 'al betaald' if cell2[9].value == 'j' else cell2[27].value result = { "found": found, "dag": active_sheet, "mg": cell2[0].value, "mgh": cell2[1].value, "mk": cell2[2].value, "mkh": cell2[3].value, "pg": cell2[4].value, "pgh": cell2[5].value, "pk": cell2[6].value, "pkh": cell2[7].value, "betaald": cell2[9].value, "bedrag": betaald_status } return result # 没找到的情况 return { "found": "Niet gevonden", "dag": "", "mg": "0", "mgh": "0", "mk": "0", "mkh": "0", "pg": "0", "pgh": "0", "pk": "0", "pkh": "0", "betaald": "Nee", "bedrag": "" }
修改file1(GUI2.py)的代码
去掉全局变量,改用实例属性,然后在clicked方法里接收返回值,调用assign更新界面:
from PyQt5.QtWidgets import QApplication, QMainWindow, QLineEdit, QComboBox, QCheckBox, QSpinBox, QLabel, QMessageBox, QPushButton import sys from vind_gebruiker_zaterdag import start class Window(QMainWindow): def __init__(self): super(Window, self).__init__() self.setWindowTitle("Inschrijven Mosselen") self.setGeometry(300, 100, 700, 700) # 用实例属性代替全局变量 self.mg = "0" self.mgh = "0" self.mk = "0" self.mkh = "0" self.pg = "0" self.pgh = "0" self.pk = "0" self.pkh = "0" self.betaald = "Nee" self.found = "Niet gevonden" self.initUI() def initUI(self): self.vind_voornaam = QLineEdit(self) self.vind_voornaam.move(100, 100) self.vind_voornaam.setFixedWidth(200) self.vind_voornaam.setFixedHeight(60) font = self.vind_voornaam.font() font.setPointSize(11) self.vind_voornaam.setFont(font) self.vind_voornaam.setPlaceholderText("Voornaam") self.vind_achternaam = QLineEdit(self) self.vind_achternaam.move(350, 100) self.vind_achternaam.setFixedWidth(200) self.vind_achternaam.setFixedHeight(60) font = self.vind_achternaam.font() font.setPointSize(11) self.vind_achternaam.setFont(font) self.vind_achternaam.setPlaceholderText("achternaam") self.Input = QLabel("Input", self) self.Input.move(305, 45) font = self.Input.font() font.setPointSize(13) self.Input.setFont(font) self.Output = QLabel("Output", self) self.Output.move(300, 200) font = self.Output.font() font.setPointSize(13) self.Output.setFont(font) self.search = QPushButton("Zoek", self) self.search.move(275, 175) self.search.setFixedWidth(100) self.search.setFixedHeight(25) font = self.search.font() font.setPointSize(12) self.search.setFont(font) self.search.clicked.connect(self.clicked) self.next = QPushButton("Volgende", self) self.next.move(250, 625) self.next.setFixedWidth(200) self.next.setFixedHeight(60) font = self.next.font() font.setPointSize(12) self.next.setFont(font) self.gevonden = QLabel(f"{self.found}", self) self.gevonden.move(285, 235) font = self.gevonden.font() font.setPointSize(11) self.gevonden.setFont(font) self.mg_label = QLabel(f"Mosselen groot: {self.mg}", self) self.mg_label.move(50, 250) font = self.mg_label.font() font.setPointSize(11) self.mg_label.setFont(font) # 添加其他对应的Label self.mgh_label = QLabel(f"Mosselen groot met brood: {self.mgh}", self) self.mgh_label.move(50, 280) font = self.mgh_label.font() font.setPointSize(11) self.mgh_label.setFont(font) self.Subject = QLabel("Vind Inschrijving", self) self.Subject.move(30, 30) font = self.Subject.font() font.setPointSize(15) self.Subject.setFont(font) self.update() def assign(self, result): # 更新实例属性 self.found = result["found"] self.mg = result["mg"] self.mgh = result["mgh"] self.mk = result["mk"] self.mkh = result["mkh"] self.pg = result["pg"] self.pgh = result["pgh"] self.pk = result["pk"] self.pkh = result["pkh"] self.betaald = result["betaald"] self.bedrag = result["bedrag"] self.dag = result["dag"] # 更新界面Label self.gevonden.setText(self.found) self.mg_label.setText(f"Mosselen groot: {self.mg}") self.mgh_label.setText(f"Mosselen groot met brood: {self.mgh}") # 可继续添加其他Label的更新逻辑 self.update() def update(self): self.Subject.adjustSize() self.gevonden.adjustSize() self.mg_label.adjustSize() self.mgh_label.adjustSize() # 其他Label也调用adjustSize() def clicked(self): voornaam = self.vind_voornaam.text() achternaam = self.vind_achternaam.text() # 获取查询结果 result = start(voornaam, achternaam) # 更新界面 self.assign(result) def window(): app = QApplication(sys.argv) win = Window() win.show() sys.exit(app.exec_()) if __name__ == "__main__": window()
解决方案二:传递GUI实例给查询函数
如果你不想修改太多查询逻辑,也可以把Window的实例传递给start函数,让它直接调用实例的assign方法:
修改file1的clicked方法
def clicked(self): voornaam = self.vind_voornaam.text() achternaam = self.vind_achternaam.text() # 把当前Window实例传递给start start(voornaam, achternaam, self)
修改file2的start函数
# 修改start函数,添加gui_instance参数 def start(voornaam1, achternaam1, gui_instance): global found voornaam = voornaam1 achternaam = achternaam1 active_sheet = "" row_index = None min_row = 5 max_row = ws1.max_row - 10 if voornaam == "": voornaam = None if achternaam == "": achternaam = None # 原有的ZATERDAG查询逻辑不变... # 找到数据后直接调用gui_instance的assign方法 gui_instance.assign(mg, mgh, mk, mkh, pg, pgh, pk, pkh, betaald, dag, bedrag, found) # 原有的ZONDAG查询逻辑不变... # 找到数据后同样调用gui_instance的assign方法 gui_instance.assign(mg, mgh, mk, mkh, pg, pgh, pk, pkh, betaald, dag, bedrag, found) # 后续逻辑不变...
这种方式更直接,但耦合度比方案一高,推荐用方案一的解耦方式。
额外建议
- 尽量避免使用全局变量,改用类的实例属性,这样代码更清晰,也不容易出现变量污染的问题。
- 可以把所有显示的Label都做成
Window类的实例属性,方便后续统一更新。 - 如果Excel操作比较耗时,建议把查询逻辑放到子线程里,避免阻塞GUI界面,这个可以作为后续优化方向。
内容的提问来源于stack exchange,提问作者Daan Van de Voorde
相关产品推荐
相关产品推荐

