#1
  1. No Profile Picture
    Registered User
    Devshed Newbie (0 - 499 posts)

    Join Date
    Mar 2004
    Posts
    9
    Rep Power
    0

    Help with submenu


    hey can someone help me make this submenu in Tkinter. I want it to be under the file menu under "New ..." and then a submenu with the templates listed. The templates are saved as .txt format in the templates folder variables Templates. Any help would be greatly appreciated.
    Last edited by Phreakster001; March 29th, 2004 at 05:04 PM.
  2. #2
  3. Mini me.
    Devshed Novice (500 - 999 posts)

    Join Date
    Nov 2003
    Location
    Cambridge, UK
    Posts
    783
    Rep Power
    13
    A sub-menu is created just like a standard menu, using the add_cascade method. Here is simple example :
    Code:
    from Tkinter import *
    def do_something():
        print "Doing something"
        
    root = Tk()
    # create a menu
    menu = Menu(root)
    root.config(menu=menu)
    filemenu = Menu(menu)
    menu.add_cascade(label="File", menu=filemenu)
    
    #Insert sub-menu here
    submenu = Menu(menu) # create a new menu
    filemenu.add_cascade(label="New ...",menu=submenu) # attach it to a parent menu
    submenu.add_command(label="Text File", command=do_something)
    submenu.add_command(label="Graphics File", command=do_something)
    
    #carry on with the filemenu
    filemenu.add_separator()
    filemenu.add_command(label="Exit", command=do_something)
    
    mainloop()
    This was a modified version of the menu1.py example taken from an-introduction-to-Tkinter [Menus]
  4. #3
  5. No Profile Picture
    Registered User
    Devshed Newbie (0 - 499 posts)

    Join Date
    Mar 2004
    Posts
    9
    Rep Power
    0
    Originally Posted by Grim Archon
    A sub-menu is created just like a standard menu, using the add_cascade method. Here is simple example :
    Code:
    from Tkinter import *
    def do_something():
        print "Doing something"
        
    root = Tk()
    # create a menu
    menu = Menu(root)
    root.config(menu=menu)
    filemenu = Menu(menu)
    menu.add_cascade(label="File", menu=filemenu)
    
    #Insert sub-menu here
    submenu = Menu(menu) # create a new menu
    filemenu.add_cascade(label="New ...",menu=submenu) # attach it to a parent menu
    submenu.add_command(label="Text File", command=do_something)
    submenu.add_command(label="Graphics File", command=do_something)
    
    #carry on with the filemenu
    filemenu.add_separator()
    filemenu.add_command(label="Exit", command=do_something)
    
    mainloop()
    This was a modified version of the menu1.py example taken from an-introduction-to-Tkinter [Menus]
    Ok thanks but I need to get all the filenames in an array or something so I can call them like say in the templates dir i have:
    • html.txt
    • blank.txt
    • C++.txt

    and I wanted it to put those names so in the submenu i can say New {template name} page so blank.txt would be New blank page etc. Thanks for the menu help though but I still need help with that.
    Last edited by Phreakster001; March 29th, 2004 at 07:28 PM.
  6. #4
  7. Mini me.
    Devshed Novice (500 - 999 posts)

    Join Date
    Nov 2003
    Location
    Cambridge, UK
    Posts
    783
    Rep Power
    13
    With a little thought making programatically generated menu items is easy enough:
    Code:
    from Tkinter import*
    
    #Some Templates
    Templates = {"Text": "text.txt", "Blank": "blank.txt", "C++": "cplusplus.txt"}
    
    def do_something(): 
        print "Doing something"
        
    def do_newfile(fname): 
        print "You want a new file:", fname
        
    root = Tk()
    # create a menu
    menu = Menu(root)
    root.config(menu = menu)
    filemenu = Menu(menu)
    menu.add_cascade(label = "File", menu = filemenu)
    
    #Insert sub-menu here
    submenu = Menu(menu) # create a new menu
    filemenu.add_cascade(label = "New ...", menu = submenu) # attach it to a parent menu
    #Pretty up the list - sort the keys first
    texts = Templates.keys()
    texts.sort()
    #build up the menu items using eval
    for text in texts: 
        menustr = '''submenu.add_command(label="New %s File", command=lambda : do_newfile("%s"))'''%(text, Templates[text])
        eval(menustr)
    
    #carry on with the filemenu
    filemenu.add_separator()
    filemenu.add_command(label = "Exit", command = do_something)
    
    mainloop()
    Personally I think using eval to make code in this way is but I could equally have used:
    Code:
    for text in texts: 
        submenu.add_command(label = "New %s File"%(text, ), command =  lambda: do_newfile(Templates[text]))
    If you want your program to pick up all/any templates in your template directory you will need to use glob (see the Python docs for details) to get the list of files. Where the menu text comes from is up to you - it could be the first line of each template for example or each template could have a description in a templates description file.

    Grim
  8. #5
  9. No Profile Picture
    Registered User
    Devshed Newbie (0 - 499 posts)

    Join Date
    Mar 2004
    Posts
    9
    Rep Power
    0
    Originally Posted by Grim Archon
    With a little thought making programatically generated menu items is easy enough:
    Code:
    from Tkinter import*
    
    #Some Templates
    Templates = {"Text": "text.txt", "Blank": "blank.txt", "C++": "cplusplus.txt"}
    
    def do_something(): 
        print "Doing something"
        
    def do_newfile(fname): 
        print "You want a new file:", fname
        
    root = Tk()
    # create a menu
    menu = Menu(root)
    root.config(menu = menu)
    filemenu = Menu(menu)
    menu.add_cascade(label = "File", menu = filemenu)
    
    #Insert sub-menu here
    submenu = Menu(menu) # create a new menu
    filemenu.add_cascade(label = "New ...", menu = submenu) # attach it to a parent menu
    #Pretty up the list - sort the keys first
    texts = Templates.keys()
    texts.sort()
    #build up the menu items using eval
    for text in texts: 
        menustr = '''submenu.add_command(label="New %s File", command=lambda : do_newfile("%s"))'''%(text, Templates[text])
        eval(menustr)
    
    #carry on with the filemenu
    filemenu.add_separator()
    filemenu.add_command(label = "Exit", command = do_something)
    
    mainloop()
    Personally I think using eval to make code in this way is but I could equally have used:
    Code:
    for text in texts: 
        submenu.add_command(label = "New %s File"%(text, ), command =  lambda: do_newfile(Templates[text]))
    If you want your program to pick up all/any templates in your template directory you will need to use glob (see the Python docs for details) to get the list of files. Where the menu text comes from is up to you - it could be the first line of each template for example or each template could have a description in a templates description file.

    Grim
    Um thats not what I mean I want it to virtually get the pages from that directory and put it in a dictionary not manually through the code so users can add them without changes arround the source code or anything.
  10. #6
  11. Mini me.
    Devshed Novice (500 - 999 posts)

    Join Date
    Nov 2003
    Location
    Cambridge, UK
    Posts
    783
    Rep Power
    13
    Um thats not what I mean I want it to virtually get the pages from that directory and put it in a dictionary not manually through the code so users can add them without changes arround the source code or anything.

    If you want your program to pick up all/any templates in your template directory you will need to use glob (see the Python docs for details) to get the list of files. Where the menu text comes from is up to you - it could be the first line of each template for example or each template could have a description in a templates description file.

    Grim
  12. #7
  13. No Profile Picture
    Registered User
    Devshed Newbie (0 - 499 posts)

    Join Date
    Mar 2004
    Posts
    9
    Rep Power
    0

    Cool


    Ok thats grim. I looked glob up and figured out how to do it. But well I got another problem I want my "Save" and "Save As ..." option under "File" to be disabled if no files are opened yet. How do I enable and disable them after creation?

    heres my code so far:
    Code:
    from Tkinter import *
    from ConfigParser import *
    import dircache
    # imports the necessary modules
    
    parse = ConfigParser()
    # creates a class for ConfigParser
    
    parse.read("prefs.ini")
    # reads the preferences file so ConfigParser can get the variables
    
    Dir = {
        "Plugins": parse.get("DIRECTORIES", "Plugins"),
        "Downloads": parse.get("DIRECTORIES", "Downloads"),
        "Incomplete": parse.get("DIRECTORIES", "Incomplete"),
        "Default": parse.get("DIRECTORIES", "Default"),
        "Skins": parse.get("DIRECTORIES", "Skins"),
        "Templates": parse.get("DIRECTORIES", "Templates")
        }
    # saves the directories as variables to call upon later
    
    Templates = dircache.listdir(Dir["Templates"])
    # puts the templates in a list
    
    for x in range(len(Templates)):
        Templates[x] = Templates[x][0:-4]
    # delete the last 4 letters of the filename which would be ".txt"
    
    Files = {}
    # make a blank file list of files opened in editor
    
    OpenFile = None
    # makes a variable to temporarily the file that needs to be opened
    
    Root = Tk()
    # creates the main (or root) widget
    
    Root.title("Webmaster-Kit")
    # changes the widgets title
    
    MainMenu = Menu(Root)
    # creates the main menu
    
    FileMenu = Menu(MainMenu)
    EditMenu = Menu(MainMenu)
    ViewMenu = Menu(MainMenu)
    SearchMenu = Menu(MainMenu)
    FTPMenu = Menu(MainMenu)
    ToolsMenu = Menu(MainMenu)
    HelpMenu = Menu(MainMenu)
    
    NewMenu = Menu(MainMenu)
    ServerMenu = Menu(MainMenu)
    InsertMenu = Menu(MainMenu)
    CaseMenu = Menu(MainMenu)
    RecentMenu = Menu(MainMenu)
    FormatMenu = Menu(MainMenu)
    # creates all the sub menus
    
    Root.config(menu=MainMenu)
    # sets the menu to display on the root widget
    
    MainMenu.add_cascade(label="File", menu=FileMenu)
    MainMenu.add_cascade(label="Edit", menu=EditMenu)
    MainMenu.add_cascade(label="View", menu=ViewMenu)
    MainMenu.add_cascade(label="Search", menu=SearchMenu)
    MainMenu.add_cascade(label="FTP", menu=FTPMenu)
    MainMenu.add_cascade(label="Tools", menu=ToolsMenu)
    MainMenu.add_cascade(label="Help", menu=HelpMenu)
    # displays the sub menus
    
    TemplateMenu = Menu(FileMenu)
    for x in range(len(Templates)):
        Page = Templates[x],"page"
        TemplateMenu.add_command(label=Page, command=OpenFile)
    
    FileMenu.add_cascade(label="New", menu=TemplateMenu)
    FileMenu.add_command(label="Open ..", command=TemplateMenu)
    FileMenu.add_command(label="Save", command=TemplateMenu)
    FileMenu.add_command(label="Save As ..", command=TemplateMenu)
    Root.mainloop()
    # stats the continuous loop that displays everything
    lol I feel like such a newb
    Last edited by Phreakster001; April 3rd, 2004 at 10:51 PM.
  14. #8
  15. Mini me.
    Devshed Novice (500 - 999 posts)

    Join Date
    Nov 2003
    Location
    Cambridge, UK
    Posts
    783
    Rep Power
    13
    One of the optional parameters in Menu creation is the postcommand which allows you to specify a function that is called prior to the menu being displayed.
    The following checks the state of a global variable and sets the state of your menu items accordingly. For the demo I just alternate this value each time the menu is displayed.
    Code:
    savemyfile = 'normal'
    def update(): 
        global savemyfile
        #The 'save' and 'save as' menu entries are at index 3 and 4
        # because your menu includes the tearoff dotted line
        FileMenu.entryconfig(3, state = savemyfile)
        FileMenu.entryconfig(4, state = savemyfile)
        #As an example the following just toggles the menu state
        if savemyfile == 'normal': 
            savemyfile = 'disabled'
        else: 
            savemyfile = 'normal'
        
    FileMenu = Menu(MainMenu, postcommand = update)
    I recommend you do read The Tkinter Manual

IMN logo majestic logo threadwatch logo seochat tools logo