tkinter optionmenu первый вариант исчезает

Виджет 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 не будет показывать первый вариант при нажатии (Tkinter)

Кажется, они нашли обходной путь, но не поняли, почему это происходит.

ОБНОВЛЕНИЕ: на самом деле такое поведение проявляется только при использовании виджета ttk. Виджет tk работает нормально (хоть и выглядит очень некрасиво).


person Tom    schedule 02.10.2013    source источник


Ответы (5)


Сигнатура команды ttk.OptionMenu такова:

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

Это строка документации:

"" "Создайте тематический виджет OptionMenu с главным элементом в качестве родителя, текстовой переменной ресурса, установленной в значение переменной, первоначально выбранным значением, заданным параметром по умолчанию, значениями меню, заданными * значениями и дополнительными ключевыми словами.

Обратите внимание на параметр default, который стоит перед списком значений. Вместо добавления пустого элемента в список значений добавьте любое значение по умолчанию:

options = ['1', '2', '3']
dropdown = ttk.OptionMenu(masterframe, value, options[1], *options)
person Bryan Oakley    schedule 09.08.2014
comment
ха-ха, отлично, вы добавили хороший ответ на вопрос годовалой давности ровно за 4 часа до того, как он мне понадобился. - person Gregor; 09.08.2014
comment
Это следует принять как правильный ответ, чтобы избежать путаницы с другими ответами. - person Cool Cloud; 12.08.2020

У меня был такой же вопрос в другом посте. Я действительно прочитал этот пост и ответы, но не заметил тонких различий между этими двумя меню опций. Итак, вот и мой ответ, хотя я новичок в Python и tkinter.

Как ответил @Bryan Oakley, да, строка документа показывает, что существует «дополнительный» обязательный параметр при использовании ttk.OptionMenu, а не tk.OptionMenu. Эта разница нарушит (или, по крайней мере, испортит) ваше меню, если вы волей-неволей измените объявление с ttk.OptionMenu обратно на tk.OptionMenu. Это потому, что tk.OptionMenu не требует объявления опции «по умолчанию». Если вы по какой-то причине измените ttk.OptionMenu обратно на tk.OptionMenu и оставите параметр default в объявлении, он будет дублировать первый параметр в 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()

Я знаю, что код может кому-то показаться некрасивым, и если вы действительно хотите его изменить, продолжайте. :)

person SouthernYankee65    schedule 13.10.2019
comment
Это очень помогло! - person Arkadiy Stepanov; 02.04.2020

просто добавляю к ответам других парней, так как они не работали для меня. Я обнаружил, что если вы не установите параметр виджета в StringVar / IntVar, он не покажет установленное стандартное значение. Это может показаться глупым, но мне потребовалось много времени, чтобы понять это. Надеюсь, это поможет, увидимся. Пример:

master = tk.Tk()
var = tk.StringVar(master)
master.mainloop()
person Pedro Moresco    schedule 21.11.2018

Старый пост, но я подумал, что добавлю к этому разговору. Очень простой способ сделать первый (или любой элемент в вашем списке) отображаемым по умолчанию на Mac при использовании tk.OptionMenu - использовать 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, чтобы установить, какое значение является «установленным». Надеюсь, это поможет!

person trozzel    schedule 30.12.2019

Кажется, что с 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

person J. Nunes    schedule 07.10.2013
comment
Хотя ваш обходной путь работает, это не очень хорошее описание проблемы. ttk.OptionMenu ожидает значение по умолчанию после аргумента переменной и перед списком значений. Пока ваше решение работает, оно скрывает то, что на самом деле происходит. - person Bryan Oakley; 09.08.2014
comment
Хахаха, мне это очень нравится !! - person StackG; 17.06.2018