Fixed no tooltips when keep on top, StatusBar - New Element, Disabled state for menu items
This commit is contained in:
parent
21c3dd83f0
commit
c9ed11faeb
128
PySimpleGUI.py
128
PySimpleGUI.py
|
@ -183,6 +183,9 @@ TIMEOUT_KEY = '__TIMEOUT__'
|
||||||
# Key indicating should not create any return values for element
|
# Key indicating should not create any return values for element
|
||||||
WRITE_ONLY_KEY = '__WRITE ONLY__'
|
WRITE_ONLY_KEY = '__WRITE ONLY__'
|
||||||
|
|
||||||
|
MENU_DISABLED_CHARACTER = '!'
|
||||||
|
|
||||||
|
|
||||||
# a shameful global variable. This represents the top-level window information. Needed because opening a second window is different than opening the first.
|
# a shameful global variable. This represents the top-level window information. Needed because opening a second window is different than opening the first.
|
||||||
class MyWindows():
|
class MyWindows():
|
||||||
def __init__(self):
|
def __init__(self):
|
||||||
|
@ -254,6 +257,7 @@ ELEM_TYPE_TABLE = 'table'
|
||||||
ELEM_TYPE_TREE = 'tree'
|
ELEM_TYPE_TREE = 'tree'
|
||||||
ELEM_TYPE_ERROR = 'error'
|
ELEM_TYPE_ERROR = 'error'
|
||||||
ELEM_TYPE_SEPARATOR = 'separator'
|
ELEM_TYPE_SEPARATOR = 'separator'
|
||||||
|
ELEM_TYPE_STATUSBAR = 'statusbar'
|
||||||
|
|
||||||
# ------------------------- Popup Buttons Types ------------------------- #
|
# ------------------------- Popup Buttons Types ------------------------- #
|
||||||
POPUP_BUTTONS_YES_NO = 1
|
POPUP_BUTTONS_YES_NO = 1
|
||||||
|
@ -310,6 +314,8 @@ class ToolTip:
|
||||||
self.tipwindow = tk.Toplevel(self.widget)
|
self.tipwindow = tk.Toplevel(self.widget)
|
||||||
self.tipwindow.wm_overrideredirect(True)
|
self.tipwindow.wm_overrideredirect(True)
|
||||||
self.tipwindow.wm_geometry("+%d+%d" % (x, y))
|
self.tipwindow.wm_geometry("+%d+%d" % (x, y))
|
||||||
|
self.tipwindow.wm_attributes("-topmost", 1)
|
||||||
|
|
||||||
label = ttk.Label(self.tipwindow, text=self.text, justify=tk.LEFT,
|
label = ttk.Label(self.tipwindow, text=self.text, justify=tk.LEFT,
|
||||||
background="#ffffe0", relief=tk.SOLID, borderwidth=1)
|
background="#ffffe0", relief=tk.SOLID, borderwidth=1)
|
||||||
label.pack()
|
label.pack()
|
||||||
|
@ -1063,6 +1069,56 @@ Txt = Text
|
||||||
T = Text
|
T = Text
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
# ---------------------------------------------------------------------- #
|
||||||
|
# StatusBar #
|
||||||
|
# ---------------------------------------------------------------------- #
|
||||||
|
class StatusBar(Element):
|
||||||
|
def __init__(self, text, size=(None, None), auto_size_text=None, click_submits=None, relief=RELIEF_SUNKEN, font=None,
|
||||||
|
text_color=None, background_color=None, justification=None, pad=None, key=None, tooltip=None):
|
||||||
|
'''
|
||||||
|
Text Element
|
||||||
|
:param text:
|
||||||
|
:param size:
|
||||||
|
:param auto_size_text:
|
||||||
|
:param click_submits:
|
||||||
|
:param relief:
|
||||||
|
:param font:
|
||||||
|
:param text_color:
|
||||||
|
:param background_color:
|
||||||
|
:param justification:
|
||||||
|
:param pad:
|
||||||
|
:param key:
|
||||||
|
:param tooltip:
|
||||||
|
'''
|
||||||
|
self.DisplayText = text
|
||||||
|
self.TextColor = text_color if text_color else DEFAULT_TEXT_COLOR
|
||||||
|
self.Justification = justification
|
||||||
|
self.Relief = relief
|
||||||
|
self.ClickSubmits = click_submits
|
||||||
|
if background_color is None:
|
||||||
|
bg = DEFAULT_TEXT_ELEMENT_BACKGROUND_COLOR
|
||||||
|
else:
|
||||||
|
bg = background_color
|
||||||
|
super().__init__(ELEM_TYPE_STATUSBAR, size=size, auto_size_text=auto_size_text, background_color=bg, font=font or DEFAULT_FONT, text_color=self.TextColor, pad=pad, key=key, tooltip=tooltip)
|
||||||
|
return
|
||||||
|
|
||||||
|
def Update(self, value=None, background_color=None, text_color=None, font=None):
|
||||||
|
if value is not None:
|
||||||
|
self.DisplayText = value
|
||||||
|
stringvar = self.TKStringVar
|
||||||
|
stringvar.set(value)
|
||||||
|
if background_color is not None:
|
||||||
|
self.TKText.configure(background=background_color)
|
||||||
|
if text_color is not None:
|
||||||
|
self.TKText.configure(fg=text_color)
|
||||||
|
if font is not None:
|
||||||
|
self.TKText.configure(font=font)
|
||||||
|
|
||||||
|
def __del__(self):
|
||||||
|
super().__del__()
|
||||||
|
|
||||||
|
|
||||||
# ---------------------------------------------------------------------- #
|
# ---------------------------------------------------------------------- #
|
||||||
# TKProgressBar #
|
# TKProgressBar #
|
||||||
# Emulate the TK ProgressBar using canvas and rectangles
|
# Emulate the TK ProgressBar using canvas and rectangles
|
||||||
|
@ -3907,6 +3963,11 @@ if sys.version_info[0] >= 3:
|
||||||
sub_menu_info = sub_menu_info[:pos] + sub_menu_info[pos + 1:]
|
sub_menu_info = sub_menu_info[:pos] + sub_menu_info[pos + 1:]
|
||||||
if sub_menu_info == '---':
|
if sub_menu_info == '---':
|
||||||
top_menu.add('separator')
|
top_menu.add('separator')
|
||||||
|
else:
|
||||||
|
if sub_menu_info[0] == MENU_DISABLED_CHARACTER:
|
||||||
|
top_menu.add_command(label=sub_menu_info[len(MENU_DISABLED_CHARACTER):], underline=pos,
|
||||||
|
command=lambda: Menu.MenuItemChosenCallback(element, sub_menu_info))
|
||||||
|
top_menu.entryconfig(sub_menu_info[len(MENU_DISABLED_CHARACTER):], state='disabled')
|
||||||
else:
|
else:
|
||||||
top_menu.add_command(label=sub_menu_info, underline=pos,
|
top_menu.add_command(label=sub_menu_info, underline=pos,
|
||||||
command=lambda: Menu.MenuItemChosenCallback(element, sub_menu_info))
|
command=lambda: Menu.MenuItemChosenCallback(element, sub_menu_info))
|
||||||
|
@ -3921,6 +3982,9 @@ if sys.version_info[0] >= 3:
|
||||||
if pos != -1:
|
if pos != -1:
|
||||||
if pos == 0 or sub_menu_info[i][pos - 1] != "\\":
|
if pos == 0 or sub_menu_info[i][pos - 1] != "\\":
|
||||||
sub_menu_info[i] = sub_menu_info[i][:pos] + sub_menu_info[i][pos + 1:]
|
sub_menu_info[i] = sub_menu_info[i][:pos] + sub_menu_info[i][pos + 1:]
|
||||||
|
if sub_menu_info[i][0] == MENU_DISABLED_CHARACTER:
|
||||||
|
top_menu.add_cascade(label=sub_menu_info[i][len(MENU_DISABLED_CHARACTER):], menu=new_menu, underline=pos, state='disabled')
|
||||||
|
else:
|
||||||
top_menu.add_cascade(label=sub_menu_info[i], menu=new_menu, underline=pos)
|
top_menu.add_cascade(label=sub_menu_info[i], menu=new_menu, underline=pos)
|
||||||
AddMenuItem(new_menu, sub_menu_info[i + 1], element, is_sub_menu=True)
|
AddMenuItem(new_menu, sub_menu_info[i + 1], element, is_sub_menu=True)
|
||||||
i += 1 # skip the next one
|
i += 1 # skip the next one
|
||||||
|
@ -3940,6 +4004,11 @@ else:
|
||||||
sub_menu_info = sub_menu_info[:pos] + sub_menu_info[pos + 1:]
|
sub_menu_info = sub_menu_info[:pos] + sub_menu_info[pos + 1:]
|
||||||
if sub_menu_info == '---':
|
if sub_menu_info == '---':
|
||||||
top_menu.add('separator')
|
top_menu.add('separator')
|
||||||
|
else:
|
||||||
|
if sub_menu_info[0] == MENU_DISABLED_CHARACTER:
|
||||||
|
top_menu.add_command(label=sub_menu_info[len(MENU_DISABLED_CHARACTER):], underline=pos,
|
||||||
|
command=lambda: Menu.MenuItemChosenCallback(element, sub_menu_info))
|
||||||
|
top_menu.entryconfig(sub_menu_info[len(MENU_DISABLED_CHARACTER):], state='disabled')
|
||||||
else:
|
else:
|
||||||
top_menu.add_command(label=sub_menu_info, underline=pos,
|
top_menu.add_command(label=sub_menu_info, underline=pos,
|
||||||
command=lambda: Menu.MenuItemChosenCallback(element, sub_menu_info))
|
command=lambda: Menu.MenuItemChosenCallback(element, sub_menu_info))
|
||||||
|
@ -3954,6 +4023,9 @@ else:
|
||||||
if pos != -1:
|
if pos != -1:
|
||||||
if pos == 0 or sub_menu_info[i][pos - 1] != "\\":
|
if pos == 0 or sub_menu_info[i][pos - 1] != "\\":
|
||||||
sub_menu_info[i] = sub_menu_info[i][:pos] + sub_menu_info[i][pos + 1:]
|
sub_menu_info[i] = sub_menu_info[i][:pos] + sub_menu_info[i][pos + 1:]
|
||||||
|
if sub_menu_info[i][0] == MENU_DISABLED_CHARACTER:
|
||||||
|
top_menu.add_cascade(label=sub_menu_info[i][len(MENU_DISABLED_CHARACTER):], menu=new_menu, underline=pos, state='disabled')
|
||||||
|
else:
|
||||||
top_menu.add_cascade(label=sub_menu_info[i], menu=new_menu, underline=pos)
|
top_menu.add_cascade(label=sub_menu_info[i], menu=new_menu, underline=pos)
|
||||||
AddMenuItem(new_menu, sub_menu_info[i + 1], element, is_sub_menu=True)
|
AddMenuItem(new_menu, sub_menu_info[i + 1], element, is_sub_menu=True)
|
||||||
i += 1 # skip the next one
|
i += 1 # skip the next one
|
||||||
|
@ -4517,7 +4589,12 @@ def PackFormIntoFrame(form, containing_frame, toplevel_form):
|
||||||
if pos != -1:
|
if pos != -1:
|
||||||
if pos == 0 or menu_entry[0][pos - 1] != "\\":
|
if pos == 0 or menu_entry[0][pos - 1] != "\\":
|
||||||
menu_entry[0] = menu_entry[0][:pos] + menu_entry[0][pos + 1:]
|
menu_entry[0] = menu_entry[0][:pos] + menu_entry[0][pos + 1:]
|
||||||
|
if menu_entry[0][0] == MENU_DISABLED_CHARACTER:
|
||||||
|
menubar.add_cascade(label=menu_entry[0][len(MENU_DISABLED_CHARACTER):], menu=baritem, underline=pos)
|
||||||
|
menubar.entryconfig(menu_entry[0][len(MENU_DISABLED_CHARACTER):], state='disabled')
|
||||||
|
else:
|
||||||
menubar.add_cascade(label=menu_entry[0], menu=baritem, underline=pos)
|
menubar.add_cascade(label=menu_entry[0], menu=baritem, underline=pos)
|
||||||
|
|
||||||
if len(menu_entry) > 1:
|
if len(menu_entry) > 1:
|
||||||
AddMenuItem(baritem, menu_entry[1], element)
|
AddMenuItem(baritem, menu_entry[1], element)
|
||||||
toplevel_form.TKroot.configure(menu=element.TKMenu)
|
toplevel_form.TKroot.configure(menu=element.TKMenu)
|
||||||
|
@ -4793,6 +4870,57 @@ def PackFormIntoFrame(form, containing_frame, toplevel_form):
|
||||||
elif element_type == ELEM_TYPE_SEPARATOR:
|
elif element_type == ELEM_TYPE_SEPARATOR:
|
||||||
separator = ttk.Separator(tk_row_frame, orient=element.Orientation, )
|
separator = ttk.Separator(tk_row_frame, orient=element.Orientation, )
|
||||||
separator.pack(side=tk.LEFT, padx=element.Pad[0], pady=element.Pad[1], fill='both', expand=True)
|
separator.pack(side=tk.LEFT, padx=element.Pad[0], pady=element.Pad[1], fill='both', expand=True)
|
||||||
|
# ------------------------- StatusBar element ------------------------- #
|
||||||
|
elif element_type == ELEM_TYPE_STATUSBAR:
|
||||||
|
# auto_size_text = element.AutoSizeText
|
||||||
|
display_text = element.DisplayText # text to display
|
||||||
|
if auto_size_text is False:
|
||||||
|
width, height = element_size
|
||||||
|
else:
|
||||||
|
lines = display_text.split('\n')
|
||||||
|
max_line_len = max([len(l) for l in lines])
|
||||||
|
num_lines = len(lines)
|
||||||
|
if max_line_len > element_size[0]: # if text exceeds element size, the will have to wrap
|
||||||
|
width = element_size[0]
|
||||||
|
else:
|
||||||
|
width = max_line_len
|
||||||
|
height = num_lines
|
||||||
|
# ---===--- LABEL widget create and place --- #
|
||||||
|
stringvar = tk.StringVar()
|
||||||
|
element.TKStringVar = stringvar
|
||||||
|
stringvar.set(display_text)
|
||||||
|
if auto_size_text:
|
||||||
|
width = 0
|
||||||
|
if element.Justification is not None:
|
||||||
|
justification = element.Justification
|
||||||
|
elif toplevel_form.TextJustification is not None:
|
||||||
|
justification = toplevel_form.TextJustification
|
||||||
|
else:
|
||||||
|
justification = DEFAULT_TEXT_JUSTIFICATION
|
||||||
|
justify = tk.LEFT if justification == 'left' else tk.CENTER if justification == 'center' else tk.RIGHT
|
||||||
|
anchor = tk.NW if justification == 'left' else tk.N if justification == 'center' else tk.NE
|
||||||
|
# tktext_label = tk.Label(tk_row_frame, textvariable=stringvar, width=width, height=height,
|
||||||
|
# justify=justify, bd=border_depth, font=font)
|
||||||
|
tktext_label = tk.Label(tk_row_frame, textvariable=stringvar, width=width, height=height,
|
||||||
|
justify=justify, bd=border_depth, font=font)
|
||||||
|
# Set wrap-length for text (in PIXELS) == PAIN IN THE ASS
|
||||||
|
wraplen = tktext_label.winfo_reqwidth() + 40 # width of widget in Pixels
|
||||||
|
if not auto_size_text and height == 1:
|
||||||
|
wraplen = 0
|
||||||
|
# print("wraplen, width, height", wraplen, width, height)
|
||||||
|
tktext_label.configure(anchor=anchor, wraplen=wraplen) # set wrap to width of widget
|
||||||
|
if element.Relief is not None:
|
||||||
|
tktext_label.configure(relief=element.Relief)
|
||||||
|
if element.BackgroundColor is not None and element.BackgroundColor != COLOR_SYSTEM_DEFAULT:
|
||||||
|
tktext_label.configure(background=element.BackgroundColor)
|
||||||
|
if element.TextColor != COLOR_SYSTEM_DEFAULT and element.TextColor is not None:
|
||||||
|
tktext_label.configure(fg=element.TextColor)
|
||||||
|
tktext_label.pack(side=tk.LEFT, padx=element.Pad[0], pady=element.Pad[1],fill=tk.BOTH, expand=True)
|
||||||
|
element.TKText = tktext_label
|
||||||
|
if element.ClickSubmits:
|
||||||
|
tktext_label.bind('<Button-1>', element.TextClickedHandler)
|
||||||
|
if element.Tooltip is not None:
|
||||||
|
element.TooltipObject = ToolTip(element.TKText, text=element.Tooltip, timeout=DEFAULT_TOOLTIP_TIME)
|
||||||
|
|
||||||
# ............................DONE WITH ROW pack the row of widgets ..........................#
|
# ............................DONE WITH ROW pack the row of widgets ..........................#
|
||||||
# done with row, pack the row of widgets
|
# done with row, pack the row of widgets
|
||||||
|
|
Loading…
Reference in New Issue