質問

With Python 2.7, I would like to turn the state of an "Entry" widget to normal/disable thank to a checkbutton.

With the help of this question Disable widget with checkbutton?, I can do it with 1 checkbutton and 1 Entry

#!/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()

Problem come when I want to have 2 or more pair (checkbutton/entry). In my final interface, I may have 20 or more of this pair, so I would like to avoid to have 20 or more the same "naccheck" method.

I tried this:

#!/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()

Unfortunately, when I launch this code, the method "naccheck" is called immediately for each checkbutton, and never after when I click on one ...

What I have done wrong?

役に立ちましたか?

解決

There are many ways to solve this problem. One way is to pass the entry and checkbutton variable into your check function. Create the entry widget and variable first. Then, create the checkbutton and pass in the variable and entry to your callback:

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

Notice the use of lambda, which is a simple technique for creating anonymous functions. This enables you to pass arguments to a callback without having to create named functions. Another option is to use functools.partial. There are no doubt dozens of examples of this on StackOverflow as this is a very common question.

Next, you need to modify your function to accept arguments:

def naccheck(self, entry, var):
    if var.get() == 0:
        entry.configure(state='disabled')
    else:
        entry.configure(state='normal')
ライセンス: CC-BY-SA帰属
所属していません StackOverflow
scroll top