You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

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)

    # 后续逻辑不变...

这种方式更直接,但耦合度比方案一高,推荐用方案一的解耦方式。


额外建议

  1. 尽量避免使用全局变量,改用类的实例属性,这样代码更清晰,也不容易出现变量污染的问题。
  2. 可以把所有显示的Label都做成Window类的实例属性,方便后续统一更新。
  3. 如果Excel操作比较耗时,建议把查询逻辑放到子线程里,避免阻塞GUI界面,这个可以作为后续优化方向。

内容的提问来源于stack exchange,提问作者Daan Van de Voorde

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.06 11:42:49