检查特定的 Checkbutton 也会检查 Tkinter 中的另一个复选框

Checking a particular Checkbutton also checks another checkbox in Tkinter

我 运行 在测试我的复选框时遇到了这个问题。

当我选中 显示提示 复选框时,字数 也会选中,反之亦然。

不知道它们之间有什么关系。这是我的代码。

import tkinter as tk

COLOUR = 'grey80'
WORDS = ['motor', 'anaconda', 'supervise', 'walnut', 'manicure', 'acre']
gui = tk.Tk()

# Root Interface
gui.geometry('720x480')
gui.title('Password Generator')
gui.resizable(0, 0)
gui.configure(bg = COLOUR)

frame_header = tk.Frame(bg='black')
tk.Label(text = 'Password Generator', font = 'Helvetica 30 bold', bg = 'black', fg='white').pack(ipady=10, fill='both')
tk.Label(text = 'A Password Generator based on Diceware', font = 'arial 11', bg = 'black', fg='white').pack(fil='both')
frame_header.pack(fill='both')

tk.Label(text= '', width = 70, height = 3, borderwidth = 2, relief = tk.SUNKEN).pack(pady=5)
tk.Checkbutton(gui, text='Show Hint', bg = COLOUR).pack(anchor='nw', padx=110)
tk.Label(text= f'Words Used : {WORDS}', bg = COLOUR).pack(anchor = 'nw', padx=130)


frame = tk.Frame(gui, bg=COLOUR)
tk.Label(frame, text='Generate a NORMAL password :', font = 'arial 12', bg=COLOUR).grid(row=0, column=0, columnspan=2, sticky=tk.W)
tk.Button(frame, text='Generate', bg='black', fg='white').grid(row=0, column=2, padx=5, pady=10)
tk.Label(frame, text='Generate a COMPLEX password :', font = 'arial 12', bg=COLOUR).grid(row=1, column=0, columnspan=2, sticky=tk.W)
tk.Button(frame, text='Generate', bg='black', fg='white').grid(row=1, column=2, padx=5, pady=10)
tk.Label(frame, text='Generate a CUSTOM password :', font = 'arial 12', bg=COLOUR).grid(row=2, column=0, columnspan=2, sticky=tk.W)
tk.Button(frame, text='Generate', bg='black', fg='white').grid(row=2, column=2, padx=5, pady=10)
tk.Label(frame, text='Password must contain-', font = 'arial 9', bg=COLOUR).grid(row=3, column=1, sticky=tk.W)

tk.Checkbutton(frame, text='Number of words(Default is 4) :', bg = COLOUR).grid(row=4, column=1, sticky=tk.W)
tk.Entry(frame, textvariable='sdfafd', width=5).grid(row=4, column=1, sticky=tk.E)
tk.Checkbutton(frame, text='Uppercase Letters', bg = COLOUR).grid(row=5, column=1, sticky=tk.W)
tk.Checkbutton(frame, text='Digits', bg = COLOUR).grid(row=4, column=2, sticky=tk.W)
tk.Checkbutton(frame, text='Symbols', bg = COLOUR).grid(row=5, column=2)

frame.pack(side=tk.LEFT, expand=True, padx=160, ipady=20)

tk.Label(text = 'by spicymaterial', font = 'arial 9', bg = COLOUR).pack(side=tk.RIGHT, anchor='se')


gui.mainloop()

也知道为什么页脚被剪掉了。

正如@jasonharper 指出的那样,需要设置 Checkbuttons 中的 variable 选项。如果未设置,则 Checkbutton 似乎按它们在包含的小部件中的位置进行分组。

此代码演示了错误行为。 'Show Hint' 链接到 'Number of Words','Test' 链接到 'Uppercase Letters'。 gui 中的第一项链接到 frame 中的第一项。第二项也有关联。

import tkinter as tk

COLOUR = 'grey80'
gui = tk.Tk()

# Root Interface
gui.title('Password Generator')
gui.resizable(0, 0)
gui.configure(bg = COLOUR)

tk.Checkbutton(gui, text='Show Hint', bg = COLOUR).pack(anchor='nw')
tk.Checkbutton( gui, text='Test').pack( anchor = 'nw')

frame = tk.Frame(gui, bg=COLOUR)
tk.Checkbutton(frame, text='Number of words(Default is 4) :', bg = COLOUR).grid(row=4, column=1, sticky=tk.W)
tk.Checkbutton(frame, text='Uppercase Letters', bg = COLOUR).grid(row=5, column=1, sticky=tk.W)
tk.Checkbutton(frame, text='Digits', bg = COLOUR).grid(row=4, column=2, sticky=tk.W)
tk.Checkbutton(frame, text='Symbols', bg = COLOUR).grid(row=5, column=2)

frame.pack(side=tk.LEFT)

