【问题标题】:tkinter optionmenu first option vanishestkinter optionmenu 第一个选项消失
【发布时间】:2013-10-08 22:22:11
【问题描述】:

一个 ttk optionmenu 小部件以下拉列表中的所有值开始。选择任何值后,列表中的第一个值就会消失,再也不会出现......

有人知道为什么吗?这是小部件设计的一个特点吗?尝试以下方法:

import tkinter.ttk as ttk
import tkinter as tk

a = tk.Tk()

options = ['1', '2', '3']
value = tk.StringVar()

masterframe = ttk.Frame()
masterframe.pack()

dropdown = ttk.OptionMenu(masterframe, value, *options)
dropdown.pack()

a.mainloop()

注意 - 另一个用户在这里问了同样的问题:OptionMenu won't show the first option when clicked (Tkinter)

他们似乎找到了解决方法,但不明白为什么会这样。

更新:实际上这种行为只在使用 ttk 小部件时出现。 tk 小部件工作正常(虽然看起来很丑)。

【问题讨论】:

    标签: python tkinter ttk optionmenu


    【解决方案1】:

    似乎ttk.OptionMenu 选项列表中的第一个条目必须留空:

    import tkinter.ttk as ttk
    import tkinter as tk
    
    a = tk.Tk()
    
    options = ['', '1', '2', '3']
    value = tk.StringVar()
    value.set(options[1])
    
    masterframe = ttk.Frame()
    masterframe.pack()
    
    dropdown = ttk.OptionMenu(masterframe, value, *options)
    dropdown.pack()
    
    a.mainloop()
    

    来源:https://pyinmyeye.blogspot.com/2012/08/tkinter-menubutton-demo.html

    【讨论】:

    • 虽然您的解决方法有效,但它对问题的描述并不是很好。 ttk.OptionMenu 期望在变量参数之后和值列表之前有一个默认值。虽然您的解决方案有效,但它掩盖了真正发生的事情。
    • 哈哈哈,超喜欢这个!!
    【解决方案2】:

    旧帖子,但我想我会添加到这个对话中。使用tk.OptionMenu 时,在Mac 上默认显示第一个(或列表中的任何项目)的一种非常简单的方法是使用tk.StringVar 例如:

    options = ['option1', 'option2', 'option3', 'option4']
    root = Tk()
    var = StringVar()
    var.set(options[0])
    OptionMenu(root, var, *options)
    mainloop()
    
    selected = var.get()
    

    使用var.set 来确定什么是“设置”值至关重要。 希望对您有所帮助!

    【讨论】:

      【解决方案3】:

      我在另一篇文章中也有同样的问题。我实际上已经阅读了这篇文章和答案,但没有注意到这两个选项菜单之间的细微差别。因此,即使我是 Python 和 tkinter 的新手,这也是我的答案。

      正如@Bryan Oakley 回答的那样,是的,文档字符串显示在使用 ttk.OptionMenu 而不是 tk.OptionMenu 时有一个“附加”必需参数。如果您将声明从 ttk.OptionMenu 更改回 tk.OptionMenu,这种差异将破坏(或至少弄乱)您的菜单。这是因为 tk.OptionMenu 不需要声明“默认”选项。如果出于某种原因将 ttk.OptionMenu 更改回 tk.OptionMenu 并在声明中保留“默认”参数,它将复制 OptionMenu 中的第一个选项。我正在用头撞墙,想弄清楚为什么这两个人的行为方式不完全相同。在我个人看来,情况不应该如此。如果有的话,'default' 参数应该是 tk.OptionMenu 和 ttk.OptionMenu 中的关键字以实现兼容性。也许我错了,但这是我目前的看法。

      为了证明这一点,请看下面的代码:

      # test-optionmenu.py
      
      import tkinter as tk
      from tkinter import ttk
      
      root = tk.Tk()
      # tk OptionMenu lists
      optionList1 = ('a', 'b', 'c')
      optionList2 = ('d', 'e', 'f')
      optionList3 = ('g', 'h', 'j')
      # ttk OptionMenu lists
      optionList4 = ('1', '2', '3')
      optionList5 = ('4', '5', '6')
      optionList6 = ('7', '8', '9')
      optionList7 = ('z', 'x', 'y')
      # Set up the StringVars for each OptionMenu
      v1 = tk.StringVar()
      v2 = tk.StringVar()
      v3 = tk.StringVar()
      v4 = tk.StringVar()
      v5 = tk.StringVar()
      v6 = tk.StringVar()
      v7 = tk.StringVar()
      
      # tk.OptionMenu requires the default option
      # to be declared via the set() method.
      v2.set(optionList2[1]) # Default tk.OptionMenu value for om2
      v3.set(optionList3[2]) # Default tk.OptionMenu item value for om3
      v5.set(optionList5[1]) # Default ttk.OptionMenu item value for om5
      
      # -------------------------------------------
      # tk OptionMenu om1 does not automatically
      # assign a default based on your list, so
      # this does not display a list item initially
      om1 = tk.OptionMenu(root, v1, *optionList1)
      
      # -------------------------------------------
      # om2 demonstrates the 'default' parameter
      # from a former ttk.OptionMenu is ignored by
      # tk.OptionMenu because it needs to have the
      # default list item set via v2.set() call.
      # Notice the 'e' is displayed initially as
      # set, but now 'd' is duplicated in the list
      # as a remnant of the former ttk.OptionMenu
      # 'default' parameter.
      om2 = tk.OptionMenu(root, v2, optionList2[0], *optionList2)
      
      # -------------------------------------------
      # om3 is a tk.OptionMenu and has no 'default'
      # paramter declared like om2 above does.  Its
      # default is set to option 2, or 'j', and is
      # initially displayed on the dropdown.  None
      # of the OptionMenu list items are duplicated.
      om3 = tk.OptionMenu(root, v3, *optionList3)
      
      # -------------------------------------------
      # om4 shows how the 'default' parameter
      # from a former ttk.OptionMenu is ignored by
      # tk.OptionMenu because it needs to have the
      # default list item set via v4.set() call.
      # Since v4 is not set, nothing at all is
      # diplayed initially and when the OptionMenu
      # is clicked, it will show that '1' is listed
      # twice.
      om4 = tk.OptionMenu(root, v4, optionList4[0], *optionList4)
      
      # -------------------------------------------
      # by changing a tk.OptionMenu to a
      # ttk.OptionMenu, without properly declaring
      # the default OptionMenu item in the ttk way
      # will result in item '5' not being displayed
      # initially, and '4' will not be displayed in
      # the OptionMenu choices after a choice has
      # been made.
      om5 = ttk.OptionMenu(root, v5, *optionList5)
      
      # -------------------------------------------
      # om6 is the same as om5, except it does not
      # have a tk.OptionMenu default declared.  It
      # is only here for consiceness.
      om6 = ttk.OptionMenu(root, v6, *optionList6)
      
      # -------------------------------------------
      # om7 is the proper way to declare a
      # ttk.OptionMenu, with a default option
      # initially set.
      om7 = ttk.OptionMenu(root, v7, optionList7[2], *optionList7)
      
      # Pack'em all up
      om1.pack()
      om2.pack()
      om3.pack()
      om4.pack()
      om5.pack()
      om6.pack()
      om7.pack()
      
      # Execute the mainloop
      root.mainloop()
      

      我知道代码对某些人来说可能很难看,如果您真的想更改它,请继续。 :)

      【讨论】:

      • 帮助很大!
      【解决方案4】:

      只是添加其他人的答案,因为他们不适合我。我发现如果您没有在 StringVar/IntVar 中设置小部件选项,它不会显示已设置的标准值。这可能看起来很愚蠢,但我花了很多时间才弄清楚这一点。希望对你有帮助,再见。 示例:

      master = tk.Tk()
      var = tk.StringVar(master)
      master.mainloop()
      

      【讨论】:

        【解决方案5】:

        ttk.OptionMenu 命令的签名是这样的:

        def __init__(self, master, variable, default=None, *values, **kwargs):
        

        这是文档字符串:

        """构造一个以master为父的主题OptionMenu小部件, 资源 textvariable 设置为变量,最初选择的值 由默认参数指定,菜单值由 *值和其他关键字。

        注意值列表之前的default 选项。不要在值列表中添加空白项,而是添加您想要的任何值作为默认值:

        options = ['1', '2', '3']
        dropdown = ttk.OptionMenu(masterframe, value, options[1], *options)
        

        【讨论】:

        • 哈哈,太好了,你在我需要的 4 小时前为一个 1 岁的问题添加了一个很好的答案。
        • 这应该被接受为正确答案,以避免与其他答案混淆。
        猜你喜欢
        • 2022-01-01
        • 1970-01-01
        • 2021-04-29
        • 2019-07-04
        • 2016-05-10
        • 1970-01-01
        • 2021-03-09
        • 2021-01-03
        相关资源
        最近更新 更多