commit
cafdc42b3b
|
@ -1,92 +1,73 @@
|
||||||
#!/usr/bin/env python
|
#!/usr/bin/env python
|
||||||
import PySimpleGUI as sg
|
import PySimpleGUI as sg
|
||||||
"""
|
"""
|
||||||
Demo - A Custom Menubar Element Simulated Using ButtonMenu Elements
|
Demo - The MenubarCustom element
|
||||||
|
|
||||||
|
With the addition of the Custom Titlebar came the addition of a problem with the
|
||||||
|
os provided menubar. It's not possible to use the custom titlebar with the
|
||||||
|
normal menubar. The menubar ends up being placed above the titlebar.
|
||||||
|
|
||||||
|
Enter the MenubarCustom!
|
||||||
|
|
||||||
|
This "Compound Element" is not really an element but rather a combination of
|
||||||
|
ButtonMenu elements and Column elements. It's possible for users to create a similar
|
||||||
|
construct. In fact, this element started as a Demo Program and then migrated into PySimpleGUI.
|
||||||
|
|
||||||
Because a Menubar is created by the OS and not the underlying GUI framework, the
|
At the moment, you cannot perform all of the same operations using this custom menubar
|
||||||
ability to customize the look and feel of the standard Menubar is not possible.
|
that you can with a traditional menubar. Modifying the menu isn't possible yet. In
|
||||||
|
other words, it's a great start, but more work is needed such as adding an update method, etc.
|
||||||
Additionally, the Titlebar Element and the Meny Element don't work well together.
|
|
||||||
The order gets swapped.
|
For statically defined menus, it works great. Shortuts are possible within the menus, but not
|
||||||
|
for the initial selection.
|
||||||
One way to get around all of the problems above is to simulate a Menu Element.
|
|
||||||
That's exactly what this demo does.
|
You can use the same menu defition as the standard Menu element.
|
||||||
|
|
||||||
|
The Menubar will tbe themed according to your current theme's colors. The theme's button
|
||||||
|
colors are used. All of the colors can be changed from the menubar to the menu's text an background.
|
||||||
|
|
||||||
|
The disabled color has a problem. The default tkinter gray is used even though PySimpleGUI sets the value.
|
||||||
The color choice for the menubar background and text use the theme's button colors.
|
The color choice for the menubar background and text use the theme's button colors.
|
||||||
You can change these color choices by changing the Menubar in the layout.
|
You can change these color choices by changing the Menubar in the layout.
|
||||||
|
|
||||||
Copyright 2021 PySimpleGUI
|
Copyright 2021 PySimpleGUI
|
||||||
"""
|
"""
|
||||||
|
|
||||||
sg.MENU_SHORTCUT_CHARACTER = '&'
|
|
||||||
|
|
||||||
def Menubar(menu_def, text_color, background_color, pad=(0, 0)):
|
|
||||||
"""
|
|
||||||
A User Defined element that simulates a Menu element by using ButtonMenu elements
|
|
||||||
|
|
||||||
:param menu_def: A standard PySimpleGUI menu definition
|
|
||||||
:type menu_def: List[List[Tuple[str, List[str]]]
|
|
||||||
:param text_color: color for the menubar's text
|
|
||||||
:type text_color:
|
|
||||||
:param background_color: color for the menubar's background
|
|
||||||
:type background_color:
|
|
||||||
:param pad: Amount of padding around each menu entry
|
|
||||||
:type pad:
|
|
||||||
:return: A column element that has a row of ButtonMenu buttons
|
|
||||||
:rtype: sg.Column
|
|
||||||
"""
|
|
||||||
row = []
|
|
||||||
for menu in menu_def:
|
|
||||||
text = menu[0]
|
|
||||||
if sg.MENU_SHORTCUT_CHARACTER in text:
|
|
||||||
text = text.replace(sg.MENU_SHORTCUT_CHARACTER, '')
|
|
||||||
if text.startswith(sg.MENU_DISABLED_CHARACTER):
|
|
||||||
disabled = True
|
|
||||||
text = text[len(sg.MENU_DISABLED_CHARACTER):]
|
|
||||||
else:
|
|
||||||
disabled = False
|
|
||||||
row += [sg.ButtonMenu(text, menu, border_width=0, button_color=f'{text_color} on {background_color}',key=text, pad=pad, disabled=disabled)]
|
|
||||||
|
|
||||||
return sg.Column([row], background_color=background_color, pad=(0,0), expand_x=True)
|
|
||||||
|
|
||||||
def main():
|
def main():
|
||||||
sg.theme('dark green 7')
|
sg.theme('dark green 7')
|
||||||
# sg.theme('dark gray 14')
|
# sg.theme('dark gray 13')
|
||||||
|
sg.theme('dark red')
|
||||||
|
# sg.theme('black')
|
||||||
|
|
||||||
menu_def = [['&File', ['&Open Ctrl-O', '&Save Ctrl-S', '&Properties', 'E&xit']],
|
menu_def = [['&File', ['&Open Ctrl-O', '&Save Ctrl-S', '&Properties', 'E&xit']],
|
||||||
['&Edit', [['Special', 'Normal',['Normal1', 'Normal2'] ], 'Undo'], ],
|
['&Edit', ['Me', 'Special', 'Normal',['Normal1', 'Normal2'] , 'Undo']],
|
||||||
['!Disabled', [['Special', 'Normal',['Normal1', 'Normal2'] ], 'Undo'], ],
|
['!Disabled', ['Special', 'Normal',['Normal1', 'Normal2'], 'Undo']],
|
||||||
['&Toolbar', ['---', 'Command &1::Command_Key', 'Command &2', '---', 'Command &3', 'Command &4']],
|
['&Toolbar', ['---', 'Command &1::Command_Key', 'Command &2', '---', 'Command &3', 'Command &4']],
|
||||||
['&Help', ['&About...']], ]
|
['&Help', ['&About...']], ]
|
||||||
|
|
||||||
layout = [
|
layout = [[sg.MenubarCustom(menu_def, pad=(0,0), k='-CUST MENUBAR-')],
|
||||||
# [sg.Menu(menu_def, tearoff=False, key='-MENU BAR-')], # This is how a Menu is normally defined
|
[sg.Multiline(size=(70, 20), reroute_cprint=True, write_only=True, no_scrollbar=True, k='-MLINE-')]]
|
||||||
[Menubar(menu_def, sg.theme_button_color()[1], sg.theme_button_color()[0], (5, 0))],
|
|
||||||
[sg.Multiline(size=(70, 20), reroute_stdout=True, reroute_cprint=True, write_only=True)],
|
|
||||||
]
|
|
||||||
|
|
||||||
window = sg.Window("Custom Titlebar with Custom (Simulated) Menubar", layout, use_custom_titlebar=True)
|
window = sg.Window("Custom Titlebar with Custom (Simulated) Menubar", layout, use_custom_titlebar=True, keep_on_top=True)
|
||||||
|
|
||||||
# ------ Event Loop ------ #
|
# ------ Event Loop ------ #
|
||||||
while True:
|
while True:
|
||||||
event, values = window.read()
|
event, values = window.read()
|
||||||
# convert ButtonMenu event so they look like Menu events
|
# convert ButtonMenu event so they look like Menu events
|
||||||
elem = window.find_element(event, silent_on_error=True)
|
|
||||||
if elem and elem.Type == sg.ELEM_TYPE_BUTTONMENU:
|
|
||||||
event = values[event]
|
|
||||||
|
|
||||||
if event in (sg.WIN_CLOSED, 'Exit'):
|
if event in (sg.WIN_CLOSED, 'Exit'):
|
||||||
break
|
break
|
||||||
|
|
||||||
sg.cprint(f'event = {event}', c='white on red')
|
sg.cprint(f'event = {event}', c=(sg.theme_background_color(), sg.theme_text_color()))
|
||||||
sg.cprint(f'values = {values}', c='white on green')
|
sg.cprint(f'values = {values}',c=(sg.theme_input_text_color(), sg.theme_input_background_color()))
|
||||||
|
|
||||||
# ------ Process menu choices ------ #
|
# ------ Process menu choices ------ #
|
||||||
if event == 'About...':
|
if event == 'About...':
|
||||||
window.disappear()
|
window.disappear()
|
||||||
sg.popup('About this program', 'Simulated Menubar to accompany a simulated Titlebar',
|
sg.popup('About this program', 'Simulated Menubar to accompany a simulated Titlebar',
|
||||||
'PySimpleGUI Version', sg.version, grab_anywhere=True, keep_on_top=True)
|
'PySimpleGUI Version', sg.get_versions(), grab_anywhere=True, keep_on_top=True)
|
||||||
window.reappear()
|
window.reappear()
|
||||||
|
elif event == 'Me':
|
||||||
|
sg.execute_editor(__file__)
|
||||||
elif event.startswith('Open'):
|
elif event.startswith('Open'):
|
||||||
filename = sg.popup_get_file('file to open', no_window=True)
|
filename = sg.popup_get_file('file to open', no_window=True)
|
||||||
print(filename)
|
print(filename)
|
||||||
|
|
|
@ -1,6 +1,6 @@
|
||||||
#!/usr/bin/python3
|
#!/usr/bin/python3
|
||||||
|
|
||||||
version = __version__ = "4.41.2.3 Unreleased\nFix for getting wrong tab number in Tab.update, added bind_return_key to Combo Element, new Sizegrip element, fixed grab_anywhere so that it doesn't grab multiline slider scrollbars input and a few other elements, changed Sizegrip parm to be grip_image which can be a filename or a bytestring, added a white sizegrip image in addition to the default black, improved tearoff menu placement, completed the MenubarCustom code (to Alpha quality perhaps)"
|
version = __version__ = "4.41.2.4 Unreleased\nFix for getting wrong tab number in Tab.update, added bind_return_key to Combo Element, new Sizegrip element, fixed grab_anywhere so that it doesn't grab multiline slider scrollbars input and a few other elements, changed Sizegrip parm to be grip_image which can be a filename or a bytestring, added a white sizegrip image in addition to the default black, improved tearoff menu placement, completed the MenubarCustom code including color settings for the bar and the menus"
|
||||||
|
|
||||||
__version__ = version.split()[0] # For PEP 396 and PEP 345
|
__version__ = version.split()[0] # For PEP 396 and PEP 345
|
||||||
|
|
||||||
|
@ -10402,17 +10402,13 @@ def Titlebar(title='',icon=None, text_color=None, background_color=None, font=No
|
||||||
|
|
||||||
|
|
||||||
# Not ready for prime time
|
# Not ready for prime time
|
||||||
def MenubarCustom(menu_definition, disabled_text_color=None, bar_font=None, font=None, tearoff=False, pad=None, bar_background_color=None, bar_text_color=None, key=None, k=None):
|
def MenubarCustom(menu_definition, disabled_text_color=None, bar_font=None, font=None, tearoff=False, pad=None, background_color=None, text_color=None, bar_background_color=None, bar_text_color=None, key=None, k=None):
|
||||||
"""
|
"""
|
||||||
A custom Menubar that replaces the OS provided Menubar
|
A custom Menubar that replaces the OS provided Menubar
|
||||||
THIS FEATURE IS NOT YET COMPLETE!
|
|
||||||
|
|
||||||
Why?
|
Why?
|
||||||
Two reasons - 1. they look great (see custom titlebar) 2. if you have a custom titlebar, then you have to use a custom menubar if you want a menubar
|
Two reasons - 1. they look great (see custom titlebar) 2. if you have a custom titlebar, then you have to use a custom menubar if you want a menubar
|
||||||
|
|
||||||
NOTE LINUX USERS - at the moment the minimize function is not yet working. Windows users
|
|
||||||
should have no problem and it should function as a normal window would.
|
|
||||||
|
|
||||||
:param menu_definition: The Menu definition specified using lists (docs explain the format)
|
:param menu_definition: The Menu definition specified using lists (docs explain the format)
|
||||||
:type menu_definition: List[List[Tuple[str, List[str]]]
|
:type menu_definition: List[List[Tuple[str, List[str]]]
|
||||||
:param disabled_text_color: color to use for text when item is disabled. Can be in #RRGGBB format or a color name "black"
|
:param disabled_text_color: color to use for text when item is disabled. Can be in #RRGGBB format or a color name "black"
|
||||||
|
@ -10425,33 +10421,27 @@ def MenubarCustom(menu_definition, disabled_text_color=None, bar_font=None, font
|
||||||
:type tearoff: (bool)
|
:type tearoff: (bool)
|
||||||
:param pad: Amount of padding to put around element (left/right, top/bottom) or ((left, right), (top, bottom))
|
:param pad: Amount of padding to put around element (left/right, top/bottom) or ((left, right), (top, bottom))
|
||||||
:type pad: (int, int) or ((int, int),(int,int)) or (int,(int,int)) or ((int, int),int)
|
:type pad: (int, int) or ((int, int),(int,int)) or (int,(int,int)) or ((int, int),int)
|
||||||
|
:param background_color: color to use for background of the menus that are displayed after making a section. Can be in #RRGGBB format or a color name "black". Defaults to the color of the bar text
|
||||||
|
:type background_color: (str)
|
||||||
|
:param text_color: color to use for the text of the many items in the displayed menus. Can be in #RRGGBB format or a color name "black". Defaults to the bar background
|
||||||
|
:type text_color: (str)
|
||||||
|
:param bar_background_color: color to use for the menubar. Can be in #RRGGBB format or a color name "black". Defaults to theme's button text color
|
||||||
|
:type bar_background_color: (str)
|
||||||
|
:param bar_text_color: color to use for the menu items text when item is disabled. Can be in #RRGGBB format or a color name "black". Defaults to theme's button background color
|
||||||
|
:type bar_text_color: (str)
|
||||||
:param key: Value that uniquely identifies this element from all other elements. Used when Finding an element or in return values. Must be unique to the window
|
:param key: Value that uniquely identifies this element from all other elements. Used when Finding an element or in return values. Must be unique to the window
|
||||||
:type key: str | int | tuple | object
|
:type key: str | int | tuple | object
|
||||||
:param k: Same as the Key. You can use either k or key. Which ever is set will be used.
|
:param k: Same as the Key. You can use either k or key. Which ever is set will be used.
|
||||||
:type k: str | int | tuple | object
|
:type k: str | int | tuple | object
|
||||||
:param visible: set visibility state of the element
|
:returns: A Column element that has a series of ButtonMenu elements
|
||||||
:type visible: (bool)
|
:rtype: Column
|
||||||
:param metadata: User metadata that can be set to ANYTHING
|
|
||||||
:type metadata: (Any)
|
|
||||||
"""
|
"""
|
||||||
#
|
|
||||||
# row = []
|
|
||||||
# for menu in menu_def:
|
|
||||||
# text = menu[0]
|
|
||||||
# if sg.MENU_SHORTCUT_CHARACTER in text:
|
|
||||||
# text = text.replace(sg.MENU_SHORTCUT_CHARACTER, '')
|
|
||||||
# if text.startswith(sg.MENU_DISABLED_CHARACTER):
|
|
||||||
# disabled = True
|
|
||||||
# text = text[len(sg.MENU_DISABLED_CHARACTER):]
|
|
||||||
# else:
|
|
||||||
# disabled = False
|
|
||||||
# row += [sg.ButtonMenu(text, menu, border_width=0, button_color=f'{text_color} on {background_color}',key=text, pad=pad, disabled=disabled)]
|
|
||||||
#
|
|
||||||
# return sg.Column([row], background_color=background_color, pad=(0,0), expand_x=True)
|
|
||||||
#
|
|
||||||
|
|
||||||
bar_bg = bar_background_color if bar_background_color is not None else theme_button_color()[0]
|
bar_bg = bar_background_color if bar_background_color is not None else theme_button_color()[0]
|
||||||
bar_text = bar_text_color if bar_text_color is not None else theme_button_color()[1]
|
bar_text = bar_text_color if bar_text_color is not None else theme_button_color()[1]
|
||||||
|
menu_bg = background_color if background_color is not None else bar_text
|
||||||
|
menu_text = text_color if text_color is not None else bar_bg
|
||||||
|
|
||||||
row = []
|
row = []
|
||||||
for menu in menu_definition:
|
for menu in menu_definition:
|
||||||
text = menu[0]
|
text = menu[0]
|
||||||
|
@ -10463,7 +10453,8 @@ def MenubarCustom(menu_definition, disabled_text_color=None, bar_font=None, font
|
||||||
else:
|
else:
|
||||||
disabled = False
|
disabled = False
|
||||||
|
|
||||||
button_menu = ButtonMenu(text, menu, border_width=0, button_color=(bar_text, bar_bg), key=text, pad=(0,0), disabled=disabled, font=bar_font, item_font=font, disabled_text_color=disabled_text_color, text_color=bar_bg, background_color=bar_text, tearoff=tearoff)
|
|
||||||
|
button_menu = ButtonMenu(text, menu, border_width=0, button_color=(bar_text, bar_bg), key=text, pad=(0,0), disabled=disabled, font=bar_font, item_font=font, disabled_text_color=disabled_text_color, text_color=menu_text, background_color=menu_bg, tearoff=tearoff)
|
||||||
button_menu.part_of_custom_menubar = True
|
button_menu.part_of_custom_menubar = True
|
||||||
button_menu.custom_menubar_key = key if key is not None else k
|
button_menu.custom_menubar_key = key if key is not None else k
|
||||||
row += [button_menu]
|
row += [button_menu]
|
||||||
|
|
Loading…
Reference in New Issue