在Python中选择OptionMenu后正确获取选项的方法

3
我想知道用户在展示列表中选择的选项,比如说:["苹果","橙子","葡萄"],当他们选择其中之一后,有没有办法让我看到?

就像当用户点击单选框并选择了苹果时,Tkinter会返回一些内容。

然后如果他把选择更改为橙子,那么这也会立即返回相应的内容。

谢谢!


如何正确设置参数?

from Tkinter import *

def option_changed(a):
    print "the user chose the value {}".format(variable.get())
    print a

master = Tk()

a = "Foo"
variable = StringVar(master)
variable.set("Apple") # default value
variable.trace("w", option_changed(a))

w = OptionMenu(master, variable, "Apple", "Orange", "Grapes")
w.pack()

mainloop()
2个回答

7
追踪 StringVar
from Tkinter import *

def option_changed(*args):
    print "the user chose the value {}".format(variable.get())
    print a

master = Tk()

a = "Foo"
variable = StringVar(master)
variable.set("Apple") # default value
variable.trace("w", option_changed)

w = OptionMenu(master, variable, "Apple", "Orange", "Grapes")
w.pack()

mainloop()

在这里,每当用户从选项菜单中选择一个选项时,option_changed将被调用。


您可以使用lambda将trace参数包装起来以指定自己的参数。

def option_changed(foo, bar, baz):
    #do stuff

#...
variable.trace("w", lambda *args: option_changed(qux, 23, "hello"))

我该如何向.trace函数添加参数? - user3404844
我上面发布的代码似乎不起作用 :( - user3404844
你不需要将 a 作为参数传递以在函数内部访问它。保留 def option_changed(*args):variable.trace("w", option_changed),并且 print a 仍然可以工作。 - Kevin
谢谢回复,但我想知道如果我需要传递参数怎么办? - user3404844
1
星号是任意参数列表的标志。当你包含它时,函数可以被调用任意数量的参数,并且任何未绑定到先前参数的内容将在元组中可用。例如,如果我定义了 def frob(x, y, *z) 并调用 frob(4, 8, 15, 16, 23),那么 z 将是元组 (15, 16, 23) - Kevin
显示剩余2条评论

6

当我遇到界面烦人的小部件时,例如 OptionMenu,通常会编写一个类来抽象掉这些烦人的属性。在这种情况下,我真的不喜欢每次创建下拉菜单时都要使用 StringVar 的冗长性,因此我只需创建一个包含 StringVarDropDown 类(使用 Python 3.5 编写,但很容易转换为其他语言):

class DropDown(tk.OptionMenu):
    """
    Classic drop down entry

    Example use:
        # create the dropdown and grid
        dd = DropDown(root, ['one', 'two', 'three'])
        dd.grid()

        # define a callback function that retrieves the currently selected option
        def callback():
            print(dd.get())

        # add the callback function to the dropdown
        dd.add_callback(callback)
    """
    def __init__(self, parent, options: list, initial_value: str=None):
        """
        Constructor for drop down entry

        :param parent: the tk parent frame
        :param options: a list containing the drop down options
        :param initial_value: the initial value of the dropdown
        """
        self.var = tk.StringVar(parent)
        self.var.set(initial_value if initial_value else options[0])

        self.option_menu = tk.OptionMenu.__init__(self, parent, self.var, *options)

        self.callback = None

    def add_callback(self, callback: callable):
        """
        Add a callback on change

        :param callback: callable function
        :return: 
        """
        def internal_callback(*args):
            callback()

        self.var.trace("w", internal_callback)

    def get(self):
        """
        Retrieve the value of the dropdown

        :return: 
        """
        return self.var.get()

    def set(self, value: str):
        """
        Set the value of the dropdown

        :param value: a string representing the
        :return: 
        """
        self.var.set(value)

使用示例:

# create the dropdown and grid, this is the ONLY required code
dd = DropDown(root, ['one', 'two', 'three'])
dd.grid()

# optionally, define a callback function that retrieves the currently selected option then add that callback to the dropdown
def callback():
    print(dd.get())

dd.add_callback(callback)

编辑补充:在创建这篇文章不久后,我对tk的一些其他属性感到烦恼,于是创建了一个名为tk_tools的软件包,以使下拉菜单和复选框更加容易,并解决其他烦恼。


太棒了。然而,我试图通过将tk.OptionMenu.__init__(self, parent, self.var, *options)更改为ttk等效项来“改进”代码,即ttk.OptionMenu.__init__(self, parent, self.var, *options)。我得到的错误是AttributeError:'DropDown'对象没有'set_menu'属性。为什么会这样 - 为什么ttk等效项无法初始化? - xax
tk.OptionMenu没有set_menu方法, 这只是ttk.OptionMenu的属性。 - Jgd10

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接