Как получить состояние нескольких Checkbuttons в Tkinter? - PullRequest
4 голосов
/ 27 января 2012

Я пишу небольшую программу Tkinter / Python, в которой есть список флажков с переменной длиной (определяется во время выполнения).

Я хочу иметь возможность прочитать состояние всех флажков в любое время, но я не уверен, как мне поступить.

Вот фрагмент кода для создания списка (принятый из этого поста ):

def relist(self):
    self.text.delete(1.0,END)
    p = subprocess.Popen (['ls', '/dev/'], stdout = subprocess.PIPE)
    lst = p.communicate()[0].split('\n')
    print lst
    for item in lst:
        v = tk.IntVar()
        cb = tk.Checkbutton(text="/dev/%s" % item, variable=v, command=self.cb(index))
        self.text.window_create("end", window=cb)
        self.text.insert("end", "\n") # to force one checkbox per line

И мой фиктивный обработчик:

def cb(self,idx):
    print ("var is %s", str(idx))
    lst[idx] = 1;

Проблема в том, что мой обработчик вызывается один раз (когда создаются кнопки), тогда как я хочу, чтобы он вызывался каждый раз, когда Checkbutton нажимается (проверяется или не проверяется), а когда он вызывается, я хочу обновить lst.

Ответы [ 4 ]

3 голосов
/ 27 января 2012

Ваша команда CheckButton выполняет обратный вызов, потому что это то, что вы говорите, чтобы сделать это.Предполагается, что команда является ссылкой на функцию, которую tkinter может выполнить при нажатии кнопки.Tkinter передает объект события в функцию обратного вызова.Смотрите это Effbot учебное пособие, но похоже, что вы уже пытаетесь реализовать их шаблон.Вы можете получить ссылку на флажок из атрибута event.widget, как объяснено здесь .Наконец, вам нужно присоединить вашу переменную к «себе», если вы хотите сослаться на нее в обратном вызове.

def relist(self):
    self.text.delete(1.0,END)       
    p = subprocess.Popen (['ls', '/dev/'], stdout = subprocess.PIPE)       
    lst = p.communicate()[0].split('\n')       
    print lst       
    self.var = tk.IntVar()
    for item in lst:           
        cb = tk.Checkbutton(text="/dev/%s" % item, variable=self.var, command=self.myCallback)
        self.text.window_create("end", window=cb)     
        self.text.insert("end", "\n") # to force one checkbox per line

def myCallback(self,event):
    var = self.var.get()
    print ("var is %s", str(var))
0 голосов
/ 18 июля 2017

Лично я не использую tk.IntVar () / tk.StringVar () и т. Д., Но, возможно, я должен.Возможно, это не лучший способ сделать это, но я думаю, что это довольно легко понять.не стесняйтесь критиковать и говорить мне, что на самом деле плохо и не пифонично, так что я могу улучшить себя (я все еще новичок).

я делаю интегратор, затем я создаю свои кнопки проверки в цикле и вобратный вызов Я передаю в параметре значение checkbutton и итератора.

    ...
    self.listeColonneFile1 = []

    self.chbFile1 = []
    indice = 0
    for column in dfFile1.columns:
        btn = ttk.Checkbutton(self.frameCheckButtonsFile1,
            text=column,
            command=lambda i=indice, col=column: self.callback_onCheck(col, i)
        )

        self.chbFile1.append(btn)
        self.chbFile1[indice].grid(row = indice, column = 0, sticky="nw")
        self.chbFile1[indice].state(['!alternate'])
        indice += 1

В моем обратном вызове у меня есть список всех checkButtons, которые проверяются (ну, не ChB, а его текст или его значение):

def callback_onCheck(self, column, indice):
    if self.chbFile1[indice].instate(['selected']) == True:
        self.listeColonneFile1.append(column)
    else:
        self.listeColonneFile1.remove(column)

PS: dfFile1 - это DataFrame для панд, см. документ

0 голосов
/ 21 июня 2017

У меня была такая же проблема.Попробуйте это:

cb = tk.Checkbutton(text="/dev/%s" % item, variable=v, command=lambda: self.cb(index))

Если вы передадите метод в качестве лямбда-функции, он будет выполнять метод при каждом изменении переменной.

0 голосов
/ 24 марта 2017

Я думаю, что то, о чем вы просили, может быть получено из здесь .

Для каждого item in lst необходимо предварительно создать отдельную переменную IntVar(), просто чтобы указать независимоекаждый флажок.Я не вижу другого способа, кроме как создать их вручную (я полагаю, у вас нет сотен флажков).Я буду повторно использовать код из этого ответа и сделаю следующее:

def relist(self):
    self.text.delete(1.0,END)       
    p = subprocess.Popen (['ls', '/dev/'], stdout = subprocess.PIPE)       
    lst = p.communicate()[0].split('\n')       
    print lst       
    self.var1 = tk.IntVar()
    self.var2 = tk.IntVar()
    self.var3 = tk.IntVar()
    .
    .
    . 
    vars = [self.var1,self.var2,self.var3,...]
    for item, var in zip(self.lst, vars):           
        cb = tk.Checkbutton(text="/dev/%s" % item, variable=var, command= lambda: self.myCallback(var))
        self.text.window_create("end", window=cb)     
        self.text.insert("end", "\n") # to force one checkbox per line

def myCallback(self,event,var):
    each_var = var.get()
    print ("var is %s", str(each_var))
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...