选中时,Tkinter optionmenu add_command字符串不会显示在窗口小部件上

时间:2018-02-21 04:16:08

标签: python tkinter optionmenu

from tkinter import *


main = Tk()

var = StringVar()
options = OptionMenu(main, var, 'option1')
options.grid()
options['menu'].add_command(label='option2')


main.mainloop()

当您在菜单中选择“option1”时,它会在窗口小部件上显示该字符串。如果选择“option2”,则不会在窗口小部件上显示该字符串。如果为option2设置命令,它将运行。选择时,为什么'option2'没有显示在窗口小部件中?

python 3.5

更新:

通过for循环添加字符串我遇到了一个问题,即每个字符串的命令使用相同的变量。

from tkinter import *

def _print(var, string):
    print(string)
    var.set(string)

lst = ['hello', 'bob', 'testing']

main = Tk()
var = StringVar()
options = OptionMenu(main, var, 'option1')
options.grid()

for string in lst:
    options['menu'].add_command(label=string, command=lambda: _print(var, string))

main.mainloop()

我尝试在循环中使用lambda event, i=string: _print(var, i)),但是lamdba并不喜欢它。说它缺少'事件'。我把事件放在_print函数和对_print的调用中,但是我得到的错误是lamdba缺少事件。知道如何为循环中的每个命令传递正确的变量吗?

2 个答案:

答案 0 :(得分:1)

当您在Optionmenu()小部件中声明'option2'时,它会起作用。可以从herehere阅读更多示例。

from tkinter import *

main = Tk()

var = StringVar()
options = OptionMenu(main, var, 'option1', 'option2')
options.grid()
#options['menu'].add_command(label='option2')


main.mainloop()

我发现menu选项用于在Menu()窗口小部件中创建项目,但不用于Optionmenu()窗口小部件。这是陈述here。您可以详细了解如何声明.Menu()小部件here。最好的tkinter开发。

<强> EDIT1:

失败的原因是您没有声明与command方法关联的.add_command选项。单独完成此操作后,您会注意到Optionmenu仍未使用添加的菜单项的新标签进行更新。要解决此问题,您必须使用控制变量.set()的{​​{1}}方法进行更新。请参阅下面的修订脚本。

StringVar

<强> EDIT2:

  1. 备注,我已将from tkinter import * def _print1(value): # By default, callback to OptionMenu has a positional arguement for the # menu item's label. print(value) print(var.get()) def _print2(): var.set('option2') print(var.get()) main = Tk() var = StringVar() options = OptionMenu(main, var, 'option1',command=_print1) options.grid() options['menu'].add_command(label='option2', command=_print2) # To add more clickable menu items, the 'add_command' method requires you to # to declare it's options 'label' and 'command'. main.mainloop() 方面添加到 Edit1 中的command。一世 没有提前解决,但认为它需要显示 完整性。
  2. 在你的更新中回答你的问题,做你想做的事,我 将脚本重写为类对象。我也使用了内部类 在{tkinter}中找到options _setit窗口小部件曾经使用过的OptionMenu 配置command使用的回调。这种方法克服了您遇到的问题。
  3. 修订代码:

    from tkinter import *
    
    class App(Tk):
    
        def __init__(self, parent=None):
            Tk.__init__(self, parent)
            self.parent=parent
            self.createOM()
            self.grid()
    
        def createOM(self):
            # Create OptionMenu
            omlist=['option1']
            self.var = StringVar()
            self.options = OptionMenu(self, self.var, *omlist,
                                      command=self._print1)
            self.options.grid()
    
            values = ['hello', 'bob', 'testing']
            for v in values:
                self.options['menu'].add_command(
                    label=v, command=_setit(self.var, v, self._print2))
            # To add more clickable menu items, the 'add_command' method requires you to
            # to declare it's options 'label' and 'command'.
    
        def _print1(self, value, *args):
            #callback for OptionMenu has these arguements because inherently it
            #uses the _setit class to configure the callback with these arguements. 
            print()        
            print(value)        
            #self.var.set('option10') #Uncomment to change OptionMenu display
            print(self.var.get())
    
        def _print2(self, value, *args):
            print()        
            print(value)        
            #self.var.set('option20') #Uncomment to change OptionMenu display
            print(self.var.get())
    
    #The following class is extracted from tkinter.
    class _setit:
        """Internal class. It wraps the command in the widget OptionMenu."""
        def __init__(self, var, value, callback=None):
            self.__value = value
            self.__var = var
            self.__callback = callback
        def __call__(self, *args):
            self.__var.set(self.__value)
            if self.__callback:
                self.__callback(self.__value, *args)
    
    
    if __name__ == "__main__":
        app = App()
        app.mainloop()
    

答案 1 :(得分:1)

它没有选择任何东西,因为它不应该。你基本上是在攻击OptionMenu的视觉部分。您作为values传递的项目首先添加到菜单中,然后给出命令选项以修改选择。当您致电options['menu'].add_command(label='option2')时,您基本上只修改了窗口小部件的可视部分,'option2' 而不是添加到值中,因此命令选项不是< / em>设置。请参阅源代码here中的自己。