【问题标题】:how to create traceable widgets with functions (python, tkinter)如何使用函数创建可追溯的小部件(python、tkinter)
【发布时间】:2020-01-03 14:25:46
【问题描述】:

我目前正在尝试使用 tkinter 为一个非常具体的数据处理工具创建 GUI。用户将通过按钮加载文件,并且根据该数据,该工具将显示许多下拉菜单,以选择特定于所提供数据的选项。 现在我在初始化 mainloop 之后一直在创建这些小部件(我需要在事后初始化/更新它们,因为用户还应该能够加载多个文件)。正在显示小部件,但我无法访问它们的值,因为这是函数内部的局部变量。

TLDR:我想在初始化窗口后创建和更新 tkinter 小部件,并且它的值需要可访问

我尝试编写如下所示的函数,该函数将根据其他代码触发。可悲的是,它们提供的值仅反映函数终止时小部件(在本例中为下拉菜单)的值,并且不会随小部件而改变。 将它们更改为全局变量也不能解决更新问题。 事后我研究了创建小部件的不同方法,但似乎没有找到方法。

import tkinter as tki

root = tki.Tk()
root.title('Data Comparison')

#specifying a frame and its grid
frame = tki.Frame(root)
frame.grid(column=9, row=7)

#I'm working with dicts, not lists, because that more accurately represents my
#actual data
numbers= {'one':1, 'two':2, 'three':3, 'four':4} 
colors= {'blue':5, 'red':6, 'green':7, 'orange':8, 'pink':9, 'yellow':10}

def createDropdown():
    global DDvalue
    DDvalue = tki.StringVar(root)
    DDvalue.set(list(numbers)[0]) 
    global DDvalues
    DDvalues = tki.OptionMenu(frame, DDvalue, *numbers)
    DDvalues.grid(column= 7, row = 1)
#the global variables only display the accurate value at the time of creation of the widget
createDropdown()

def displayvalue():
    print(str(DDvalue.get()))

DDvalue.trace_add('write', displayvalue())

def updateDropdown():
    DDvalues.destroy

btnupdate= tki.Button(frame, text='update', command= updateDropdown)
btnupdate.grid (column= 8, row= 7)

#I also could not delete the widget with the button above

root.mainloop()

现在 trace_add 只打印一次值,在创建小部件时(一个),之后更改值会导致以下错误消息: TypeError: 'NoneType' 对象不可调用

另外,更新按钮无法访问小部件

我想查看在满足某些条件后创建的小部件的值可访问。

【问题讨论】:

  • 这个.trace_add('write', displayvalue())应该写成.trace_add('write', displayvalue)注意没有()global DDvalue必须是global。跨度>
  • 嘿,感谢您的评论!当我在全局后删除变量时,我得到一个无效的语法错误。此外,当我删除空括号时,我收到以下错误:TypeError: displayvalue() takes 0 positional arguments but 3 were given
  • 你有#global DDvalue 作为comment,我的意思是必须是global DDvalue
  • 我按照描述中的说明进行了尝试。我将编辑代码以包含它。
  • def displayvalue(): 更改为def displayvalue(*args):

标签: python tkinter


【解决方案1】:

destroy() 需要调用括号。

displayvalue 作为函数对象传递,不应有括号。

trace 在调用它的变量之上传递两个参数:最后一个是mode,它对应于触发回调的操作(writereadunset)。

函数和变量的命名对于能够阅读和理解代码非常重要。

你应该首先声明和分配你的变量;在创建它们之前在函数内部声明它们是非常糟糕的做法。

tkinter 通常别名为tk,而不是tki

import tkinter as tk


numbers= {'one': 1, 'two': 2, 'three': 3, 'four': 4} 
colors= {'blue': 5, 'red': 6, 'green': 7, 'orange': 8, 'pink': 9, 'yellow': 10}


def set_value():    
    dd_var.set(list(numbers)[0]) 


def displayvalue(*args):
    # this is triggered each time dd_var is reset to a value
    print(args)
    print(str(dd_var.get()))


def remove_dropdown():
    drop_values.destroy()


root = tk.Tk()
root.title('Data Comparison')

frame = tk.Frame(root)
frame.grid(column=9, row=7)

dd_var = tk.StringVar(root)
set_value()
dd_var.trace_add('write', displayvalue)

drop_values = tk.OptionMenu(frame, dd_var, *numbers)
drop_values.grid(column=7, row =1)

remove_dropdown_btn = tk.Button(frame, text='update', command=remove_dropdown)
remove_dropdown_btn.grid (column= 8, row= 7)

root.mainloop()

【讨论】:

  • 感谢您的回答!我知道从函数内部声明全局变量是不好的做法,但是我不知道如何从函数内部更改 OptionMenu,这就是我刚刚在那里声明它的原因。有没有办法全局声明一个 OptionMenu 并在以后通过函数或按钮可调用的类似东西对其进行更改?
猜你喜欢
  • 1970-01-01
  • 2020-11-19
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2021-03-11
  • 1970-01-01
相关资源
最近更新 更多