Tkinter用复选框禁用多个输入框

2 投票
1 回答
13567 浏览
提问于 2025-04-17 17:14

在Python 2.7中,我想通过一个复选框来控制一个“输入框”的状态,让它变成正常或禁用。

通过参考这个问题 用复选框禁用控件?,我可以用一个复选框和一个输入框来实现这个功能。

#!/usr/bin/env python2.7
# -*- coding: utf-8 -*-

import Tkinter as tk

root = tk.Tk()


class Principal(tk.Tk):
    def __init__(self, *args, **kwargs):
        self.foo = tk.StringVar()
        self.nac = tk.IntVar()

        self.ck1 = tk.Checkbutton(root, text='test',
            variable=self.nac, command=self.naccheck)
        self.ck1.pack()

        self.ent1 = tk.Entry(root, width=20, background='white',
            textvariable=self.foo, state='disabled')
        self.ent1.pack()

    def naccheck(self):
        print "check"
        if self.nac.get() == 0:
            self.ent1.configure(state='disabled')
        else:
            self.ent1.configure(state='normal')

app = Principal()
root.mainloop()

但是,当我想要有两个或更多的复选框和输入框配对时,就出现了问题。因为在我的最终界面中,可能会有20对或者更多这样的配对,所以我希望能避免写20个相同的“naccheck”方法。

我尝试了这个:

#!/usr/bin/env python2.7
# -*- coding: utf-8 -*-

import Tkinter as tk

root = tk.Tk()


class Principal(tk.Tk):
    def __init__(self, *args, **kwargs):
        self.foo = tk.StringVar()
        self.nac = {}
        self.ent = {}

        self.ent["test"] = tk.Entry(root, width=20, background='white', textvariable=self.foo, state='disabled')
        self.ent["test"].pack()

        self.ent["image"] = tk.Entry(root, width=20, background='white', textvariable=self.foo, state='disabled')
        self.ent["image"].pack()

        self.nac["test"] = tk.IntVar()
        self.ck1 = tk.Checkbutton(root, text='test', variable=self.nac["test"], command=self.naccheck("test"))
        self.ck1.pack()

        self.nac["image"] = tk.IntVar()
        self.ck1 = tk.Checkbutton(root, text='image', variable=self.nac["image"], command=self.naccheck("image"))
        self.ck1.pack()


    def naccheck(self,item):
        print "check "+item
        print self.nac[item].get()
        if self.nac[item].get() == 0:
            self.ent[item].configure(state='disabled')
        else:
            self.ent[item].configure(state='normal')

app = Principal()
root.mainloop()

不幸的是,当我运行这段代码时,每个复选框的“naccheck”方法会立即被调用,而不是在我点击某个复选框后才调用……

我哪里做错了呢?

1 个回答

8

解决这个问题的方法有很多种。一个方法是把输入框和复选框的变量传递到你的检查函数里。首先创建输入框和变量。然后,创建复选框,并把变量和输入框传给你的回调函数:

ent = tk.Entry(...)
var = tk.IntVar()
chk = tk.Checkbutton(..., command=lambda e=ent, v=var: self.naccheck(e,v))

注意这里使用了lambda,这是一个简单的技巧,用来创建匿名函数。这样你就可以在不需要创建命名函数的情况下,把参数传给回调函数。另一个选择是使用 functools.partial。在StackOverflow上肯定有很多关于这个的例子,因为这是一个非常常见的问题。

接下来,你需要修改你的函数,以便接受参数:

def naccheck(self, entry, var):
    if var.get() == 0:
        entry.configure(state='disabled')
    else:
        entry.configure(state='normal')

撰写回答