【问题标题】:Store the values of Radiobuttons and Checkbuttons存储 Radiobuttons 和 Checkbuttons 的值
【发布时间】:2015-04-20 02:18:06
【问题描述】:

我正在尝试获取以下格式的用户界面

import pandas as pd
from Tkinter import *

features =  pd.read_csv("C:\\Users\\ggorantla\\Desktop\\Competition\\otto\\data\\train.csv",dtype=object)
features = features.columns
master = Tk()
row = 0
result = []
mappe = {}
def saver(each):
    print(each, v.get())
    result.append(v.get())
    mappe[each] = v.get()
MODES = [ ("String", "str"), ("Number","num")]
for each in features:
    if row >4 :
        continue
    Label(master, text=each).grid(row=row, column=0)
    v = StringVar()
    v.set("default")
    col = 1
    for text, mode in MODES:
        Radiobutton(master, text=text, variable=v,value = mode, command=saver(each)).grid(row=row,column=col)
        col+=1
    print(v.get())
    row += 1         
mainloop()

我的问题是,当我运行此代码时,我得到了预期的 UI,但我无法将所有变量存储在 mappe 字典或 result 列表中。

所有值都默认为“默认”值。我被这个卡住了。

【问题讨论】:

    标签: python python-2.7 tkinter


    【解决方案1】:

    您为功能中的每个条目创建一个新的StringVarv,但您没有保存前一个以供以后参考。您应该将v 制作为字典并将StringVars 保存在它们所属功能的键下。

    另外,command 参数需要一个对函数的引用,但是你给它一个函数调用,这意味着该函数的返回值将被分配给command。因此,与其使用command=function(),不如使用command=function。因为您想将变量传递给函数,所以您需要 command 来调用一个调用您的实际函数的新函数。幸运的是,您可以使用 lambda 函数轻松完成此操作,例如

    command = lambda: saver(each)
    

    但是,因为 lambda 函数仅在调用它们时才被评估,所以您需要指定您当时要使用 each,而不是上次迭代中的 each。你这样做使用

    command = lambda each=each: saver(each)
    

    然后,为了保存输入,我建议使用字典而不是列表,因为您使用名称而不是索引来引用 features 中的项目。

    结合所有这些,您的程序变成:

    from Tkinter import *
    
    features = ['a', 'b', 'c', 'd']
    master = Tk()
    row = 0
    mappe = {}
    v = {}
    
    def saver(each):
        print(each, v[each].get())
        mappe[each] = v[each].get()
        print mappe
        
    MODES = [ ("String", "str"), ("Number","num")]
    
    for each in features:
    
        if row >4 :
            continue
            
        Label(master, text=each).grid(row=row, column=0)
        v[each] = StringVar()
        v[each].set("default")
        col = 1
        
        for text, mode in MODES:
            Radiobutton(master, text=text, variable=v[each], value=mode, 
                        command=lambda feature=each: saver(feature)).grid(row=row, column=col)
            col+=1
            
        row += 1   
        
    master.mainloop()
    

    【讨论】:

    • 效果很好,非常感谢。你有没有机会知道我如何使用滚动条。当我添加滚动条时,它只出现在第一行。我正在使用 scrollbar = Scrollbar(master) scrollbar.grid(column=3)。
    • 为此,您必须制作一个 Canvas,将 Scrollbar 绑定到该 Canvas,在 Canvas 中放置一个 Frame,并将所有小部件放入 Frame 中。查看示例here
    【解决方案2】:

    这也把我绊倒了。由于父框架仍然存在,因此界面对我来说感觉不一致,但传递给工厂的其他变量却没有。另一种解决方法是用它对父级进行monkeypatch。感觉就像是 hack,我说不出它有多像 Python,但在某种程度上它看起来非常优雅。

    label = Label(master, text=each).grid(row=row, column=0)
    label.v = StringVar() 
    label.v.set("Default")
    for text, mode in MODES:
        Radiobutton(master, text=text, variable=label.v, value = mode, 
                    command=saver(each)).grid(row=row,column=col)      
        col+=1
        print(label.v.get())
        row += 1 
    

    这将导致变量保持不变。可以理解的是,您冒着覆盖 Label 类中现有变量的风险。但是,它确实消除了在分配给标签的范围之外跟踪变量的需要。

    【讨论】:

      猜你喜欢
      • 2020-01-20
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2020-09-12
      • 2021-05-22
      • 2022-11-10
      相关资源
      最近更新 更多