tkinter creating buttons in for loop passing command arguments

前端 未结 3 1329
陌清茗
陌清茗 2020-11-22 01:09

I am trying to create buttons in tkinter within a for loop. And with each loop pass the i count value out as an argument in the command value. So when the function is called

相关标签:
3条回答
  • 2020-11-22 01:52

    Change your lambda to lambda i=i: self.open_this(i).

    This may look magical, but here's what's happening. When you use that lambda to define your function, the open_this call doesn't get the value of the variable i at the time you define the function. Instead, it makes a closure, which is sort of like a note to itself saying "I should look for what the value of the variable i is at the time that I am called". Of course, the function is called after the loop is over, so at that time i will always be equal to the last value from the loop.

    Using the i=i trick causes your function to store the current value of i at the time your lambda is defined, instead of waiting to look up the value of i later.

    0 讨论(0)
  • 2020-11-22 01:52

    This is how closures work in python. I ran into this problem myself once. You could use functools.partial for this.

    for i in range(3):
        self.button.append(Button(self, text='Game '+str(i+1), command=partial(self.open_this, i)))
    
    0 讨论(0)
  • 2020-11-22 01:52

    Simply attach your buttons scope within a lambda function like this:

    btn["command"] = lambda btn=btn: click(btn) where click(btn) is the function that passes in the button itself. This will create a binding scope from the button to the function itself.

    Features:

    • Customize gridsize
    • Responsive resizing
    • Toggle active state

    #Python2
    #from Tkinter import *
    #import Tkinter as tkinter
    #Python3
    from tkinter import *
    import tkinter
    
    root = Tk()
    frame=Frame(root)
    Grid.rowconfigure(root, 0, weight=1)
    Grid.columnconfigure(root, 0, weight=1)
    frame.grid(row=0, column=0, sticky=N+S+E+W)
    grid=Frame(frame)
    grid.grid(sticky=N+S+E+W, column=0, row=7, columnspan=2)
    Grid.rowconfigure(frame, 7, weight=1)
    Grid.columnconfigure(frame, 0, weight=1)
    
    active="red"
    default_color="white"
    
    def main(height=5,width=5):
      for x in range(width):
        for y in range(height):
          btn = tkinter.Button(frame, bg=default_color)
          btn.grid(column=x, row=y, sticky=N+S+E+W)
          btn["command"] = lambda btn=btn: click(btn)
    
      for x in range(width):
        Grid.columnconfigure(frame, x, weight=1)
    
      for y in range(height):
        Grid.rowconfigure(frame, y, weight=1)
    
      return frame
    
    def click(button):
      if(button["bg"] == active):
        button["bg"] = default_color
      else:
        button["bg"] = active
    
    w= main(10,10)
    tkinter.mainloop()
    

    0 讨论(0)
提交回复
热议问题