tk.Label(text = 'by spicymaterial', font = 'arial 9', bg = COLOUR).pack(side=tk.RIGHT, anchor='se')

gui.mainloop()

为了获得预期的行为,创建 tk.IntVars 并使用 variable 选项链接到复选按钮。

import tkinter as tk

COLOUR = 'grey80'
WORDS = ['motor', 'anaconda', 'supervise', 'walnut', 'manicure', 'acre']
gui = tk.Tk()

# Root Interface
gui.geometry('720x480')
gui.title('Password Generator')
gui.resizable(0, 0)
gui.configure(bg = COLOUR)

# Checkbox variables
hint_var = tk.IntVar()
words_var = tk.IntVar()
upper_var = tk.IntVar()
digits_var = tk.IntVar()
symbols_var = tk.IntVar()


frame_header = tk.Frame(bg='black')
tk.Label(text = 'Password Generator', font = 'Helvetica 30 bold', bg = 'black', fg='white').pack(ipady=10, fill='both')
tk.Label(text = 'A Password Generator based on Diceware', font = 'arial 11', bg = 'black', fg='white').pack(fil='both')
frame_header.pack(fill='both')

tk.Label(text= '', width = 70, height = 3, borderwidth = 2, relief = tk.SUNKEN).pack(pady=5)
tk.Checkbutton(gui, text='Show Hint', bg = COLOUR, variable = hint_var).pack(anchor='nw', padx=110)
# Note variable = hint_var
tk.Label(text= f'Words Used : {WORDS}', bg = COLOUR).pack(anchor = 'nw', padx=130)


frame = tk.Frame(gui, bg=COLOUR)
tk.Label(frame, text='Generate a NORMAL password :', font = 'arial 12', bg=COLOUR).grid(row=0, column=0, columnspan=2, sticky=tk.W)
tk.Button(frame, text='Generate', bg='black', fg='white').grid(row=0, column=2, padx=5, pady=10)
tk.Label(frame, text='Generate a COMPLEX password :', font = 'arial 12', bg=COLOUR).grid(row=1, column=0, columnspan=2, sticky=tk.W)
tk.Button(frame, text='Generate', bg='black', fg='white').grid(row=1, column=2, padx=5, pady=10)
tk.Label(frame, text='Generate a CUSTOM password :', font = 'arial 12', bg=COLOUR).grid(row=2, column=0, columnspan=2, sticky=tk.W)
tk.Button(frame, text='Generate', bg='black', fg='white').grid(row=2, column=2, padx=5, pady=10)
tk.Label(frame, text='Password must contain-', font = 'arial 9', bg=COLOUR).grid(row=3, column=1, sticky=tk.W)

tk.Checkbutton(frame, text='Number of words(Default is 4) :',  variable = words_var, bg = COLOUR).grid(row=4, column=1, sticky=tk.W)
tk.Entry(frame, textvariable='sdfafd', width=5).grid(row=4, column=1, sticky=tk.E)
tk.Checkbutton(frame, text='Uppercase Letters', bg = COLOUR, variable = upper_var).grid(row=5, column=1, sticky=tk.W)
tk.Checkbutton(frame, text='Digits', bg = COLOUR, variable = digits_var).grid(row=4, column=2, sticky=tk.W)
tk.Checkbutton(frame, text='Symbols', bg = COLOUR, variable = symbols_var).grid(row=5, column=2)

frame.pack(side=tk.LEFT, expand=True, padx=160, ipady=20)

tk.Label(text = 'by spicymaterial', font = 'arial 9', bg = COLOUR).pack(side=tk.RIGHT, anchor='se')


gui.mainloop()

生成密码的代码现在可以访问 tk.IntVars 以更改密码的生成方式。

每个复选按钮都需要一个关联变量。如果你没有明确定义一个变量,tkinter 会为你定义一个。当 tkinter 为您定义一个时,它将基于小部件的内部名称,使用全名的最后一部分。

当您在 gui 中创建第一个复选按钮时,它的全名可能是 .!checkbutton,因为它是根 window 的子项,变量名将是 !checkbutton.

当您在 frame 中创建第二个复选按钮时,它的全名可能是 .!frame2.!checkbutton,因为它是框架的子项,变量名将是 !checkbutton

因为变量具有相同的内部名称,所以它们在内部被 tkinter 认为是相同的变量,因此检查按钮是链接的。

创建 Checkbutton 的正确方法是始终显式定义 variable 选项。

hint_var = tk.IntVar()
num_words_var = tk.IntVar()

tk.Checkbutton(..., variable=hint_var)
tk.Checkbutton(..., variable=num_words_var)

如果您不打算使用这些变量,您可以提供一个普通字符串并避免创建单独的变量对象

tk.Checkbutton(..., variable="hint")
tk.Checkbutton(..., variable="num words")