【问题标题】:Tkinter - Creating multiple check boxes using a loopTkinter - 使用循环创建多个复选框
【发布时间】:2019-11-20 16:30:43
【问题描述】:

我正在尝试创建一个程序,允许用户选择任意数量的复选框并点击按钮以从这些复选框返回随机结果。由于我的列表基于 Smash bros Ultimate 的名单,我试图避免创建 70 多个变量只是为了放置复选框。但是,我无法弄清楚如何迭代它。在我弄清楚之前,为行设置的各种值只是占位符。我还想在顶部有一个重置按钮,允许用户自动取消选中每个框。这段代码是我到目前为止所拥有的。任何帮助将不胜感激。

#!/usr/bin/python3

from tkinter import *
window = Tk()

#window name and header
window.title("Custom Random SSBU")
lbl = Label(window, text="Select the fighters you would like to include:")
lbl.grid(column=1, row=0)

f = [] #check boxes

ft = open("Fighters.txt").readlines() #list of all the character names

fv=[0]*78 #list for tracking what boxes are checked

ff=[] #list to place final character strings

def  reset():
   for i in fv:
       fv[i]=0

rst = Button(window, text="Reset", command=reset)
rst.grid(column=0, row=3)

for y in range (0,77):
    f[y] = Checkbutton(window, text = ft[y], variable = fv[y])
    f[y].grid(column=0, row=4+y)

def done():
    for j in fv:
        if fv[j] == 1:
            ff.append(fv[j])
    result = random.choice(ff)
    r=Label(window, text=result)

d = Button(window, text="Done", command=done)
d.grid(column=0, row = 80)

window.mainloop()

【问题讨论】:

    标签: python tkinter


    【解决方案1】:

    很遗憾,恐怕您必须为每个复选框创建变量。

    tkinter 具有特殊用途 Variable Classes 用于保存不同类型的值,如果在创建 Checkbutton 之类的小部件时将其中的一个实例指定为 variable= 选项,它将自动设置或重置其值每当用户更改它时,您的程序所要做的就是通过调用其get() 方法来检查其当前值。

    以下是在循环中创建它们(并在done() 回调函数中使用它们)所需的代码修改示例:

    import random
    from tkinter import *
    
    window = Tk()
    
    #window name and header
    window.title("Custom Random SSBU")
    
    lbl = Label(window, text="Select the fighters you would like to include:")
    lbl.grid(column=1, row=0)
    
    with open("Fighters.txt") as fighters:
        ft = fighters.read().splitlines() # List of all the character names.
    
    fv = [BooleanVar(value=False) for _ in ft] # List to track which boxes are checked.
    
    ff = [] # List to place final character strings.
    
    def  reset():
       for var in fv:
           var.set(False)
    
    rst = Button(window, text="Reset", command=reset)
    rst.grid(column=0, row=3)
    
    for i, (name, var) in enumerate(zip(ft, fv)):
        chk_btn = Checkbutton(window, text=name, variable=var)
        chk_btn.grid(column=0, row=i+4, sticky=W)
    
    def done():
        global ff
        ff = [name for name, var in zip(ft, fv) if var.get()]  # List of checked names.
        # Randomly select one of them.
        choice.configure(text=random.choice(ff) if ff else "None")
    
    d = Button(window, text="Done", command=done)
    d.grid(column=0, row=len(ft)+4)
    
    choice = Label(window, text="None")
    choice.grid(column=1, row=3)
    
    window.mainloop()
    

    我不确定您希望包含结果的 Label 去哪里,所以我只是将它放在 Reset 按钮的右侧。

    【讨论】:

      【解决方案2】:
      variable = fv[y]
      

      这会查找 fv[y] 的值 - 即整数 0 - 在创建 Checkbutton 时,并将其用于 variable 参数。

      您需要改用value-tracking classes provided by TKinter 之一的实例。在这种情况下,我们需要BooleanVar,因为我们正在跟踪一个布尔状态。我们仍然可以提前在列表中创建这些:

      text = open("Fighters.txt").readlines()
      # Let's not hard-code the number of lines - we'll find it out automatically,
      # and just make one for each line.
      trackers = [BooleanVar() for line in text]
      # And we'll iterate over those pair-wise to make the buttons:
      buttons = [
          Checkbutton(window, text = line, variable = tracker)
          for line, tracker in zip(text, trackers)
      ]
      

      (但我们可以这样做,例如trackers = [BooleanVar()] * len(text),因为这为我们提供了78次相同跟踪器,因此每个复选框都将共享该跟踪器;我们需要单独跟踪。)

      当你点击复选框时,TKinter 会自动更新对应的BooleanVar() 的内部状态,我们可以使用它的.get() 方法来检查。此外,当我们为random.choice 设置选项时,我们希望为按钮选择相应的文本,而不是跟踪器。我们可以再次使用zip 技巧来做到这一点。

      所以我们想要更像:

      result_label = Label(window) # create it ahead of time
      
      def done():
          result_label.text = random.choice(
              label
              for label, tracker in zip(text, trackers)
              if tracker.get()
          )
      

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 2018-01-01
        • 2021-11-22
        • 2020-11-22
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多