如何在 python tkinter 中跨动态小部件应用相同的更改?

How do I apply the same change across dynamic widgets in python tkinter?

我有以下代码可以根据数据库中保存的某个位置的橄榄球运动员数量创建动态复选框:

#Dynamic Checkboxes
connectDB = sqlite3.connect("H:\Python\Uned_5\Databases\CDRR.db")
Cursor = connectDB.cursor()
Cursor.execute("SELECT firstName, surname FROM firstTeam WHERE position = 'Prop'")
nameResult = Cursor.fetchall()

for j in range(len(nameResult)):
    theText = nameResult[j]
    propCheckbutton = Checkbutton(framePropCheck, text = theText, bg = theBlue, fg = theWhite, font = ("calibri", 13), state = DISABLED)
    propCheckbutton.grid(row = 0, column = j)

重复此代码为每个橄榄球位置创建动态复选框。

当您单击与玩家位置关联的按钮时,它会运行一个功能,该功能会禁用除您单击的位置之外的所有复选框(将其视为过滤掉玩家位置的按钮)。例如,如果我按下“道具”按钮,除了包含在道具位置玩的玩家的复选框之外,所有其他复选框都将被禁用。

这是与按钮相关的代码:

propButton = Button(framePosition, text = "Props", bg = theGray, fg = theWhite, font = ("calibri", 13), command = selectProps)
propButton.grid(row = 0, column = 0)

这是它导致的功能:

def selectProps():    
    try:
        propCheckbutton.config(state = NORMAL)
        hookerCheckbutton.config(state = DISABLED)
        lockCheckbutton.config(state = DISABLED)
        wingerCheckbutton.config(state = DISABLED)
        scrumCheckbutton.config(state = DISABLED)
        flyCheckbutton.config(state = DISABLED)
        centreCheckbutton.config(state = DISABLED)
        fullCheckbutton.config(state = DISABLED)
    except NameError:
        pass

当数据库中存储的每个位置只有 1 名球员时,一切正常,但一旦将第二名球员添加到与现有球员相同的位置,.config 仅适用于最新的动态复选框。 例如,如果我有 2 个玩家在道具位置,第一个道具仍然会跟随:

propCheckbutton = Checkbutton(framePropCheck, text = theText, bg = theBlue, fg = theWhite, font = ("calibri", 13), state = DISABLED)

而第二个道具将紧随其后:

propCheckbutton.config(state = NORMAL)

有没有办法让 propCheckbutton.config(state = NORMAL) 应用于所有动态复选框?

这是最小的、可复制的示例,应该适用于其他想要查看此问题的人:

from tkinter import *
import sqlite3
import sys
import os
pathname = os.path.dirname(sys.argv[0])

#This function only applies this propCheckbutton.config to the latest checkbox created 
def selectProps():    
    try:
        propCheckbutton.config(state = NORMAL)
        hookerCheckbutton.config(state = DISABLED)
    except NameError:
        pass

def selectHookers():
    try:
        propCheckbutton.config(state = DISABLED)
        hookerCheckbutton.config(state = NORMAL)
    except NameError:
        pass

#Creating a basic tkinter window
Window = Tk()
Window.geometry("700x700")

#Creating the table in database
connectDB = sqlite3.connect(pathname + "\CDRR.db")
Cursor = connectDB.cursor()
Cursor.execute(
    """CREATE TABLE IF NOT EXISTS firstTeam(
        firstName text,
        surname text,
        position text
        )""")

#Inserting the data quickly and making sure the same data isn't inserted twice
normalText = str.maketrans("(),'[]",6*" ")
insertValues = ("INSERT INTO firstTeam (firstName, surname, position) VALUES (?, ?, ?)")
selectValues = ("SELECT firstName FROM firstTeam WHERE firstName = ?")
Cursor.execute(selectValues, [("Johnny")])
prop_1 = Cursor.fetchall()
prop_1 = str(prop_1)
prop_1.translate(normalText)
prop_1 = prop_1.strip()
if "Johnny" not in prop_1:
    Cursor.execute(insertValues, [("Johnny"), ("Silverhand"), ("Prop")])
else:
    pass

Cursor.execute(selectValues, [("Jackie")])
prop_2 = Cursor.fetchall()
prop_2 = str(prop_2)
prop_2.translate(normalText)
prop_2 = prop_2.strip()
if "Jackie" not in prop_2:
    Cursor.execute(insertValues, [("Jackie"), ("Welles"), ("Prop")])
else:
    pass

Cursor.execute(selectValues, [("Dexter")])
hooker_1 = Cursor.fetchall()
hooker_1 = str(hooker_1)
hooker_1.translate(normalText)
hooker_1 = hooker_1.strip()
if "Dexter" not in hooker_1:
    Cursor.execute(insertValues, [("Dexter"), ("DeShawn"), ("Hooker")])
else:
    pass

connectDB.commit()

#Buttons
propButton = Button(Window, text = "Props", command = selectProps)
propButton.grid(row = 0, column = 0)

hookerButton = Button(Window, text = "Hookers", command = selectHookers)
hookerButton.grid(row = 0, column = 1)

#Dynamic Checkboxes
Cursor.execute("SELECT firstName, surname FROM firstTeam WHERE position = 'Prop'")
nameResult = Cursor.fetchall()

for j in range(len(nameResult)):
    theText = nameResult[j]
    propCheckbutton = Checkbutton(Window, text = theText, state = DISABLED)
    propCheckbutton.grid(row = 1, column = j)

Cursor.execute("SELECT firstName, surname FROM firstTeam WHERE position = 'Hooker'")
nameResult = Cursor.fetchall()

for j in range(len(nameResult)):
    theRow = 0
    theText = nameResult[j]
    hookerCheckbutton = Checkbutton(Window, text = theText, state = DISABLED)
    hookerCheckbutton.grid(row = 2, column = j)

Window.mainloop()

感谢您的任何建议。

您需要使用 dictionary 来按 position 分组存储那些 Checkbutton 小部件,然后您可以轻松地 enable/disable 您想要的东西:

# enable the checkbuttons with given position
def select_position(position):
    for pos, players in buttons.items():
        for player in players:
            player.config(state=NORMAL if pos == position else DISABLED)

#Buttons
propButton = Button(Window, text="Props", command=lambda: select_position("Prop"))
propButton.grid(row=0, column=0)

hookerButton = Button(Window, text="Hookers", command=lambda: select_position("Hooker"))
hookerButton.grid(row=0, column=1)

buttons = {} # store the checkbuttons group by position

#Dynamic Checkboxes
for i, position in enumerate(["Prop", "Hooker"]):
    Cursor.execute("SELECT firstName, surname FROM firstTeam WHERE position = ?", (position,))
    nameResult = Cursor.fetchall()

    buttons[position] = []
    for j, theText in enumerate(nameResult):
        cb = Checkbutton(Window, text=theText, state=DISABLED)
        cb.grid(row=i+1, column=j)
        buttons[position].append(cb)