Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
5 changes: 5 additions & 0 deletions Doc/library/tkinter.rst
Original file line number Diff line number Diff line change
Expand Up @@ -4844,6 +4844,8 @@ Widget classes
is the initial choice, and *values* are the remaining menu entries.
The keyword argument *command* may be given a callback that is invoked with
the selected value, and the keyword argument *name* sets the Tk widget name.
Other keyword arguments are passed to the underlying :class:`Menubutton`
and may override its default appearance.

.. method:: destroy()

Expand All @@ -4852,6 +4854,9 @@ Widget classes
.. versionchanged:: 3.14
Added support for the *name* keyword argument.

.. versionchanged:: next
Other :class:`Menubutton` options can now be passed as keyword arguments.



.. class:: PanedWindow(master=None, cnf={}, **kw)
Expand Down
4 changes: 4 additions & 0 deletions Doc/whatsnew/3.16.rst
Original file line number Diff line number Diff line change
Expand Up @@ -216,6 +216,10 @@ tkinter
dithered image when its data was supplied in pieces.
(Contributed by Serhiy Storchaka in :gh:`151888`.)

* :class:`tkinter.OptionMenu` now accepts arbitrary :class:`!tkinter.Menubutton`
options as keyword arguments, which can also override its default appearance.
(Contributed by Serhiy Storchaka in :gh:`101284`.)

xml
---

Expand Down
17 changes: 15 additions & 2 deletions Lib/test/test_tkinter/test_widgets.py
Original file line number Diff line number Diff line change
Expand Up @@ -437,9 +437,22 @@ class OptionMenuTest(MenubuttonTest, unittest.TestCase):
def create(self, default='b', values=('a', 'b', 'c'), **kwargs):
return tkinter.OptionMenu(self.root, None, default, *values, **kwargs)

def test_kwargs(self):
# Menubutton options can be passed at construction (gh-101284).
widget = tkinter.OptionMenu(self.root, None, 'b',
width=10, direction='right')
self.assertEqual(int(widget['width']), 10)
self.assertEqual(str(widget['direction']), 'right')
# They override OptionMenu's own appearance defaults,
widget = tkinter.OptionMenu(self.root, None, 'b', relief='flat')
self.assertEqual(str(widget['relief']), 'flat')
# which otherwise keep their historical values.
widget = tkinter.OptionMenu(self.root, None, 'b')
self.assertEqual(str(widget['relief']), 'raised')

def test_bad_kwarg(self):
with self.assertRaisesRegex(TclError, r"^unknown option -image$"):
tkinter.OptionMenu(self.root, None, 'b', image='')
with self.assertRaisesRegex(TclError, r'^unknown option "-spam"$'):
tkinter.OptionMenu(self.root, None, 'b', spam='')

def test_specify_name(self):
widget = tkinter.OptionMenu(self.root, None, ':)', name="option_menu")
Expand Down
23 changes: 13 additions & 10 deletions Lib/tkinter/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -4516,20 +4516,23 @@ def __init__(self, master, variable, value, *values, **kwargs):
"""Construct an optionmenu widget with the parent MASTER, with
the option textvariable set to VARIABLE, the initially selected
value VALUE, the other menu values VALUES and an additional
keyword argument command."""
kw = {"borderwidth": 2, "textvariable": variable,
"indicatoron": 1, "relief": RAISED, "anchor": "c",
"highlightthickness": 2, "name": kwargs.pop("name", None)}
keyword argument command.

Other keyword arguments are passed to the underlying menubutton
and may override its default appearance."""
name = kwargs.pop("name", None)
callback = kwargs.pop("command", None)
# Default appearance, which may be overridden by keyword arguments.
kw = {"borderwidth": 2, "indicatoron": 1, "relief": RAISED,
"anchor": "c", "highlightthickness": 2}
kw.update(kwargs)
# These options are controlled by OptionMenu itself.
kw["textvariable"] = variable
kw["name"] = name
Widget.__init__(self, master, "menubutton", kw)
self.widgetName = 'tk_optionMenu'
menu = self.__menu = Menu(self, name="menu", tearoff=0)
self.menuname = menu._w
# 'command' is the only supported keyword
callback = kwargs.get('command')
if 'command' in kwargs:
del kwargs['command']
if kwargs:
raise TclError('unknown option -'+next(iter(kwargs)))
menu.add_command(label=value,
command=_setit(variable, value, callback))
for v in values:
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
:class:`tkinter.OptionMenu` now accepts arbitrary :class:`!tkinter.Menubutton`
options as keyword arguments and uses them to override its default appearance.
Loading