0

I have two separate columns of checkbuttons in tkinter in python with identical labels.

My goal is to disable those in one of the columns when the same item is selected in another column.

I can do this outside of classes and functions, but am having trouble calling the variables within the functions.

When I plug in static values for the dynamic parameters and remove the loop on the command function creation to disable the buttons, it works perfectly. Whenever I use the loop, however, I receive an "AttributeError: 'tool' object has no attribute 'dsblr0'" response.

How can I access the loop-created functions, such that I can disable the boxes in the second column whenever the same items are checked in the first column?

Any help is greatly appreciated!

My current code:

from tkinter import *
from tkinter import messagebox

buttonnames = []
class tool(Frame):
    def get_button_names(self):
        self.buttonnames=['b1','b2','b3','b4','b5']
        global buttonnames
        for item in self.buttonnames:
            buttonnames.append(item)

    def __init__(self, parent):
        '''
        Constructor
        '''
        Frame.__init__(self, parent)
        self.parent=parent
        self.get_button_names()
        self.display_new_window()

    for i in range(len(buttonnames)):
        exec('''def dsblr{0}(self):
    self.bcb{0}.config(state=DISABLED if self.var{0}.get() else NORMAL)'''.format(i,))

    def display_new_window(self):
        """ Transpose tools
        """
        self.parent.title("Tool")

        self.parent.grid_rowconfigure(0, weight=1)
        self.parent.grid_columnconfigure(0, weight=1)

        for i,column in enumerate(self.buttonnames):
            exec('self.var{0}=IntVar()'.format(i,))
            exec('self.bvar{0}=IntVar()'.format(i,))
            exec('self.cb{0} = Checkbutton(self.parent, text=column, variable=self.var{0},command=self.dsblr{0})'.format(i,))
            exec("self.cb{0}.grid(row=i+1,column=0,sticky='w')".format(i,))
            exec('self.bcb{0} = Checkbutton(self.parent, text=column, variable=self.bvar{0})'.format(i,))
            exec("self.bcb{0}.grid(row=i+1,column=1,sticky='w')".format(i,))

def main():
    root=Tk()
    d=tool(root)
    root.mainloop()

if __name__=="__main__":
    main()
UBHDNNX
  • 61
  • 1
  • 9
  • Can you share the code where you call these functions? Is there issue of sequence? – Kamal Feb 27 '19 at 09:09
  • the looped functions are called within 'command=self.dsblr{0}'-- about 5 lines from the bottom... The omitted code just sets up the GUI – UBHDNNX Feb 27 '19 at 09:13
  • No, I mean are you calling `display_new_window` which is using function `self.dsblr` before these functions are even created. It is not clear from the code you shared. Please share [Minimal, Complete and Verifiable Example](https://stackoverflow.com/help/mcve) – Kamal Feb 27 '19 at 09:17
  • @Kamal -- edited code to make it replicable. You should be able to reproduce the error now. Thanks for the tips! – UBHDNNX Feb 27 '19 at 09:55
  • [Edit] your Question and explain in detail **why** do you need to use `exec`, like `exec('self.var{0}=IntVar()'.format(i,))` at all? Create a `list` of `Button` objects instead. `buttons.append(Checkbutton(...))` – stovfl Feb 27 '19 at 11:12
  • @stovfl In short, I hadn't pursued your route with enough vigor. I just reconverted everything back to lists using your append method. I hit a bump in the road passing parameters to the tkinter command without running the functions immediately. This was solved by: https://stackoverflow.com/questions/6920302/how-to-pass-arguments-to-a-button-command-in-tkinter – UBHDNNX Feb 27 '19 at 14:16
  • @stovfl If you add the lists/appends method as an answer, I'd be happy to accept it. – UBHDNNX Feb 27 '19 at 14:18

0 Answers0