PySimpleGUI - Menubar



Most of the desktop applications have a menu system to trigger different operations based on user’s choice of options in the menu. In a typical application window, the menu bar is placed just below the title bar and above the client area of the window.

A menubar is a horizontal bar consisting of clickable buttons. When any of these buttons is clicked it generates a pull down list of option buttons. Such an option button triggers a click event which can be processed inside an event loop.

The menu system is designed just as the window layout is specified. It is also a list of lists. Each list has one or more strings. The starting string of the list at the first level is the caption for the button appearing in the horizontal menu bar. It is followed by a list of caption strings for the option buttons in the drop down menu. These option captions are in a list inside the first level list.

You may have a sub-menu under an option button, in which case the captions are put in a third level list. Likewise, the captions can be nested up to any level.

The general format of a menu definition is as follows:

menu_def = [
   ['Memu1', ['btn1', 'btn2', 'btn3', 'btn4',]],
   ['menu2', ['btn5', 'btn6','btn7', 'btn8'],],
]

To attach the menu system to the main layout of PysimpleGUI window, place the Menu object in the first row of the layout.

The Menu constructor is given the menu_def list as the argument. Other rows of the main layout may be given after the row having Menu object.

layout= [[psg.Menu(menu_def),[..], [..]]

In the code given below, we have a menu bar with File, Edit and Help menus, each having a few menu buttons in respective menu bar.

import PySimpleGUI as psg
menu_def = [['File', ['New', 'Open', 'Save', 'Exit', ]], ['Edit', ['Cut', 'Copy', 'Paste', 'Undo'], ],  ['Help', 'About...'], ]
layout = [[psg.Menu(menu_def)],
   [psg.Multiline("", key='-IN-',
   expand_x=True, expand_y=True)],
   [psg.Multiline("", key='-OUT-',
   expand_x=True, expand_y=True)],
   [psg.Text("", key='-TXT-',
   expand_x=True, font=("Arial Bold", 14))]
]
window = psg.Window("Menu", layout, size=(715, 300))
while True:
   event, values = window.read()
   print(event, values)

   if event != psg.WIN_CLOSED:
      window['-TXT-'].update(values[0] + "Menu Button Clicked")
   if event == 'Copy':
      txt = window['-IN-'].get()
   if event == 'Paste':
      window['-OUT-'].update(value=txt)
   if event == psg.WIN_CLOSED:
      break
window.close()

Below the Menubar, two Multiline elements are placed. The last row has a Text element.

When any menu option button is clicked, the event so generated is the caption of the button. This caption is displayed on the Text label in the last row. Refer to the following figure −

Menu Bar Display

When the Copy event occurs, the text in the upper multiline box with -INkey is stored in a txt variable. Afterwards, when Paste button is pressed, the -OUT- box is updated with the value of txt.

Menu Bar Edit

Menu button with Hot Key

To map a menu button with a key on the keyboard, put an ampersand & character before the desired character. For example, put & before File so that the string is '&File'. By doing so, the File menu can be accessed by pressing "Alf+F" key. Here "F" key is said to be a hot key.

Add hot keys to the menu buttons in our menu definition.

menu_def = [
   ['&File', ['&New', '&Open', '&Save', 'E&xit',]],
   ['&Edit', ['C&ut', '&Copy','&Paste', '&Undo'],],
   ['&Help', '&About...'],
]

When the code is run, the hot keys in the menu are shown as underlined.

Menu Button Hot Key

Right-click Menu

This menu is detached from the menubar which is at the top of the application window. Whenever the user presses the right click button of the mouse, this menu pops up at the same position where the click takes place.

In the menubar defined above, each list is a definition of a single menu. Such single menu definition can be attached to any element by the right_click_menu parameter in the constructor. This parameter can also be passed while constructing the main Window object.

Let us use rightclick as a variable for the list corresponding to the Edit menu.

rightclick=['&Edit', ['C&ut', '&Copy','&Paste', '&Undo']]
menu_def = [
   ['&File', ['&New', '&Open', '&Save', 'E&xit',]], rightclick,
   ['&Help', '&About...'],
]

Use it as the value of right_click_menu parameter in the Window constructor. See the following snippet −

window=psg.Window("Menu", layout, size=(715, 300), right_click_menu=rightclick)

Make these changes and run the code. Click anywhere in the window. The menu pops up as shown −

Right Click Menu

ButtonMenu

This menu is similar to the right click menu, except that it is attached to a button and pops up when the button is clicked.

In the last row of the main layout, we add a ButtonMenu element and use the rightclick list as its layout.

layout= [
   [psg.Menu(menu_def)],
   [psg.Multiline("", key='-IN-', expand_x=True, expand_y=True)],
   [psg.Multiline("", key='-OUT-', expand_x=True, expand_y=True)],
   [psg.Text("", key='-TXT-', expand_x=True, font=("Arial Bold", 14)),
   psg.ButtonMenu('ButtonMenu', rightclick, key='-BMENU-')]
]

When the button at the lower right is clicked, the menu comes up as can be seen in the following figure −

ButtonMenu
Advertisements