简体   繁体   中英

Tkinter OptionMenu items being read as values for master

I'm building a temporary interface for my game project so that I can interact with it and test it while waiting on the artwork to come through, which involves drop-down menus to select moves. I just can't seem to get the OptionMenu widget to work.

I've seen plenty of people call it in the style:

optionmenu=tkinter.OptionMenu(master, variable, *listitems)

And in context, that looks like:

UI.window=tkinter.Tk(className='/Temporary Interface')
standard_move=tkinter.StringVar()
standard_move.set('Attack')
standard_moves=tkinter.OptionMenu(master=UI.window,variable=standard_move,*list(UI.party[UI.control.get()].normal_moves))

where UI.party[UI.control.get()] is an instance of a custom class representing a combatant, and normal_moves is a dictionary attribute of the class of the form {'Move Name':move_function} , so I'm passing in and unpacking a list of all the names of the moves that the player has on offer as their current character.

Running it yields the error TypeError: __init__() got multiple values for argument 'master' , and I have no idea why. A bit of help identifying the reason and fixing the bug would be of great help.

OptionMenu(master=UI.window,variable=standard_move,*list(UI.party[UI.control.get()].normal_moves))

When you mix keyword arguments and packed positional arguments like this, the *list gets bound to the positional parameters first, putting the first element of the list for master , the second for variable , and the remainder for the option items. Then the keyword arguments try to bind themselves to master and variable , but a TypeError occurs because those names already have a value.

Consider this simpler example:

def f(a,b,c):
    print(a,b,c)

f(a=23, *[42,99])
#TypeError: f() got multiple values for argument 'a'

Try passing in the first two arguments without using their names.

standard_moves=tkinter.OptionMenu(UI.window,standard_move,*list(UI.party[UI.control.get()].normal_moves))

Don't say:

OptionMenu(master=UI.window, ...

Instead say:

OptionMenu(UI.window, ...

In other words, don't use the master keyword. The first value is not optional. Keywords are often used with optional arguments and to make APIs cleaner.

Also, don't use the variable keyword either. Just pass in the values.

The system is complaining about "multiple values" for master due to the use of the keyword. I would guess that the system, not seeing a non-keyword argument passed in as master, assumes that master is either None or the first item from *listitems. And then it sees your master= and complains about the multiple values. I just ran this simple test case to prove it. putting master=root and variable=variable reproduces your error.

from tkinter import *

root = Tk()
variable = StringVar()
values = list('abc')
option = OptionMenu(root, variable, *values)
option.pack()
root.mainloop()

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM