Hi,

The same code as my previous post, but because of this list thing, i'm not able to run specific commands for different options. Here i have 2 options under the 'Names' Menu, 'rajat','prasun', now when the user selects either of them i should be able to know which one he selected and run the command associated for it. i've tried some stuff like trying to use 'variable' or 'value' properties but its just not working.. any hints would be helpful..

from Tkinter import *

fileObj = open("c:/test","w")
fileObj.write("rajat")
fileObj.write("\n")
fileObj.write("prasun")
fileObj.close()

file1 = open("c:/test","r")
lines = file1.readlines()
file1.close()

root = Tk()
menubar = Menu(root)
filemenu = Menu(menubar)
menubar.add_cascade(label="Names",menu=filemenu)

for line in lines:
    filemenu.add_cascade(label=line)

root.config(menu=menubar)
root.mainloop()

Dani AI

Generated

Short summary and a simple, robust fix for a dynamic menu of names (one handler, identify which item was clicked).

The original loop used add_cascade and created menu entries without attaching a callable target. For per-item actions prefer add_command and capture the label at creation time so the handler knows which item was chosen. Two safe ways to capture the current label inside the loop are: use a lambda with a default argument, or use functools.partial. Both avoid the common late-binding pitfall where every command ends up using the final loop value.

Example using a lambda default (strip newlines when building the label):

def open_topic(name):
    name = name.strip()
    # load/process file named after 'name'

for raw in lines:
    label = raw.strip()
    filemenu.add_command(label=label, command=lambda l=label: open_topic(l))

Same idea with functools.partial:

from functools import partial

for raw in lines:
    label = raw.strip()
    filemenu.add_command(label=label, command=partial(open_topic, label))

Notes and cautions:

  • discovered the radiobutton/variable approach; that is useful if the menu should show a persistent selected state. Use a shared StringVar for that case and read var.get() when needed.
  • ’s pointer to Tkinter docs is on the right track: add_command is the usual way to add clickable menu items, while add_cascade is for attaching submenus.
  • Always strip() labels read from files, use with open(...) for safe file handling, and sanitize labels when turning them into filenames.
  • In modern Python use tkinter (lowercase) on Python 3; on older codebases Tkinter (capital T) appears.

Recommended Answers

All 3 Replies

A Google for "Tkinter menu" will yield numerous examples. New Mexico Tech
and Fredrik Lundh http://hem1.passagen.se/eff/
have good Tkinter sites. The following code came from "Charming Python", also a good site. http://www.ibm.com/developerworks/linux/library/l-tkprg/#h5

def help_menu():
    help_btn = Tkinter.Menubutton(menu_frame, text='Help', underline=0)
    help_btn.pack(side=Tkinter.LEFT, padx="2m")
    help_btn.menu = Tkinter.Menu(help_btn)
    help_btn.menu.add_command(label="How To", underline=0, command=HowTo)
    help_btn.menu.add_command(label="About", underline=0, command=About)
    help_btn['menu'] = help_btn.menu
    return help_btn

hi..
I havn't checked the links yet but this example is not what i want, Here we are calling a separate command for each menu option, however i have to be able to call the same command for each Menu option but in the function i should be able to find out that from which Menu Option the call has come so that i can do some specific work then. Basically for each Menu Option i will have a file of the same menu name in some locaion. So if i can make out the 'label' property in the function i can simply replace the file name with the 'label' name and thus using just one fn i can accomplish this. i need this because the menu options are extensible also, so i cant dynamically keep adding more fns for new menu's. hence i need to fire just one command for each option

Ok so i found that out ... we need use the 'variable' and 'value' properties of the radiobutton

something like:

self.filemenu.insert_radiobutton(label=topic.strip(),index=self.indexVal,variable=self.v,value=topic.strip(),
                                             command=self.ShowTopicContent)

now when the user clicks on any menu i can check for the 'variable' value. self.v is a string

print self.v.get()

This gives me the 'value' property and i can identify which option was selected.

Keeping this still open, incase someone has a better way of doing it..

Be a part of the DaniWeb community

We're a friendly, industry-focused community of developers, IT pros, digital marketers, and technology enthusiasts meeting, networking, learning, and sharing knowledge.