0

I got another little question...

I want to make multiple variables which I create with 'setattr'

That works quite fine. It creates these variables:

self.sectionButton_1 = Button(text=x)
self.sectionButton_2 = Button(text=x)
self.sectionButton_3 = Button(text=x)

Now I want them to get displayed on the window with tkinter so that this should happen:

self.sectionButton_1.grid(row=i, column=0)
self.sectionButton_2.grid(row=i, column=0)

and so on..

But how do I have to edit the loop that the sectionButtons gonna be created with .grid from tkinter in a loop without writing the above ten times.

# Display Section selection
def checkSection(self):
    # Read all sections from config
    self.sections = config.sections()
    self.sectionsCount = str(len(self.sections))
    self.i = 0

    self.text = Label(text="Choose Section:" + self.sectionsCount)
    self.text.grid(row=1, column=0)
    for x in self.sections:
        i = +1
        setattr(self, 'sectionButton_' + str(i), Button(text=x))

I'm not that good at explaining but hopefully its enough to understand my problem ^^

If not, just comment, I will try to answer it

Marius1773
  • 23
  • 5

1 Answers1

1

If you have a group of related variables of the same type and you're doing the same operations to each one then that's a natural place to switch to using a list instead of individual variables.

Your code would become more like:

self.sectionButtons = []

for i, x in enumerate(self.sections):
    button = Button(text=x)
    button.grid(row=i+1, column=0)
    self.sectionButtons.append(button)

This also has the advantage of no longer needing to construct the variable names as strings and use setattr, which is often a sign there's a better way.

Kemp
  • 3,467
  • 1
  • 18
  • 27
  • But how can I effectively use the list for my purpose? In the first iteration this should be created and executed: 1. self.sectionButton_1 = Button(text=x) | create variable with the Button 2. self.sectionButton_1.grid(row=i, column=0) | Display the Button, with the .grid function with each individual variable self.selectionButton_i , where ' i ' is the current Iteration – Marius1773 Jun 15 '21 at 10:43
  • Can you tell me what my answer doesn't do that you require? Because as far as I can tell based on your example code it does what your original code does. If you need creation and the calls to `grid` to be in separate loops for some reason then you can have a second loop iterating over `self.sectionButtons` to do the `grid` calls. – Kemp Jun 15 '21 at 10:50
  • I'm dumb, yea, you are right, that is the solution that makes it run ... thanks. much love – Marius1773 Jun 15 '21 at 10:55
  • One more little thing: If I put a command in there with command=lambda: self.checkOption(x) Every button got the same x value from the checkSection function So If I click on button 1, I got the same result as If I click on button 3 – Marius1773 Jun 15 '21 at 11:15
  • I believe the issue you're having is that the value of `x` is evaluated at the time the lambda is executed, not at the time it's created. One way to work around this, which seems to be the recommended way in the docs, is to add a parameter to the lambda with a default value set to the value you want it to use, as described [here](https://stackoverflow.com/a/2295372/3228591). So you'd have `command=lambda x=x: self.checkOption(x)`. – Kemp Jun 15 '21 at 12:36
  • Yessss!!! Thats it! I also figured out how to delete them all with `for x in self.sectionButtons: x.grid_remove()` Thank you soooooo much! – Marius1773 Jun 15 '21 at 20:52