当for循环创建小部件时,从spinbox值更新标签

时间:2016-05-12 17:55:52

标签: python user-interface tkinter

我使用for循环在gui窗口中添加了多个spinbox和标签。 for循环在同一行上创建spinbox和label。然后在循环的下一个刺激中创建另一行标签和旋转框。如何从旋转框中获取值(单击时或增加或减少时),然后使用单击的旋转框中的值进行计算并更新与旋转框位于同一行的标签?

我添加了用于使用for循环创建旋转框的代码。

import Tkinter as tk

win = tk.Tk()

val = int()


def exitProgram():
        print("Exit Button pressed")
        win.quit()
        win.destroy()


def createSpinBoxes():

        boxes = []
        lbls = []
        corr = []

        def Correction(event):
                print "you clicked on", event.widget
                w = event.widget
                if isinstance(w, tk.Spinbox):
                        print "what is w??"
                        print w
                        print repr(w)
                        data = float(w.get())
                        data = (data/2)+3
                        print data
                        lbl.configure(text = str(data))

        def TestCorr(data):
                print data


        # Create Spinbox Title label
        lbl = tk.Label(win, text = 'SpBox#',
                       background = "light gray",
                       font = ('Courier' , 10))
        lbl.grid(column = 0, row = 0, sticky = 'we')

        # Create Nominal Value Title label
        lbl = tk.Label(win, text = 'Nom Val',
                       background = "light gray",
                       font = ('Courier' , 10))
        lbl.grid(column = 1, row = 0, sticky = 'w')

        # Create Correction Title label
        lbl = tk.Label(win, text = 'Corr',
                       background = "light gray",
                       font = ('Courier' , 10))
        lbl.grid(column = 2, row = 0, sticky = 'we')

        # Create Value Parameter labels
        valLabels = ['IN VAL ',
                     'OUT VAL',
                     'COR VAL']
        # Nominal values
        valNom = [37.0,    # Value 1
                  64.0,    # Value 2
                  20.0]    # Value 3

        # Nominal value Level Range
        valRange = [33,  # Min Value 1
                   44,  # Max Value 1
                   62,  # Min Value 2
                   68,  # Max Value 2
                   15,  # Min Value 3
                   25]  # Max Value 3


        valRngCnt = 0
        for i in range(0, 3):
                lbl = tk.Label(win,
                               text = valLabels[i],
                               font = ('Courier' , 10),
                               background = "light pink").grid(column = 0, row = i+2, sticky = 'w')
                val = valNom[i]
                SPbox = tk.Spinbox(win,
                                   from_= valRange[valRngCnt],
                                   to = valRange[valRngCnt+1],
                                   font = ('Courier' , 10),
                                   width = 5,
                                   increment=0.1,
                                   textvariable=val,
                                   command=lambda: TestCorr(val))
                SPbox.grid(column = 1, row = i+2, sticky = 'w')
                SPbox.delete(0,"end")
                SPbox.insert(0,valNom[i])

                # Debug lines
                print str(valNom[i]) + " Start Range: " + str(valRange[valRngCnt]) + " End Range: " + str(valRange[valRngCnt+1])
                print valRngCnt

                valRngCnt += 2
                lbl = tk.Label(win,
                               background = "light pink",
                               font = ('Courier' , 10))
                lbl.grid(column = 2, row = i+2, sticky = 'w')
                boxes.append(SPbox)
                lbls.append(lbl)
                corr.append(corr)
                SPbox.bind("<Button-1>", Correction)

                # Debug line
                print boxes


createSpinBoxes()

exitButton  = tk.Button(win,
                        text = "Exit",
                        background = "YELLOW",
                        command = exitProgram)
exitButton.grid(column = 4, row = 7, sticky = 'e')



tk.mainloop()

1 个答案:

答案 0 :(得分:0)

Correction当你这样做时:

lbl.configure(text = str(data))

您希望lbl与点击旋转框相关联的正确吗?相反,它会在lbl循环之后使用分配给Correction变量的小部件for被称为,因此它只会更新最后lbl

有两种方法可以确保Correction更新正确的标签:

  1. 使用Correction
  2. 的包装器

    首先,这意味着Correction需要将标签更新为参数:

    def Correction(event, label):
        ...
        #instead of lbl you use label
        label.configure(text=str(data))
    

    您可以使用functools.partial制作回调包装器:

    wrapper = functools.partial(Correction, label=lbl) #current lbl is saved with the wrapper
    SPbox.bind("<Button-1>", wrapper)
     #the two above would replace this line:
    #SPbox.bind("<Button-1>", Correction)
    
    1. 使标签成为触发回调的旋转框的属性。
    2. 我个人更喜欢这种方法,你可以在所有tk小部件上创建任意属性:

      SPbox.label = lbl #make the label an attribute of each SPbox.
      #this would be done around the same time as you do the binding:
      SPbox.bind("<Button-1>", Correction)
      

      然后lbl代替Correction,您会更新w.label

      #instead of lbl.configure(text = str(data))
      w.label.configure(text = str(data)) 
      

      请注意,您可能希望完全使用<Button-1>逐步淘汰,因为正如您所遇到的那样,它在点击箭头时并不总是触发,并且在使用箭头键时它肯定不会触发,一个解决方案是在初始化之后更改Spinbox的command,以便它触发虚拟事件(这样您仍然可以在编写时使用Correction)然后绑定该虚拟事件而不是{{ 1}}:

      <Button-1>

      然后只需将绑定更改为使用SPbox = tk.Spinbox(win, ..., textvariable=val)#, #command=lambda: TestCorr(val)) #we can't make a partial that references SPbox because it doesn't exist yet! SPbox["command"] = partial(SPbox.event_generate, "<<Change>>") SPbox.grid(column = 1, row = i+2, sticky = 'w') ... ,它就会在每次更改时生成并处理该事件...

      <<Change>>