Release 3.14.0, 1.14.0

This commit is contained in:
MikeTheWatchGuy 2018-11-02 12:29:20 -04:00
parent 090bc5d479
commit cc5ca4d814
3 changed files with 312 additions and 124 deletions

View File

@ -190,15 +190,18 @@ ThisRow = 555666777 # magic number
# DEFAULT_WINDOW_ICON = ''
MESSAGE_BOX_LINE_WIDTH = 60
# "Special" Key Values.. reserved
# Key representing a Read timeout
TIMEOUT_KEY = '__timeout__'
TIMEOUT_KEY = '__TIMEOUT__'
# Key indicating should not create any return values for element
WRITE_ONLY_KEY = '__WRITE ONLY__'
# 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(object):
def __init__(self):
self.NumOpenWindows = 0
self.user_defined_icon = None
self.hidden_master_root = None
def Decrement(self):
self.NumOpenWindows -= 1 * (self.NumOpenWindows != 0) # decrement if not 0
@ -405,7 +408,6 @@ class Element(object):
button_element.ButtonCallBack()
def ListboxSelectHandler(self, event):
MyForm = self.ParentForm
# first, get the results table built
# modify the Results table in the parent FlexForm object
if self.Key is not None:
@ -417,7 +419,6 @@ class Element(object):
self.ParentForm.TKroot.quit() # kick the users out of the mainloop
def ComboboxSelectHandler(self, event):
MyForm = self.ParentForm
# first, get the results table built
# modify the Results table in the parent FlexForm object
if self.Key is not None:
@ -428,8 +429,16 @@ class Element(object):
if self.ParentForm.CurrentlyRunningMainloop:
self.ParentForm.TKroot.quit() # kick the users out of the mainloop
def RadioHandler(self):
if self.Key is not None:
self.ParentForm.LastButtonClicked = self.Key
else:
self.ParentForm.LastButtonClicked = ''
self.ParentForm.FormRemainedOpen = True
if self.ParentForm.CurrentlyRunningMainloop:
self.ParentForm.TKroot.quit()
def CheckboxHandler(self):
MyForm = self.ParentForm
if self.Key is not None:
self.ParentForm.LastButtonClicked = self.Key
else:
@ -439,7 +448,6 @@ class Element(object):
self.ParentForm.TKroot.quit()
def TabGroupSelectHandler(self, event):
MyForm = self.ParentForm
if self.Key is not None:
self.ParentForm.LastButtonClicked = self.Key
else:
@ -449,7 +457,6 @@ class Element(object):
self.ParentForm.TKroot.quit()
def KeyboardHandler(self, event):
MyForm = self.ParentForm
if self.Key is not None:
self.ParentForm.LastButtonClicked = self.Key
else:
@ -520,6 +527,13 @@ class InputText(Element):
def Get(self):
return self.TKStringVar.get()
def SetFocus(self):
try:
self.TKEntry.focus_set()
except:
pass
def __del__(self):
super().__del__()
@ -535,7 +549,7 @@ Input = InputText
class InputCombo(Element):
def __init__(self, values, default_value=None, size=(None, None), auto_size_text=None, background_color=None,
text_color=None, change_submits=False, disabled=False, key=None, pad=None, tooltip=None,
readonly=False):
readonly=False, font=None):
'''
Input Combo Box Element (also called Dropdown box)
:param values:
@ -554,9 +568,9 @@ class InputCombo(Element):
fg = text_color if text_color is not None else DEFAULT_INPUT_TEXT_COLOR
super().__init__(ELEM_TYPE_INPUT_COMBO, size=size, auto_size_text=auto_size_text, background_color=bg,
text_color=fg, key=key, pad=pad, tooltip=tooltip)
text_color=fg, key=key, pad=pad, tooltip=tooltip, font=font or DEFAULT_FONT)
def Update(self, value=None, values=None, set_to_index=None, disabled=None, readonly=None):
def Update(self, value=None, values=None, set_to_index=None, disabled=None, readonly=None, font=None):
if values is not None:
try:
self.TKCombo['values'] = values
@ -587,6 +601,8 @@ class InputCombo(Element):
self.Readonly = readonly
if self.Readonly:
self.TKCombo['state'] = 'readonly'
if font is not None:
self.TKText.configure(font=font)
def __del__(self):
try:
@ -745,7 +761,7 @@ class Listbox(Element):
# ---------------------------------------------------------------------- #
class Radio(Element):
def __init__(self, text, group_id, default=False, disabled=False, size=(None, None), auto_size_text=None,
background_color=None, text_color=None, font=None, key=None, pad=None, tooltip=None):
background_color=None, text_color=None, font=None, key=None, pad=None, tooltip=None, change_submits=False):
'''
Radio Button Element
:param text:
@ -760,6 +776,7 @@ class Radio(Element):
:param key:
:param pad:
:param tooltip:
:param change_submits:
'''
self.InitialState = default
self.Text = text
@ -767,7 +784,8 @@ class Radio(Element):
self.GroupID = group_id
self.Value = None
self.Disabled = disabled
self.TextColor = text_color if text_color else DEFAULT_TEXT_COLOR
self.TextColor = text_color or DEFAULT_TEXT_COLOR
self.ChangeSubmits = change_submits
super().__init__(ELEM_TYPE_INPUT_RADIO, size=size, auto_size_text=auto_size_text, font=font,
background_color=background_color, text_color=self.TextColor, key=key, pad=pad,
@ -931,7 +949,7 @@ class Spin(Element):
class Multiline(Element):
def __init__(self, default_text='', enter_submits=False, disabled=False, autoscroll=False, size=(None, None),
auto_size_text=None, background_color=None, text_color=None, change_submits=False, do_not_clear=False, key=None, focus=False,
pad=None, tooltip=None):
font=None, pad=None, tooltip=None):
'''
Multiline Element
:param default_text:
@ -947,6 +965,7 @@ class Multiline(Element):
:param focus:
:param pad:
:param tooltip:
:param font:
'''
self.DefaultText = default_text
self.EnterSubmits = enter_submits
@ -959,10 +978,10 @@ class Multiline(Element):
self.ChangeSubmits = change_submits
super().__init__(ELEM_TYPE_INPUT_MULTILINE, size=size, auto_size_text=auto_size_text, background_color=bg,
text_color=fg, key=key, pad=pad, tooltip=tooltip)
text_color=fg, key=key, pad=pad, tooltip=tooltip, font=font or DEFAULT_FONT)
return
def Update(self, value=None, disabled=None, append=False):
def Update(self, value=None, disabled=None, append=False, font=None):
if value is not None:
try:
if not append:
@ -977,10 +996,19 @@ class Multiline(Element):
self.TKText.configure(state='disabled')
elif disabled == False:
self.TKText.configure(state='normal')
if font is not None:
self.TKText.configure(font=font)
def Get(self):
return self.TKText.get(1.0, tk.END)
def SetFocus(self):
try:
self.TKText.focus_set()
except:
pass
def __del__(self):
super().__del__()
@ -1240,6 +1268,7 @@ class Button(Element):
self.Focus = focus
self.TKCal = None
self.CalendarCloseWhenChosen = None
self.DefaultDate_M_D_Y = (None, None, None)
self.InitialFolder = initial_folder
self.Disabled = disabled
@ -1369,7 +1398,7 @@ class Button(Element):
should_submit_window = False
root = tk.Toplevel()
root.title('Calendar Chooser')
self.TKCal = TKCalendar(master=root, firstweekday=calendar.SUNDAY, target_element=target_element, close_when_chosen=self.CalendarCloseWhenChosen )
self.TKCal = TKCalendar(master=root, firstweekday=calendar.SUNDAY, target_element=target_element, close_when_chosen=self.CalendarCloseWhenChosen, default_date=self.DefaultDate_M_D_Y )
self.TKCal.pack(expand=1, fill='both')
root.update()
@ -2067,6 +2096,12 @@ class TkScrollableFrame(tk.Frame):
self.TKFrame.config(borderwidth=0, highlightthickness=0)
self.config(borderwidth=0, highlightthickness=0)
# scrollbar = tk.Scrollbar(frame)
# scrollbar.pack(side=tk.RIGHT, fill='y')
# scrollbar.config(command=treeview.yview)
# self.vscrollbar.config(command=self.TKFrame.yview)
# self.TKFrame.configure(yscrollcommand=self.vscrollbar.set)
self.bind('<Configure>', self.set_scrollregion)
self.bind_mouse_scroll(self.canvas, self.yscroll)
@ -2182,7 +2217,7 @@ class TKCalendar(tkinter.ttk.Frame):
datetime = calendar.datetime.datetime
timedelta = calendar.datetime.timedelta
def __init__(self, master=None, target_element=None, close_when_chosen=True, **kw):
def __init__(self, master=None, target_element=None, close_when_chosen=True, default_date=(None, None, None), **kw):
"""
WIDGET-SPECIFIC OPTIONS
@ -2190,15 +2225,16 @@ class TKCalendar(tkinter.ttk.Frame):
selectforeground
"""
self._TargetElement = target_element
default_mon, default_day, default_year = default_date
# remove custom options from kw before initializating ttk.Frame
fwday = kw.pop('firstweekday', calendar.MONDAY)
year = kw.pop('year', self.datetime.now().year)
month = kw.pop('month', self.datetime.now().month)
year = kw.pop('year', default_year or self.datetime.now().year)
month = kw.pop('month', default_mon or self.datetime.now().month)
locale = kw.pop('locale', None)
sel_bg = kw.pop('selectbackground', '#ecffc4')
sel_fg = kw.pop('selectforeground', '#05640e')
self._date = self.datetime(year, month, 1)
self._date = self.datetime(year, month, default_day or 1)
self._selection = None # no date selected
self._master = master
self.close_when_chosen = close_when_chosen
@ -2582,17 +2618,25 @@ class Tree(Element):
self.add_treeview_data(node)
def Update(self, values=None):
if values is None:
return
children = self.TKTreeview.get_children()
for i in children:
self.TKTreeview.detach(i)
self.TKTreeview.delete(i)
children = self.TKTreeview.get_children()
self.TreeData = values
self.add_treeview_data(self.TreeData.root_node)
self.SelectedRows = []
def Update(self, values=None, key=None, value=None, text=None):
if values is not None:
children = self.TKTreeview.get_children()
for i in children:
self.TKTreeview.detach(i)
self.TKTreeview.delete(i)
children = self.TKTreeview.get_children()
self.TreeData = values
self.add_treeview_data(self.TreeData.root_node)
self.SelectedRows = []
if key is not None:
item = self.TKTreeview.item(key)
if value is not None:
self.TKTreeview.item(key, values=value)
if text is not None:
self.TKTreeview.item(key, text=text)
item = self.TKTreeview.item(key)
return self
def __del__(self):
super().__del__()
@ -2624,11 +2668,6 @@ class TreeData(object):
parent_node = self.tree_dict[parent]
parent_node._Add(node)
# def _print_node(self, node):
# # print(f'Node: {node.text}')
# # print(f'Children = {[c.text for c in node.children]}')
# for node in node.children:
# self._print_node(node)
def __repr__(self):
return self._NodeStr(self.root_node, 1)
@ -2940,13 +2979,11 @@ class Window(object):
else:
return self.ReturnValues
def ReadNonBlocking(self, Message=''):
def ReadNonBlocking(self):
if self.TKrootDestroyed:
return None, None
if not self.Shown:
self.Show(non_blocking=True)
if Message:
print(Message)
try:
rc = self.TKroot.update()
except:
@ -3086,7 +3123,8 @@ class Window(object):
self.RootNeedsDestroying = True
return None
def CloseNonBlocking(self):
def Close(self):
if self.TKrootDestroyed:
return
try:
@ -3095,16 +3133,16 @@ class Window(object):
except:
pass
CloseNonBlockingForm = CloseNonBlocking
Close = CloseNonBlockingForm
CloseNonBlockingForm = Close
CloseNonBlocking = Close
# IT FINALLY WORKED! 29-Oct-2018 was the first time this damned thing got called
def OnClosingCallback(self):
print('Got closing callback')
# print('Got closing callback')
self.TKroot.quit() # kick the users out of the mainloop
if self.CurrentlyRunningMainloop: # quit if this is the current mainloop, otherwise don't quit!
self.TKroot.destroy() # kick the users out of the mainloop
self.TKrootDestroyed = True
return
@ -3150,6 +3188,10 @@ class Window(object):
except:
pass
def CurrentLocation(self):
return int(self.TKroot.winfo_x()), int(self.TKroot.winfo_y())
def __enter__(self):
return self
@ -3161,10 +3203,7 @@ class Window(object):
for row in self.Rows:
for element in row:
element.__del__()
# try:
# del(self.TKroot)
# except:
# pass
FlexForm = Window
@ -3370,7 +3409,7 @@ def DummyButton(button_text, image_filename=None, image_data=None, image_size=(N
# ------------------------- Calendar Chooser Button lazy function ------------------------- #
def CalendarButton(button_text, target=(None, None), close_when_date_chosen=True, image_filename=None, image_data=None, image_size=(None, None),
def CalendarButton(button_text, target=(None, None), close_when_date_chosen=True, default_date_m_d_y=(None,None,None), image_filename=None, image_data=None, image_size=(None, None),
image_subsample=None, tooltip=None, border_width=None, size=(None, None), auto_size_button=None,
button_color=None, disabled=False, font=None, bind_return_key=False, focus=False, pad=None,
key=None):
@ -3380,6 +3419,7 @@ def CalendarButton(button_text, target=(None, None), close_when_date_chosen=True
auto_size_button=auto_size_button, button_color=button_color, font=font, disabled=disabled,
bind_return_key=bind_return_key, focus=focus, pad=pad, key=key)
button.CalendarCloseWhenChosen = close_when_date_chosen
button.DefaultDate_M_D_Y = default_date_m_d_y
return button
@ -3453,6 +3493,8 @@ def BuildResultsForSubform(form, initialize_only, top_level_form):
button_pressed_text = top_level_form.LastButtonClicked
for row_num, row in enumerate(form.Rows):
for col_num, element in enumerate(row):
if element.Key is not None and WRITE_ONLY_KEY in str(element.Key):
continue
value = None
if element.Type == ELEM_TYPE_COLUMN:
element.DictionaryKeyCounter = top_level_form.DictionaryKeyCounter
@ -4199,8 +4241,13 @@ def PackFormIntoFrame(form, containing_frame, toplevel_form):
element.TKIntVar = RadVar # store the RadVar in Radio object
if default_value: # if this radio is the one selected, set RadVar to match
element.TKIntVar.set(value)
element.TKRadio = tk.Radiobutton(tk_row_frame, anchor=tk.NW, text=element.Text, width=width,
variable=element.TKIntVar, value=value, bd=border_depth, font=font)
if element.ChangeSubmits:
element.TKRadio = tk.Radiobutton(tk_row_frame, anchor=tk.NW, text=element.Text, width=width,
variable=element.TKIntVar, value=value, bd=border_depth, font=font,
command=element.RadioHandler)
else:
element.TKRadio = tk.Radiobutton(tk_row_frame, anchor=tk.NW, text=element.Text, width=width,
variable=element.TKIntVar, value=value, bd=border_depth, font=font)
if not element.BackgroundColor in (None, COLOR_SYSTEM_DEFAULT):
element.TKRadio.configure(background=element.BackgroundColor)
element.TKRadio.configure(selectcolor=element.BackgroundColor)
@ -4643,7 +4690,16 @@ def StartupTK(my_flex_form):
# print('Starting TK open Windows = {}'.format(ow))
if not ow and not my_flex_form.ForceTopLevel:
root = tk.Tk()
# if first window being created, make a throwaway, hidden master root. This stops one user
# window from becoming the child of another user window. All windows are children of this
# hidden window
_my_windows.Increment()
_my_windows.hidden_master_root = tk.Tk()
_my_windows.hidden_master_root.attributes('-alpha', 0) # hide window while building it. makes for smoother 'paint'
_my_windows.hidden_master_root.wm_overrideredirect(True)
# root = tk.Tk() # users windows are no longer using tk.Tk. They are all Toplevel windows
root = tk.Toplevel()
else:
root = tk.Toplevel()
@ -5061,16 +5117,20 @@ _easy_print_data = None # global variable... I'm cheating
class DebugWin(object):
def __init__(self, size=(None, None)):
def __init__(self, size=(None, None), location=(None, None), font=None, no_titlebar=False, no_button=False, grab_anywhere=False, keep_on_top=False):
# Show a form that's a running counter
win_size = size if size != (None, None) else DEFAULT_DEBUG_WINDOW_SIZE
self.form = Window('Debug Window', auto_size_text=True, font=('Courier New', 12))
self.window = Window('Debug Window', no_titlebar=no_titlebar, auto_size_text=True, location=location, font=font or ('Courier New', 10), grab_anywhere=grab_anywhere, keep_on_top=keep_on_top)
self.output_element = Output(size=win_size)
self.form_rows = [[Text('EasyPrint Output')],
[self.output_element],
[DummyButton('Quit')]]
self.form.AddRows(self.form_rows)
self.form.Show(non_blocking=True) # Show a ;non-blocking form, returns immediately
if no_button:
self.layout = [[self.output_element]]
else:
self.layout = [
[self.output_element],
[DummyButton('Quit')]
]
self.window.AddRows(self.layout)
self.window.Read(timeout=0) # Show a non-blocking form, returns immediately
return
def Print(self, *args, **_3to2kwargs):
@ -5080,45 +5140,43 @@ class DebugWin(object):
else: end = None
sepchar = sep if sep is not None else ' '
endchar = end if end is not None else '\n'
if self.window is None: # if window was destroyed already, just print
print(*args, sep=sepchar, end=endchar)
return
event, values = self.window.Read(timeout=0)
if event == 'Quit' or event is None:
self.Close()
print(*args, sep=sepchar, end=endchar)
# for a in args:
# msg = str(a)
# print(msg, end="", sep=sepchar)
# print(1, 2, 3, sep='-')
# if end is None:
# print("")
self.form.ReadNonBlocking()
# Add extra check to see if the window was closed... if closed by X sometimes am not told
try:
state = self.window.TKroot.state()
except:
self.Close()
def Close(self):
self.form.CloseNonBlockingForm()
self.form.__del__()
def Print(*args, **_3to2kwargs):
if 'sep' in _3to2kwargs: sep = _3to2kwargs['sep']; del _3to2kwargs['sep']
else: sep = None
if 'end' in _3to2kwargs: end = _3to2kwargs['end']; del _3to2kwargs['end']
else: end = None
if 'size' in _3to2kwargs: size = _3to2kwargs['size']; del _3to2kwargs['size']
else: size = (None, None)
EasyPrint(*args, size=size, end=end, sep=sep)
self.window.Close()
self.window.__del__()
self.window = None
def PrintClose():
EasyPrintClose()
def eprint(*args, **_3to2kwargs):
if 'sep' in _3to2kwargs: sep = _3to2kwargs['sep']; del _3to2kwargs['sep']
else: sep = None
if 'end' in _3to2kwargs: end = _3to2kwargs['end']; del _3to2kwargs['end']
else: end = None
if 'size' in _3to2kwargs: size = _3to2kwargs['size']; del _3to2kwargs['size']
else: size = (None, None)
EasyPrint(*args, size=size, end=end, sep=sep)
def EasyPrint(*args, **_3to2kwargs):
if 'keep_on_top' in _3to2kwargs: keep_on_top = _3to2kwargs['keep_on_top']; del _3to2kwargs['keep_on_top']
else: keep_on_top = False
if 'grab_anywhere' in _3to2kwargs: grab_anywhere = _3to2kwargs['grab_anywhere']; del _3to2kwargs['grab_anywhere']
else: grab_anywhere = False
if 'no_button' in _3to2kwargs: no_button = _3to2kwargs['no_button']; del _3to2kwargs['no_button']
else: no_button = False
if 'no_titlebar' in _3to2kwargs: no_titlebar = _3to2kwargs['no_titlebar']; del _3to2kwargs['no_titlebar']
else: no_titlebar = False
if 'font' in _3to2kwargs: font = _3to2kwargs['font']; del _3to2kwargs['font']
else: font = None
if 'location' in _3to2kwargs: location = _3to2kwargs['location']; del _3to2kwargs['location']
else: location = (None, None)
if 'sep' in _3to2kwargs: sep = _3to2kwargs['sep']; del _3to2kwargs['sep']
else: sep = None
if 'end' in _3to2kwargs: end = _3to2kwargs['end']; del _3to2kwargs['end']
@ -5128,30 +5186,18 @@ def EasyPrint(*args, **_3to2kwargs):
global _easy_print_data
if _easy_print_data is None:
_easy_print_data = DebugWin(size=size)
_easy_print_data = DebugWin(size=size, location=location, font=font, no_titlebar=no_titlebar, no_button=no_button, grab_anywhere=grab_anywhere, keep_on_top=keep_on_top)
_easy_print_data.Print(*args, end=end, sep=sep)
def EasyPrintold(*args, **_3to2kwargs):
if 'sep' in _3to2kwargs: sep = _3to2kwargs['sep']; del _3to2kwargs['sep']
else: sep = None
if 'end' in _3to2kwargs: end = _3to2kwargs['end']; del _3to2kwargs['end']
else: end = None
if 'size' in _3to2kwargs: size = _3to2kwargs['size']; del _3to2kwargs['size']
else: size = (None, None)
if 'easy_print_data' not in EasyPrint.__dict__: # use a function property to save DebugWin object (static variable)
EasyPrint.easy_print_data = DebugWin(size=size)
if EasyPrint.easy_print_data is None:
EasyPrint.easy_print_data = DebugWin(size=size)
EasyPrint.easy_print_data.Print(*args, end=end, sep=sep)
Print = EasyPrint
eprint = EasyPrint
def EasyPrintClose():
if 'easy_print_data' in EasyPrint.__dict__:
if EasyPrint.easy_print_data is not None:
EasyPrint.easy_print_data._Close()
EasyPrint.easy_print_data = None
# del EasyPrint.easy_print_data
global _easy_print_data
if _easy_print_data is not None:
_easy_print_data.Close()
_easy_print_data = None
# ======================== Scrolled Text Box =====#
@ -5825,7 +5871,7 @@ def Popup(*args, **_3to2kwargs):
pad=((20, 0), 3)))
if non_blocking:
button, values = window.ReadNonBlocking()
button, values = window.Read(timeout=0)
else:
button, values = window.Read()
@ -5972,7 +6018,7 @@ def PopupQuick(*args, **_3to2kwargs):
if 'non_blocking' in _3to2kwargs: non_blocking = _3to2kwargs['non_blocking']; del _3to2kwargs['non_blocking']
else: non_blocking = True
if 'auto_close_duration' in _3to2kwargs: auto_close_duration = _3to2kwargs['auto_close_duration']; del _3to2kwargs['auto_close_duration']
else: auto_close_duration = 1
else: auto_close_duration = 2
if 'auto_close' in _3to2kwargs: auto_close = _3to2kwargs['auto_close']; del _3to2kwargs['auto_close']
else: auto_close = True
if 'text_color' in _3to2kwargs: text_color = _3to2kwargs['text_color']; del _3to2kwargs['text_color']
@ -6009,6 +6055,62 @@ def PopupQuick(*args, **_3to2kwargs):
font=font, no_titlebar=no_titlebar, grab_anywhere=grab_anywhere, keep_on_top=keep_on_top, location=location)
# --------------------------- PopupQuick - a NonBlocking, Self-closing Popup with no titlebar and no buttons ---------------------------
def PopupQuickMessage(*args, **_3to2kwargs):
if 'location' in _3to2kwargs: location = _3to2kwargs['location']; del _3to2kwargs['location']
else: location = (None, None)
if 'keep_on_top' in _3to2kwargs: keep_on_top = _3to2kwargs['keep_on_top']; del _3to2kwargs['keep_on_top']
else: keep_on_top = False
if 'grab_anywhere' in _3to2kwargs: grab_anywhere = _3to2kwargs['grab_anywhere']; del _3to2kwargs['grab_anywhere']
else: grab_anywhere = False
if 'no_titlebar' in _3to2kwargs: no_titlebar = _3to2kwargs['no_titlebar']; del _3to2kwargs['no_titlebar']
else: no_titlebar = True
if 'font' in _3to2kwargs: font = _3to2kwargs['font']; del _3to2kwargs['font']
else: font = None
if 'line_width' in _3to2kwargs: line_width = _3to2kwargs['line_width']; del _3to2kwargs['line_width']
else: line_width = None
if 'icon' in _3to2kwargs: icon = _3to2kwargs['icon']; del _3to2kwargs['icon']
else: icon = DEFAULT_WINDOW_ICON
if 'non_blocking' in _3to2kwargs: non_blocking = _3to2kwargs['non_blocking']; del _3to2kwargs['non_blocking']
else: non_blocking = True
if 'auto_close_duration' in _3to2kwargs: auto_close_duration = _3to2kwargs['auto_close_duration']; del _3to2kwargs['auto_close_duration']
else: auto_close_duration = 2
if 'auto_close' in _3to2kwargs: auto_close = _3to2kwargs['auto_close']; del _3to2kwargs['auto_close']
else: auto_close = True
if 'text_color' in _3to2kwargs: text_color = _3to2kwargs['text_color']; del _3to2kwargs['text_color']
else: text_color = None
if 'background_color' in _3to2kwargs: background_color = _3to2kwargs['background_color']; del _3to2kwargs['background_color']
else: background_color = None
if 'button_color' in _3to2kwargs: button_color = _3to2kwargs['button_color']; del _3to2kwargs['button_color']
else: button_color = None
if 'button_type' in _3to2kwargs: button_type = _3to2kwargs['button_type']; del _3to2kwargs['button_type']
else: button_type = POPUP_BUTTONS_NO_BUTTONS
"""
Show Popup box that doesn't block and closes itself
:param args:
:param button_type:
:param button_color:
:param background_color:
:param text_color:
:param auto_close:
:param auto_close_duration:
:param non_blocking:
:param icon:
:param line_width:
:param font:
:param no_titlebar:
:param grab_anywhere:
:param keep_on_top:
:param location:
:return:
"""
Popup(*args, button_color=button_color, background_color=background_color, text_color=text_color,
button_type=button_type,
auto_close=auto_close, auto_close_duration=auto_close_duration, non_blocking=non_blocking, icon=icon,
line_width=line_width,
font=font, no_titlebar=no_titlebar, grab_anywhere=grab_anywhere, keep_on_top=keep_on_top, location=location)
# --------------------------- PopupNoTitlebar ---------------------------
def PopupNoTitlebar(*args, **_3to2kwargs):
if 'location' in _3to2kwargs: location = _3to2kwargs['location']; del _3to2kwargs['location']
@ -6395,7 +6497,7 @@ def PopupYesNo(*args, **_3to2kwargs):
def PopupGetFolder(message, default_path='', no_window=False, size=(None, None), button_color=None,
background_color=None, text_color=None, icon=DEFAULT_WINDOW_ICON, font=None, no_titlebar=False,
grab_anywhere=False, keep_on_top=False, location=(None, None)):
grab_anywhere=False, keep_on_top=False, location=(None, None), initial_folder=None):
"""
Display popup with text entry field and browse button. Browse for folder
:param message:
@ -6413,8 +6515,14 @@ def PopupGetFolder(message, default_path='', no_window=False, size=(None, None),
:param location:
:return: Contents of text field. None if closed using X or cancelled
"""
global _my_windows
if no_window:
root = tk.Tk()
if _my_windows.NumOpenWindows:
root = tk.Toplevel()
else:
root = tk.Tk()
try:
root.attributes('-alpha', 0) # hide window while building it. makes for smoother 'paint'
except:
@ -6424,7 +6532,7 @@ def PopupGetFolder(message, default_path='', no_window=False, size=(None, None),
return folder_name
layout = [[Text(message, auto_size_text=True, text_color=text_color, background_color=background_color)],
[InputText(default_text=default_path, size=size), FolderBrowse()],
[InputText(default_text=default_path, size=size), FolderBrowse(initial_folder=initial_folder)],
[CloseButton('Ok', size=(5, 1), bind_return_key=True), CloseButton('Cancel', size=(5, 1))]]
window = Window(title=message, icon=icon, auto_size_text=True, button_color=button_color,
@ -6446,7 +6554,7 @@ def PopupGetFolder(message, default_path='', no_window=False, size=(None, None),
def PopupGetFile(message, default_path='', default_extension='', save_as=False, file_types=(("ALL Files", "*.*"),),
no_window=False, size=(None, None), button_color=None, background_color=None, text_color=None,
icon=DEFAULT_WINDOW_ICON, font=None, no_titlebar=False, grab_anywhere=False, keep_on_top=False,
location=(None, None)):
location=(None, None), initial_folder=None):
"""
Display popup with text entry field and browse button. Browse for file
:param message:
@ -6467,8 +6575,14 @@ def PopupGetFile(message, default_path='', default_extension='', save_as=False,
:param location:
:return: string representing the path chosen, None if cancelled or window closed with X
"""
global _my_windows
if no_window:
root = tk.Tk()
if _my_windows.NumOpenWindows:
root = tk.Toplevel()
else:
root = tk.Tk()
try:
root.attributes('-alpha', 0) # hide window while building it. makes for smoother 'paint'
except:
@ -6482,7 +6596,7 @@ def PopupGetFile(message, default_path='', default_extension='', save_as=False,
root.destroy()
return filename
browse_button = SaveAs(file_types=file_types) if save_as else FileBrowse(file_types=file_types)
browse_button = SaveAs(file_types=file_types, initial_folder=initial_folder) if save_as else FileBrowse(file_types=file_types, initial_folder=initial_folder)
layout = [[Text(message, auto_size_text=True, text_color=text_color, background_color=background_color)],
[InputText(default_text=default_path, size=size), browse_button],

View File

@ -24,9 +24,9 @@
## Now supports both Python 2.7 & 3
![Python Version](https://img.shields.io/badge/PySimpleGUI_For_Python_3.x_Version-3.13.0-red.svg?longCache=true&style=for-the-badge)
![Python Version](https://img.shields.io/badge/PySimpleGUI_For_Python_3.x_Version-3.14.0-red.svg?longCache=true&style=for-the-badge)
![Python Version](https://img.shields.io/badge/PySimpleGUI_For_Python_2.7_Version-1.13.0-blue.svg?longCache=true&style=for-the-badge)
![Python Version](https://img.shields.io/badge/PySimpleGUI_For_Python_2.7_Version-1.14.0-blue.svg?longCache=true&style=for-the-badge)
[Announcements of Latest Developments](https://github.com/MikeTheWatchGuy/PySimpleGUI/issues/142)
@ -3569,6 +3569,8 @@ A MikeTheWatchGuy production... entirely responsible for this code.... unless it
| 3.11.0 & 1.11.0 | Oct 28, 2018
| 3.12.0 & 1.12.0 | Oct 28, 2018
| 3.13.0 & 1.13.0 | Oct 29, 2018
| 3.14.0 & 1.14.0 | Nov 2, 2018
## Release Notes
2.3 - Sliders, Listbox's and Image elements (oh my!)
@ -3797,7 +3799,7 @@ Emergency patch release... going out same day as previous release
* Progress meter uses new CloseButton
* Popups use new CloseButton
## 3.13.0 & 1.13.0
### 3.13.0 & 1.13.0
* Improved multiple window handling of Popups when the X is used to close
* Change submits added for:
* Multiline
@ -3808,7 +3810,40 @@ Emergency patch release... going out same day as previous release
* Update for Tree Element
* Scroll bars for Trees
### 3.14.0 & 1.14.0
- More windowing changes...
using a hidden root windowing (Tk())
all children are Toplevel() windows
Read only setting for:
Input Text
Multiline
Font setting for InputCombo, Multiline
change_submits settinf for Radio Element
SetFocus for multiline, input elements
Default mon, day, year for calendar chooser button
Tree element update, added ability to change a single key
Message parm removed from ReadNonBlocking
Fix for closing windows using X
CurrentLocation method for Windows
Debug Window options
location
font
no_button
no_titlebar
grab_anywhere
keep_on_top
New Print / EasyPrint options
location
font
no_button
no_titlebar
grab_anywhere
keep_on_top
New popup, PopupQuickMessage
PopupGetFolder, PopupGetFile new initial_folder parm
### Upcoming
Make suggestions people! Future release features
@ -3885,6 +3920,8 @@ GNU Lesser General Public License (LGPL 3) +
* Tony Crewe (anthony.crewe@gmail.com) Generously provided his classroom materials that he has written to teach a GUI course. If you're an educator and want to trade materials with Tony, he would like to hear from you.
* [spectre6000](https://github.com/spectre6000) - Readme updates
* [jackyOO7](https://github.com/jackyOO7) - Demo programs. OpenCV with realtime image processing, popup keyboard, input Combo read only option.
* [AltoRetrato](https://github.com/AltoRetrato) - Fonts for multiline and combo
## How Do I
Finally, I must thank the fine folks at How Do I.

View File

@ -24,9 +24,9 @@
## Now supports both Python 2.7 & 3
![Python Version](https://img.shields.io/badge/PySimpleGUI_For_Python_3.x_Version-3.13.0-red.svg?longCache=true&style=for-the-badge)
![Python Version](https://img.shields.io/badge/PySimpleGUI_For_Python_3.x_Version-3.14.0-red.svg?longCache=true&style=for-the-badge)
![Python Version](https://img.shields.io/badge/PySimpleGUI_For_Python_2.7_Version-1.13.0-blue.svg?longCache=true&style=for-the-badge)
![Python Version](https://img.shields.io/badge/PySimpleGUI_For_Python_2.7_Version-1.14.0-blue.svg?longCache=true&style=for-the-badge)
[Announcements of Latest Developments](https://github.com/MikeTheWatchGuy/PySimpleGUI/issues/142)
@ -3569,6 +3569,8 @@ A MikeTheWatchGuy production... entirely responsible for this code.... unless it
| 3.11.0 & 1.11.0 | Oct 28, 2018
| 3.12.0 & 1.12.0 | Oct 28, 2018
| 3.13.0 & 1.13.0 | Oct 29, 2018
| 3.14.0 & 1.14.0 | Nov 2, 2018
## Release Notes
2.3 - Sliders, Listbox's and Image elements (oh my!)
@ -3797,7 +3799,7 @@ Emergency patch release... going out same day as previous release
* Progress meter uses new CloseButton
* Popups use new CloseButton
## 3.13.0 & 1.13.0
### 3.13.0 & 1.13.0
* Improved multiple window handling of Popups when the X is used to close
* Change submits added for:
* Multiline
@ -3808,7 +3810,40 @@ Emergency patch release... going out same day as previous release
* Update for Tree Element
* Scroll bars for Trees
### 3.14.0 & 1.14.0
- More windowing changes...
using a hidden root windowing (Tk())
all children are Toplevel() windows
Read only setting for:
Input Text
Multiline
Font setting for InputCombo, Multiline
change_submits settinf for Radio Element
SetFocus for multiline, input elements
Default mon, day, year for calendar chooser button
Tree element update, added ability to change a single key
Message parm removed from ReadNonBlocking
Fix for closing windows using X
CurrentLocation method for Windows
Debug Window options
location
font
no_button
no_titlebar
grab_anywhere
keep_on_top
New Print / EasyPrint options
location
font
no_button
no_titlebar
grab_anywhere
keep_on_top
New popup, PopupQuickMessage
PopupGetFolder, PopupGetFile new initial_folder parm
### Upcoming
Make suggestions people! Future release features
@ -3885,6 +3920,8 @@ GNU Lesser General Public License (LGPL 3) +
* Tony Crewe (anthony.crewe@gmail.com) Generously provided his classroom materials that he has written to teach a GUI course. If you're an educator and want to trade materials with Tony, he would like to hear from you.
* [spectre6000](https://github.com/spectre6000) - Readme updates
* [jackyOO7](https://github.com/jackyOO7) - Demo programs. OpenCV with realtime image processing, popup keyboard, input Combo read only option.
* [AltoRetrato](https://github.com/AltoRetrato) - Fonts for multiline and combo
## How Do I
Finally, I must thank the fine folks at How Do I.