user1978912
user1978912

Reputation: 47

Tkinter.OptionMenu not working as expected

I have been hacking at python for a little while, and not really a programmer as such, so as a last resort I am asking for help here. I have been googling the heck out of this all day, and I just can't seem to crack it.

In this code, which was lifted from an example from SE, the commented out lines

#self.Val2Txt = Tkinter.Entry(stepOne)

work just fine. But I actually need 2 dropdowns instead.

So I added the lines below the commented ones,

self.Val1Txt = Tkinter.OptionMenu(stepOne, 'Choose a Playlist', 'a','b','c')

When I run the script, as soon as I touch the dropdowns I get the error

AttributeError: 'str' object has no attribute 'set'

And they don't take the selection

And if I hit the submit button, I get the error

AttributeError: OptionMenu instance has no attribute 'get'

` ... and the window still persists, whereas the original would quit the window when submit was pressed.

I read that OptionMenu requires a "command" but I could not find out how to successfully do that. Here is the code, I hope it's just something simple I have missed/messed.

    #!/usr/bin/env python

import Tkinter
from Tkinter import *
import Tkinter, tkFileDialog

class Values(Tkinter.Tk):
    """docstring for Values"""
    def __init__(self, parent):
        Tkinter.Tk.__init__(self,parent)
        self.parent = parent
        self.initialize()

    def initialize(self):
        self.grid()
        stepOne = Tkinter.LabelFrame(self, text=" Choose A Playlist ")
        stepOne.grid(row=0, columnspan=7, sticky='W',padx=5, pady=5, ipadx=5, ipady=5)
        self.Val1Lbl = Tkinter.Label(stepOne,text="Playlist")
        self.Val1Lbl.grid(row=0, column=0, sticky='E', padx=10, pady=2)
        #self.Val1Txt = Tkinter.Entry(stepOne)        
        self.Val1Txt = Tkinter.OptionMenu(stepOne, 'Choose a Playlist', 'a','b','c')
        self.Val1Txt.grid(row=0, column=1, columnspan=4, pady=2, sticky='WE')
        self.Val2Lbl = Tkinter.Label(stepOne,text="Directory")
        self.Val2Lbl.grid(row=1, column=0, sticky='E', padx=10, pady=2)
        #self.Val2Txt = Tkinter.Entry(stepOne)
        self.Val2Txt = Tkinter.OptionMenu(stepOne, 'Select Something', 'd','e','f')
        self.Val2Txt.grid(row=1, column=1, columnspan=4, pady=2, sticky='WE')

        self.val1 = None
        self.val2 = None

        SubmitBtn = Tkinter.Button(stepOne, text="Submit",command=self.submit)
        SubmitBtn.grid(row=4, column=3, sticky='W', padx=5, pady=2)

    def submit(self):
        self.val1=self.Val1Txt.get()
        if self.val1=="":
            Win2=Tkinter.Tk()
            Win2.withdraw()

        self.val2=self.Val2Txt.get()
        if self.val2=="":
            Win2=Tkinter.Tk()
            Win2.withdraw()

        self.quit()


if __name__ == '__main__':
    app = Values(None)
    app.title('Values')
    app.mainloop() #this will run until it closes
    #Print the stuff you want.
    print app.val1,app.val2

Upvotes: 2

Views: 3349

Answers (2)

rolika
rolika

Reputation: 391

The Entry widget has the method .get(), that's why it's working. However, the Optionmenu widget works different: it needs a StringVar(), that holds the selected item. The .get() method in your submit() method works with these StringVars.

Declare two StringVars in the initialize() method:

self.s1, self.s2 = StringVar(), StringVar()

Then add these StringVars to the OptionMenus as the second parameter:

self.Val1Txt = Tkinter.OptionMenu(stepOne, self.s1, 'Choose a Playlist', 'a','b','c')
self.Val2Txt = Tkinter.OptionMenu(stepOne, self.s2, 'Select Something', 'd','e','f')

Anything after the second parameter is considered as choice, so don't display there messages (or filter them when selected), just the options ('Choose a PlayList' and 'Select Something' are valid selection options).

In the submit() method, get the StringVar's values:

self.val1 = self.s1.get()
self.val2 = self.s2.get()

I hope this helps a bit along :-)

Upvotes: 1

Bryan Oakley
Bryan Oakley

Reputation: 386342

The first argument when creating an option menu is the parent. You've got that right. The second argument must be a special tkinter variable (eg: StringVar). This object has the methods get and set. However, you're not passing in one of these variables, you're passing in a string. Strings don't have these messages, which is why you get the error you say you do.

Change your option menu to look like this:

self.Val1Var = StringVar()
self.Val1Txt = Tkinter.OptionMenu(stepOne, self.Val1Var, 'Choose a Playlist', 'a','b','c')

Later, when you want the value, you can use the get method on the variable:

self.val1=self.Val1Var.get()

For more information on OptionMenu see the OptionMenu page on effbot. You can also do a google or bing search on "tkinter optionmenu", and you'll find lots of stackoverflow answers related to option menus, as well as links to other sites that discuss the option menu.

Upvotes: 2

Related Questions