PySide6 应用程序中的函数重复和全局变量问题,按下按钮时打印日期和月份的函数重复

Problem with function duplication and global variables in PySide6 app, a function to print day and month is duplicated when button pressed

我是初学者,我知道我错过了一些东西,但我不知道到底是什么,所以我有一个 PySide6 应用程序,我创建了一个函数来使用日历模块在 QTableWidget 中生成日历python 一切正常,但当我尝试添加导航按钮以获取下个月和上个月时出现问题: 这是我的职能:

import sys
import os
import platform
import datetime as dt
import time
import calendar

from PySide6 import *
from PySide6 import QtGui
from PySide6 import QtWidgets
from PySide6 import QtCore
from PySide6.QtGui import QColor

from functools import partial

yy = int(dt.datetime.now().strftime("%Y"))
mm = int(dt.datetime.now().strftime("%m"))

class MainWindow(QMainWindow):
    def __init__(self):
        QMainWindow.__init__(self)
        self.ui = Ui_MainWindow()
        self.ui.setupUi(self)
        global widgets
        widgets = self.ui

        # Calender generator
        self.calender_gen(mm,yy)



    def calender_gen(self, mm_g, yy_g):
        # Creat table rows and columns
        widgets.tableWidget_3.setRowCount(5)
        widgets.tableWidget_3.setColumnCount(7)

        # Table header labels
        week_list = ["Sat","Sun","Mon","Tue","Wed","Thu","Fri"]
        widgets.tableWidget_3.setHorizontalHeaderLabels(week_list)

        # Start inserting days of the month into the table
        row = 0
        col = 0
        for week in calendar.monthcalendar(yy_g,mm_g):
            for day in week:
                if day == 0:
                    widgets.tableWidget_3.setItem(row,col,QTableWidgetItem(" "))
                else:
                    widgets.tableWidget_3.setItem(row,col,QTableWidgetItem(str(day)))
                col += 1
            row += 1
            col = 0
        print(mm_g,yy_g)
        # Connect Buttons to function
        widgets.pushButton_3.clicked.connect(partial(self.next_calendar_butt,mm_g,yy_g))
        widgets.pushButton_2.clicked.connect(partial(self.prev_calendar_butt,mm_g,yy_g))

    def next_calendar_butt(self,mm_new, yy_new):
        mm_new += 1
        if mm_new > 12:
            mm_new = 1
            yy_new += 1

        widgets.tableWidget_3.setRowCount(0)
        widgets.tableWidget_3.setColumnCount(0)
        self.calender_gen(mm_new,yy_new)

    def prev_calendar_butt(self,mm_g_new,yy_g_new):
        mm_g_new -= 1
        if mm_g_new == 0:
            mm_g_new = 12
            yy_g_new -= 1

        widgets.tableWidget_3.setRowCount(0)
        widgets.tableWidget_3.setColumnCount(0)
        self.calender_gen(mm_g_new,yy_g_new)

当我 运行 应用程序时,日历显示在 table 中,如图所示 image of the GUI table

控制台输出Console prints 11 2021

当我第一次点击 pushButton_3 时,它正常工作并在控制台中打印“12 2021” console prints 12 2021 但在我再次点击同一个按钮后,它开始复制:控制台打印“12 2021 1 2022”console prints 12 2021 1 2022 如果我再次单击它会打印图像中的 '12 2021 1 2022 1 2022 2 2022' enter image description here 每次单击它都会复制更多,它应该只打印一个语句,即 '2 2022'

我试图将以下行移出 calendar_gen() 函数,但我无法传递参数,即使在声明全局变量并将它们分配给参数之后也是如此:

widgets.pushButton_3.clicked.connect(partial(self.next_calendar_butt,mm_g,yy_g))
widgets.pushButton_2.clicked.connect(partial(self.prev_calendar_butt,mm_g,yy_g))

我试过这样做: 在 calendar_gen() 函数中,我声明了全局变量并将它们分配给函数参数,以创建类似全局参数的东西

global var_mm
global var_yy

var_mm = mm_g
var_yy = yy_g

然后在 init(self) 函数中我输入了这两行:

def __init__(self):
    widgets.pushButton_3.clicked.connect(partial(self.next_calendar_butt,var_mm,var_yy))
    widgets.pushButton_2.clicked.connect(partial(self.prev_calendar_butt,var_mm,var_yy))

但这在控制台中不起作用,当我 运行 应用程序时,它会打印“11 2021”,然后当我单击 pushButton_3 时,它会打印“12 2021”,当我再次单击时在上面,它再次打印“12 2021”等等 与另一个按钮一样,它一次又一次地打印“10 2021”

Qt 信号连接不是独占的(默认情况下),一个信号可以多次连接到同一个函数。

由于您正在连接 calender_gen 中按钮的 clicked 信号,因此每次调用该函数时,您都会添加一个 进一步 连接到那些信号。结果是每次发出信号时,连接的函数将被调用的次数与它们连接的次数一样多。

一个正确的解决方案是连接到可以切换月份的函数并保留对当前月份的引用以进行“新”月份计算。

由于函数几乎相同,最好将它们分组到一个独特的函数中,然后将信号连接到单独的函数,这些函数最终会使用适当的参数调用前一个函数:

class MainWindow(QMainWindow):
    def __init__(self):
        # ...
        self.calender_gen(mm,yy)

        self.pushButton_2.clicked.connect(self.prev_month)
        self.pushButton_3.clicked.connect(self.next_month)

    def calender_gen(self, mm_g, yy_g):
        # Creat table rows and columns
        self.tableWidget_3.setRowCount(5)
        self.tableWidget_3.setColumnCount(7)

        # Table header labels
        week_list = ["Sat","Sun","Mon","Tue","Wed","Thu","Fri"]
        self.tableWidget_3.setHorizontalHeaderLabels(week_list)

        # Start inserting days of the month into the table
        row = 0
        col = 0
        for week in calendar.monthcalendar(yy_g,mm_g):
            for day in week:
                if day == 0:
                    self.tableWidget_3.setItem(row,col,QTableWidgetItem(" "))
                else:
                    self.tableWidget_3.setItem(row,col,QTableWidgetItem(str(day)))
                col += 1
            row += 1
            col = 0

        self.current_month = mm_g
        self.current_year = yy_g

    def prev_month(self):
        self.step_month(-1)

    def next_month(self):
        self.step_month(1)

    def step_month(self, delta):
        mm_new = self.current_month + delta
        mm_year = self.current_year
        if mm_new > 12:
            mm_new = 1
            mm_year += 1
        elif mm_new < 1:
            mm_new = 12
            mm_year -= 1

        self.calender_gen(mm_new, mm_year)

显然,正确实施 QCalendarWidget 可能要简单得多,因为它已经提供了大部分功能。