commit
b6d0eda2e3
|
@ -190,6 +190,7 @@ class MyWindows():
|
||||||
self.NumOpenWindows = 0
|
self.NumOpenWindows = 0
|
||||||
self.user_defined_icon = None
|
self.user_defined_icon = None
|
||||||
self.hidden_master_root = None
|
self.hidden_master_root = None
|
||||||
|
self.window_being_closed = None
|
||||||
|
|
||||||
def Decrement(self):
|
def Decrement(self):
|
||||||
self.NumOpenWindows -= 1 * (self.NumOpenWindows != 0) # decrement if not 0
|
self.NumOpenWindows -= 1 * (self.NumOpenWindows != 0) # decrement if not 0
|
||||||
|
@ -3049,6 +3050,7 @@ class Window:
|
||||||
# print('** tkafter cancel failed **')
|
# print('** tkafter cancel failed **')
|
||||||
self.TimerCancelled = True
|
self.TimerCancelled = True
|
||||||
if self.RootNeedsDestroying:
|
if self.RootNeedsDestroying:
|
||||||
|
print('*** DESTROYING LATE ***')
|
||||||
self.TKroot.destroy()
|
self.TKroot.destroy()
|
||||||
_my_windows.Decrement()
|
_my_windows.Decrement()
|
||||||
# if form was closed with X
|
# if form was closed with X
|
||||||
|
@ -3065,6 +3067,11 @@ class Window:
|
||||||
|
|
||||||
def ReadNonBlocking(self):
|
def ReadNonBlocking(self):
|
||||||
if self.TKrootDestroyed:
|
if self.TKrootDestroyed:
|
||||||
|
try:
|
||||||
|
self.TKroot.quit()
|
||||||
|
self.TKroot.destroy()
|
||||||
|
except:
|
||||||
|
print('DESTROY FAILED')
|
||||||
return None, None
|
return None, None
|
||||||
if not self.Shown:
|
if not self.Shown:
|
||||||
self.Show(non_blocking=True)
|
self.Show(non_blocking=True)
|
||||||
|
@ -3073,8 +3080,12 @@ class Window:
|
||||||
except:
|
except:
|
||||||
self.TKrootDestroyed = True
|
self.TKrootDestroyed = True
|
||||||
_my_windows.Decrement()
|
_my_windows.Decrement()
|
||||||
# print("read failed")
|
print("read failed")
|
||||||
# return None, None
|
# return None, None
|
||||||
|
if self.RootNeedsDestroying:
|
||||||
|
print('*** DESTROYING LATE ***')
|
||||||
|
self.TKroot.destroy()
|
||||||
|
_my_windows.Decrement()
|
||||||
return BuildResults(self, False, self)
|
return BuildResults(self, False, self)
|
||||||
|
|
||||||
def Finalize(self):
|
def Finalize(self):
|
||||||
|
@ -3222,12 +3233,15 @@ class Window:
|
||||||
|
|
||||||
# IT FINALLY WORKED! 29-Oct-2018 was the first time this damned thing got called
|
# IT FINALLY WORKED! 29-Oct-2018 was the first time this damned thing got called
|
||||||
def OnClosingCallback(self):
|
def OnClosingCallback(self):
|
||||||
|
global _my_windows
|
||||||
if self.DisableClose:
|
if self.DisableClose:
|
||||||
return
|
return
|
||||||
|
_my_windows.window_being_closed = 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!
|
if self.CurrentlyRunningMainloop: # quit if this is the current mainloop, otherwise don't quit!
|
||||||
|
self.TKroot.quit() # kick the users out of the mainloop
|
||||||
self.TKroot.destroy() # kick the users out of the mainloop
|
self.TKroot.destroy() # kick the users out of the mainloop
|
||||||
|
self.RootNeedsDestroying = True
|
||||||
else:
|
else:
|
||||||
self.RootNeedsDestroying = True
|
self.RootNeedsDestroying = True
|
||||||
self.TKrootDestroyed = True
|
self.TKrootDestroyed = True
|
||||||
|
|
208
PySimpleGUI27.py
208
PySimpleGUI27.py
|
@ -981,7 +981,7 @@ class Multiline(Element):
|
||||||
text_color=fg, key=key, pad=pad, tooltip=tooltip, font=font or DEFAULT_FONT)
|
text_color=fg, key=key, pad=pad, tooltip=tooltip, font=font or DEFAULT_FONT)
|
||||||
return
|
return
|
||||||
|
|
||||||
def Update(self, value=None, disabled=None, append=False, font=None):
|
def Update(self, value=None, disabled=None, append=False, font=None, text_color=None, background_color=None):
|
||||||
if value is not None:
|
if value is not None:
|
||||||
try:
|
try:
|
||||||
if not append:
|
if not append:
|
||||||
|
@ -996,6 +996,10 @@ class Multiline(Element):
|
||||||
self.TKText.configure(state='disabled')
|
self.TKText.configure(state='disabled')
|
||||||
elif disabled == False:
|
elif disabled == False:
|
||||||
self.TKText.configure(state='normal')
|
self.TKText.configure(state='normal')
|
||||||
|
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:
|
if font is not None:
|
||||||
self.TKText.configure(font=font)
|
self.TKText.configure(font=font)
|
||||||
|
|
||||||
|
@ -1421,13 +1425,6 @@ class Button(Element):
|
||||||
self.TKButton['state'] = 'disabled'
|
self.TKButton['state'] = 'disabled'
|
||||||
elif disabled == False:
|
elif disabled == False:
|
||||||
self.TKButton['state'] = 'normal'
|
self.TKButton['state'] = 'normal'
|
||||||
# if image_data is not None:
|
|
||||||
# if type(image_data) is bytes:
|
|
||||||
# image = tk.PhotoImage(data=image_data)
|
|
||||||
# else:
|
|
||||||
# image = image_data
|
|
||||||
# width, height = image.width, image.height
|
|
||||||
# self.TKButton.config(image=image, width=width, height=height)
|
|
||||||
if image_data is not None:
|
if image_data is not None:
|
||||||
image = tk.PhotoImage(data=image_data)
|
image = tk.PhotoImage(data=image_data)
|
||||||
width, height = image.width(), image.height()
|
width, height = image.width(), image.height()
|
||||||
|
@ -1585,7 +1582,7 @@ class Canvas(Element):
|
||||||
# Graph #
|
# Graph #
|
||||||
# ---------------------------------------------------------------------- #
|
# ---------------------------------------------------------------------- #
|
||||||
class Graph(Element):
|
class Graph(Element):
|
||||||
def __init__(self, canvas_size, graph_bottom_left, graph_top_right, background_color=None, pad=None, key=None,
|
def __init__(self, canvas_size, graph_bottom_left, graph_top_right, background_color=None, pad=None, change_submits=False, drag_submits=False, key=None,
|
||||||
tooltip=None):
|
tooltip=None):
|
||||||
'''
|
'''
|
||||||
Graph Element
|
Graph Element
|
||||||
|
@ -1602,19 +1599,38 @@ class Graph(Element):
|
||||||
self.TopRight = graph_top_right
|
self.TopRight = graph_top_right
|
||||||
self._TKCanvas = None
|
self._TKCanvas = None
|
||||||
self._TKCanvas2 = None
|
self._TKCanvas2 = None
|
||||||
|
self.ChangeSubmits = change_submits
|
||||||
|
self.DragSubmits = drag_submits
|
||||||
|
self.ClickPosition = (None, None)
|
||||||
|
self.MouseButtonDown = False
|
||||||
super().__init__(ELEM_TYPE_GRAPH, background_color=background_color, size=canvas_size, pad=pad, key=key,
|
super().__init__(ELEM_TYPE_GRAPH, background_color=background_color, size=canvas_size, pad=pad, key=key,
|
||||||
tooltip=tooltip)
|
tooltip=tooltip)
|
||||||
return
|
return
|
||||||
|
|
||||||
def _convert_xy_to_canvas_xy(self, x_in, y_in):
|
def _convert_xy_to_canvas_xy(self, x_in, y_in):
|
||||||
|
if None in (x_in,y_in):
|
||||||
|
return None, None
|
||||||
scale_x = (self.CanvasSize[0] - 0) / (self.TopRight[0] - self.BottomLeft[0])
|
scale_x = (self.CanvasSize[0] - 0) / (self.TopRight[0] - self.BottomLeft[0])
|
||||||
scale_y = (0 - self.CanvasSize[1]) / (self.TopRight[1] - self.BottomLeft[1])
|
scale_y = (0 - self.CanvasSize[1]) / (self.TopRight[1] - self.BottomLeft[1])
|
||||||
new_x = 0 + scale_x * (x_in - self.BottomLeft[0])
|
new_x = 0 + scale_x * (x_in - self.BottomLeft[0])
|
||||||
new_y = self.CanvasSize[1] + scale_y * (y_in - self.BottomLeft[1])
|
new_y = self.CanvasSize[1] + scale_y * (y_in - self.BottomLeft[1])
|
||||||
return new_x, new_y
|
return new_x, new_y
|
||||||
|
|
||||||
|
|
||||||
|
def _convert_canvas_xy_to_xy(self, x_in, y_in):
|
||||||
|
if None in (x_in,y_in):
|
||||||
|
return None, None
|
||||||
|
scale_x = (self.CanvasSize[0] - 0) / (self.TopRight[0] - self.BottomLeft[0])
|
||||||
|
scale_y = (0 - self.CanvasSize[1]) / (self.TopRight[1] - self.BottomLeft[1])
|
||||||
|
|
||||||
|
new_x = x_in/scale_x+self.BottomLeft[0]
|
||||||
|
new_y = (y_in - self.CanvasSize[1]) / scale_y + self.BottomLeft[1]
|
||||||
|
return int(new_x), int(new_y)
|
||||||
|
|
||||||
|
|
||||||
def DrawLine(self, point_from, point_to, color='black', width=1):
|
def DrawLine(self, point_from, point_to, color='black', width=1):
|
||||||
|
if point_from == (None, None):
|
||||||
|
return
|
||||||
converted_point_from = self._convert_xy_to_canvas_xy(point_from[0], point_from[1])
|
converted_point_from = self._convert_xy_to_canvas_xy(point_from[0], point_from[1])
|
||||||
converted_point_to = self._convert_xy_to_canvas_xy(point_to[0], point_to[1])
|
converted_point_to = self._convert_xy_to_canvas_xy(point_to[0], point_to[1])
|
||||||
if self._TKCanvas2 is None:
|
if self._TKCanvas2 is None:
|
||||||
|
@ -1624,6 +1640,8 @@ class Graph(Element):
|
||||||
return self._TKCanvas2.create_line(converted_point_from, converted_point_to, width=width, fill=color)
|
return self._TKCanvas2.create_line(converted_point_from, converted_point_to, width=width, fill=color)
|
||||||
|
|
||||||
def DrawPoint(self, point, size=2, color='black'):
|
def DrawPoint(self, point, size=2, color='black'):
|
||||||
|
if point == (None, None):
|
||||||
|
return
|
||||||
converted_point = self._convert_xy_to_canvas_xy(point[0], point[1])
|
converted_point = self._convert_xy_to_canvas_xy(point[0], point[1])
|
||||||
if self._TKCanvas2 is None:
|
if self._TKCanvas2 is None:
|
||||||
print('*** WARNING - The Graph element has not been finalized and cannot be drawn upon ***')
|
print('*** WARNING - The Graph element has not been finalized and cannot be drawn upon ***')
|
||||||
|
@ -1634,6 +1652,8 @@ class Graph(Element):
|
||||||
outline=color)
|
outline=color)
|
||||||
|
|
||||||
def DrawCircle(self, center_location, radius, fill_color=None, line_color='black'):
|
def DrawCircle(self, center_location, radius, fill_color=None, line_color='black'):
|
||||||
|
if center_location == (None, None):
|
||||||
|
return
|
||||||
converted_point = self._convert_xy_to_canvas_xy(center_location[0], center_location[1])
|
converted_point = self._convert_xy_to_canvas_xy(center_location[0], center_location[1])
|
||||||
if self._TKCanvas2 is None:
|
if self._TKCanvas2 is None:
|
||||||
print('*** WARNING - The Graph element has not been finalized and cannot be drawn upon ***')
|
print('*** WARNING - The Graph element has not been finalized and cannot be drawn upon ***')
|
||||||
|
@ -1676,6 +1696,8 @@ class Graph(Element):
|
||||||
converted_bottom_right[1], fill=fill_color, outline=line_color)
|
converted_bottom_right[1], fill=fill_color, outline=line_color)
|
||||||
|
|
||||||
def DrawText(self, text, location, color='black', font=None, angle=0):
|
def DrawText(self, text, location, color='black', font=None, angle=0):
|
||||||
|
if location == (None, None):
|
||||||
|
return
|
||||||
converted_point = self._convert_xy_to_canvas_xy(location[0], location[1])
|
converted_point = self._convert_xy_to_canvas_xy(location[0], location[1])
|
||||||
if self._TKCanvas2 is None:
|
if self._TKCanvas2 is None:
|
||||||
print('*** WARNING - The Graph element has not been finalized and cannot be drawn upon ***')
|
print('*** WARNING - The Graph element has not been finalized and cannot be drawn upon ***')
|
||||||
|
@ -1726,6 +1748,50 @@ class Graph(Element):
|
||||||
print('*** form = sg.Window("My Form").Layout(layout).Finalize() ***')
|
print('*** form = sg.Window("My Form").Layout(layout).Finalize() ***')
|
||||||
return self._TKCanvas2
|
return self._TKCanvas2
|
||||||
|
|
||||||
|
# Realtime button release callback
|
||||||
|
def ButtonReleaseCallBack(self, event):
|
||||||
|
self.ClickPosition = (None, None)
|
||||||
|
self.LastButtonClickedWasRealtime = not self.DragSubmits
|
||||||
|
if self.Key is not None:
|
||||||
|
self.ParentForm.LastButtonClicked = self.Key
|
||||||
|
else:
|
||||||
|
self.ParentForm.LastButtonClicked = '__GRAPH__' # need to put something rather than None
|
||||||
|
if self.ParentForm.CurrentlyRunningMainloop:
|
||||||
|
self.ParentForm.TKroot.quit()
|
||||||
|
if self.DragSubmits:
|
||||||
|
self.ParentForm.LastButtonClicked = None
|
||||||
|
self.MouseButtonDown = False
|
||||||
|
|
||||||
|
|
||||||
|
# Realtime button callback
|
||||||
|
def ButtonPressCallBack(self, event):
|
||||||
|
self.ClickPosition = self._convert_canvas_xy_to_xy(event.x, event.y)
|
||||||
|
self.ParentForm.LastButtonClickedWasRealtime = self.DragSubmits
|
||||||
|
if self.Key is not None:
|
||||||
|
self.ParentForm.LastButtonClicked = self.Key
|
||||||
|
else:
|
||||||
|
self.ParentForm.LastButtonClicked = '__GRAPH__' # need to put something rather than None
|
||||||
|
if self.ParentForm.CurrentlyRunningMainloop:
|
||||||
|
self.ParentForm.TKroot.quit() # kick out of loop if read was called
|
||||||
|
self.MouseButtonDown = True
|
||||||
|
|
||||||
|
|
||||||
|
# Realtime button callback
|
||||||
|
def MotionCallBack(self, event):
|
||||||
|
if not self.MouseButtonDown:
|
||||||
|
return
|
||||||
|
self.ClickPosition = self._convert_canvas_xy_to_xy(event.x, event.y)
|
||||||
|
self.ParentForm.LastButtonClickedWasRealtime = self.DragSubmits
|
||||||
|
if self.Key is not None:
|
||||||
|
self.ParentForm.LastButtonClicked = self.Key
|
||||||
|
else:
|
||||||
|
self.ParentForm.LastButtonClicked = '__GRAPH__' # need to put something rather than None
|
||||||
|
if self.ParentForm.CurrentlyRunningMainloop:
|
||||||
|
self.ParentForm.TKroot.quit() # kick out of loop if read was called
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
def __del__(self):
|
def __del__(self):
|
||||||
super().__del__()
|
super().__del__()
|
||||||
|
|
||||||
|
@ -2066,20 +2132,24 @@ class Slider(Element):
|
||||||
# TkScrollableFrame (Used by Column) #
|
# TkScrollableFrame (Used by Column) #
|
||||||
# ---------------------------------------------------------------------- #
|
# ---------------------------------------------------------------------- #
|
||||||
class TkScrollableFrame(tk.Frame):
|
class TkScrollableFrame(tk.Frame):
|
||||||
def __init__(self, master, **kwargs):
|
def __init__(self, master, vertical_only, **kwargs):
|
||||||
tk.Frame.__init__(self, master, **kwargs)
|
tk.Frame.__init__(self, master, **kwargs)
|
||||||
|
|
||||||
# create a canvas object and a vertical scrollbar for scrolling it
|
# create a canvas object and a vertical scrollbar for scrolling it
|
||||||
self.vscrollbar = tk.Scrollbar(self, orient=tk.VERTICAL)
|
self.vscrollbar = tk.Scrollbar(self, orient=tk.VERTICAL)
|
||||||
self.vscrollbar.pack(side='right', fill="y", expand="false")
|
self.vscrollbar.pack(side='right', fill="y", expand="false")
|
||||||
|
|
||||||
|
if not vertical_only:
|
||||||
self.hscrollbar = tk.Scrollbar(self, orient=tk.HORIZONTAL)
|
self.hscrollbar = tk.Scrollbar(self, orient=tk.HORIZONTAL)
|
||||||
self.hscrollbar.pack(side='bottom', fill="x", expand="false")
|
self.hscrollbar.pack(side='bottom', fill="x", expand="false")
|
||||||
|
|
||||||
self.canvas = tk.Canvas(self, yscrollcommand=self.vscrollbar.set, xscrollcommand=self.hscrollbar.set)
|
self.canvas = tk.Canvas(self, yscrollcommand=self.vscrollbar.set, xscrollcommand=self.hscrollbar.set)
|
||||||
|
else:
|
||||||
|
self.canvas = tk.Canvas(self, yscrollcommand=self.vscrollbar.set)
|
||||||
|
|
||||||
self.canvas.pack(side="left", fill="both", expand=True)
|
self.canvas.pack(side="left", fill="both", expand=True)
|
||||||
|
|
||||||
self.vscrollbar.config(command=self.canvas.yview)
|
self.vscrollbar.config(command=self.canvas.yview)
|
||||||
|
if not vertical_only:
|
||||||
self.hscrollbar.config(command=self.canvas.xview)
|
self.hscrollbar.config(command=self.canvas.xview)
|
||||||
|
|
||||||
# reset the view
|
# reset the view
|
||||||
|
@ -2102,6 +2172,7 @@ class TkScrollableFrame(tk.Frame):
|
||||||
self.bind('<Configure>', self.set_scrollregion)
|
self.bind('<Configure>', self.set_scrollregion)
|
||||||
|
|
||||||
self.bind_mouse_scroll(self.canvas, self.yscroll)
|
self.bind_mouse_scroll(self.canvas, self.yscroll)
|
||||||
|
if not vertical_only:
|
||||||
self.bind_mouse_scroll(self.hscrollbar, self.xscroll)
|
self.bind_mouse_scroll(self.hscrollbar, self.xscroll)
|
||||||
self.bind_mouse_scroll(self.vscrollbar, self.yscroll)
|
self.bind_mouse_scroll(self.vscrollbar, self.yscroll)
|
||||||
|
|
||||||
|
@ -2136,7 +2207,7 @@ class TkScrollableFrame(tk.Frame):
|
||||||
# Column #
|
# Column #
|
||||||
# ---------------------------------------------------------------------- #
|
# ---------------------------------------------------------------------- #
|
||||||
class Column(Element):
|
class Column(Element):
|
||||||
def __init__(self, layout, background_color=None, size=(None, None), pad=None, scrollable=False, key=None):
|
def __init__(self, layout, background_color=None, size=(None, None), pad=None, scrollable=False, vertical_scroll_only=False, key=None):
|
||||||
'''
|
'''
|
||||||
Column Element
|
Column Element
|
||||||
:param layout:
|
:param layout:
|
||||||
|
@ -2155,6 +2226,7 @@ class Column(Element):
|
||||||
self.Rows = []
|
self.Rows = []
|
||||||
self.TKFrame = None
|
self.TKFrame = None
|
||||||
self.Scrollable = scrollable
|
self.Scrollable = scrollable
|
||||||
|
self.VerticalScrollOnly = vertical_scroll_only
|
||||||
# self.ImageFilename = image_filename
|
# self.ImageFilename = image_filename
|
||||||
# self.ImageData = image_data
|
# self.ImageData = image_data
|
||||||
# self.ImageSize = image_size
|
# self.ImageSize = image_size
|
||||||
|
@ -2464,7 +2536,7 @@ class Table(Element):
|
||||||
def __init__(self, values, headings=None, visible_column_map=None, col_widths=None, def_col_width=10,
|
def __init__(self, values, headings=None, visible_column_map=None, col_widths=None, def_col_width=10,
|
||||||
auto_size_columns=True, max_col_width=20, select_mode=None, display_row_numbers=False, num_rows=None,
|
auto_size_columns=True, max_col_width=20, select_mode=None, display_row_numbers=False, num_rows=None,
|
||||||
font=None, justification='right', text_color=None, background_color=None, alternating_row_color=None,
|
font=None, justification='right', text_color=None, background_color=None, alternating_row_color=None,
|
||||||
size=(None, None), change_submits=False, pad=None, key=None, tooltip=None):
|
size=(None, None), change_submits=False, bind_return_key=False, pad=None, key=None, tooltip=None):
|
||||||
'''
|
'''
|
||||||
Table Element
|
Table Element
|
||||||
:param values:
|
:param values:
|
||||||
|
@ -2503,7 +2575,9 @@ class Table(Element):
|
||||||
self.AlternatingRowColor = alternating_row_color
|
self.AlternatingRowColor = alternating_row_color
|
||||||
self.SelectedRows = []
|
self.SelectedRows = []
|
||||||
self.ChangeSubmits = change_submits
|
self.ChangeSubmits = change_submits
|
||||||
|
self.BindReturnKey = bind_return_key
|
||||||
|
self.StartingRowNumber = 0 # When displaying row numbers, where to start
|
||||||
|
self.RowHeaderText = 'Row'
|
||||||
super().__init__(ELEM_TYPE_TABLE, text_color=text_color, background_color=background_color, font=font,
|
super().__init__(ELEM_TYPE_TABLE, text_color=text_color, background_color=background_color, font=font,
|
||||||
size=size, pad=pad, key=key, tooltip=tooltip)
|
size=size, pad=pad, key=key, tooltip=tooltip)
|
||||||
return
|
return
|
||||||
|
@ -2518,7 +2592,7 @@ class Table(Element):
|
||||||
# self.TKTreeview.delete(*self.TKTreeview.get_children())
|
# self.TKTreeview.delete(*self.TKTreeview.get_children())
|
||||||
for i, value in enumerate(values):
|
for i, value in enumerate(values):
|
||||||
if self.DisplayRowNumbers:
|
if self.DisplayRowNumbers:
|
||||||
value = [i] + value
|
value = [i+self.StartingRowNumber] + value
|
||||||
id = self.TKTreeview.insert('', 'end', text=i, iid=i + 1, values=value, tag=i % 2)
|
id = self.TKTreeview.insert('', 'end', text=i, iid=i + 1, values=value, tag=i % 2)
|
||||||
if self.AlternatingRowColor is not None:
|
if self.AlternatingRowColor is not None:
|
||||||
self.TKTreeview.tag_configure(1, background=self.AlternatingRowColor)
|
self.TKTreeview.tag_configure(1, background=self.AlternatingRowColor)
|
||||||
|
@ -2539,6 +2613,20 @@ class Table(Element):
|
||||||
self.ParentForm.TKroot.quit()
|
self.ParentForm.TKroot.quit()
|
||||||
|
|
||||||
|
|
||||||
|
def treeview_double_click(self, event):
|
||||||
|
selections = self.TKTreeview.selection()
|
||||||
|
self.SelectedRows = [int(x) - 1 for x in selections]
|
||||||
|
if self.BindReturnKey:
|
||||||
|
MyForm = self.ParentForm
|
||||||
|
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 __del__(self):
|
def __del__(self):
|
||||||
super().__del__()
|
super().__del__()
|
||||||
|
|
||||||
|
@ -2710,11 +2798,11 @@ class ErrorElement(Element):
|
||||||
class Window(object):
|
class Window(object):
|
||||||
|
|
||||||
def __init__(self, title, default_element_size=DEFAULT_ELEMENT_SIZE, default_button_element_size=(None, None),
|
def __init__(self, title, default_element_size=DEFAULT_ELEMENT_SIZE, default_button_element_size=(None, None),
|
||||||
auto_size_text=None, auto_size_buttons=None, location=(None, None), button_color=None, font=None,
|
auto_size_text=None, auto_size_buttons=None, location=(None, None), size=(None, None), button_color=None, font=None,
|
||||||
progress_bar_color=(None, None), background_color=None, border_depth=None, auto_close=False,
|
progress_bar_color=(None, None), background_color=None, border_depth=None, auto_close=False,
|
||||||
auto_close_duration=DEFAULT_AUTOCLOSE_TIME, icon=DEFAULT_WINDOW_ICON, force_toplevel=False,
|
auto_close_duration=DEFAULT_AUTOCLOSE_TIME, icon=DEFAULT_WINDOW_ICON, force_toplevel=False,
|
||||||
alpha_channel=1, return_keyboard_events=False, use_default_focus=True, text_justification=None,
|
alpha_channel=1, return_keyboard_events=False, use_default_focus=True, text_justification=None,
|
||||||
no_titlebar=False, grab_anywhere=False, keep_on_top=False, resizable=False):
|
no_titlebar=False, grab_anywhere=False, keep_on_top=False, resizable=False, disable_close=False):
|
||||||
'''
|
'''
|
||||||
Window
|
Window
|
||||||
:param title:
|
:param title:
|
||||||
|
@ -2786,6 +2874,9 @@ class Window(object):
|
||||||
self.Timeout = None
|
self.Timeout = None
|
||||||
self.TimeoutKey = '_timeout_'
|
self.TimeoutKey = '_timeout_'
|
||||||
self.TimerCancelled = False
|
self.TimerCancelled = False
|
||||||
|
self.DisableClose = disable_close
|
||||||
|
self._Hidden = False
|
||||||
|
self._Size = size
|
||||||
|
|
||||||
# ------------------------- Add ONE Row to Form ------------------------- #
|
# ------------------------- Add ONE Row to Form ------------------------- #
|
||||||
def AddRow(self, *args):
|
def AddRow(self, *args):
|
||||||
|
@ -3135,10 +3226,14 @@ class Window(object):
|
||||||
|
|
||||||
# IT FINALLY WORKED! 29-Oct-2018 was the first time this damned thing got called
|
# IT FINALLY WORKED! 29-Oct-2018 was the first time this damned thing got called
|
||||||
def OnClosingCallback(self):
|
def OnClosingCallback(self):
|
||||||
|
if self.DisableClose:
|
||||||
|
return
|
||||||
# print('Got closing callback')
|
# print('Got closing callback')
|
||||||
self.TKroot.quit() # kick the users out of the mainloop
|
self.TKroot.quit() # kick the users out of the mainloop
|
||||||
if self.CurrentlyRunningMainloop: # quit if this is the current mainloop, otherwise don't quit!
|
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.TKroot.destroy() # kick the users out of the mainloop
|
||||||
|
else:
|
||||||
|
self.RootNeedsDestroying = True
|
||||||
self.TKrootDestroyed = True
|
self.TKrootDestroyed = True
|
||||||
|
|
||||||
return
|
return
|
||||||
|
@ -3150,10 +3245,13 @@ class Window(object):
|
||||||
self.TKroot.grab_release()
|
self.TKroot.grab_release()
|
||||||
|
|
||||||
def Hide(self):
|
def Hide(self):
|
||||||
|
self._Hidden = True
|
||||||
self.TKroot.withdraw()
|
self.TKroot.withdraw()
|
||||||
|
|
||||||
def UnHide(self):
|
def UnHide(self):
|
||||||
|
if self._Hidden:
|
||||||
self.TKroot.deiconify()
|
self.TKroot.deiconify()
|
||||||
|
self._Hidden = False
|
||||||
|
|
||||||
def Disappear(self):
|
def Disappear(self):
|
||||||
self.TKroot.attributes('-alpha', 0)
|
self.TKroot.attributes('-alpha', 0)
|
||||||
|
@ -3189,6 +3287,21 @@ class Window(object):
|
||||||
return int(self.TKroot.winfo_x()), int(self.TKroot.winfo_y())
|
return int(self.TKroot.winfo_x()), int(self.TKroot.winfo_y())
|
||||||
|
|
||||||
|
|
||||||
|
@property
|
||||||
|
def Size(self):
|
||||||
|
win_width = self.TKroot.winfo_width()
|
||||||
|
win_height = self.TKroot.winfo_height()
|
||||||
|
return win_width, win_height
|
||||||
|
|
||||||
|
@Size.setter
|
||||||
|
def Size(self, size):
|
||||||
|
try:
|
||||||
|
self.TKroot.geometry("%sx%s" % (size[0], size[1]))
|
||||||
|
self.TKroot.update_idletasks()
|
||||||
|
except:
|
||||||
|
pass
|
||||||
|
|
||||||
|
|
||||||
def __enter__(self):
|
def __enter__(self):
|
||||||
return self
|
return self
|
||||||
|
|
||||||
|
@ -3606,6 +3719,8 @@ def BuildResultsForSubform(form, initialize_only, top_level_form):
|
||||||
value = element.SelectedRows
|
value = element.SelectedRows
|
||||||
elif element.Type == ELEM_TYPE_TREE:
|
elif element.Type == ELEM_TYPE_TREE:
|
||||||
value = element.SelectedRows
|
value = element.SelectedRows
|
||||||
|
elif element.Type == ELEM_TYPE_GRAPH:
|
||||||
|
value = element.ClickPosition
|
||||||
else:
|
else:
|
||||||
value = None
|
value = None
|
||||||
|
|
||||||
|
@ -3742,7 +3857,10 @@ def _FindElementWithFocusInSubForm(form):
|
||||||
if element.TKEntry is not None:
|
if element.TKEntry is not None:
|
||||||
if element.TKEntry is element.TKEntry.focus_get():
|
if element.TKEntry is element.TKEntry.focus_get():
|
||||||
return element
|
return element
|
||||||
|
if element.Type == ELEM_TYPE_INPUT_MULTILINE:
|
||||||
|
if element.TKText is not None:
|
||||||
|
if element.TKText is element.TKText.focus_get():
|
||||||
|
return element
|
||||||
|
|
||||||
if sys.version_info[0] >= 3:
|
if sys.version_info[0] >= 3:
|
||||||
def AddMenuItem(top_menu, sub_menu_info, element, is_sub_menu=False, skip=False):
|
def AddMenuItem(top_menu, sub_menu_info, element, is_sub_menu=False, skip=False):
|
||||||
|
@ -3864,7 +3982,7 @@ def PackFormIntoFrame(form, containing_frame, toplevel_form):
|
||||||
# ------------------------- COLUMN element ------------------------- #
|
# ------------------------- COLUMN element ------------------------- #
|
||||||
if element_type == ELEM_TYPE_COLUMN:
|
if element_type == ELEM_TYPE_COLUMN:
|
||||||
if element.Scrollable:
|
if element.Scrollable:
|
||||||
col_frame = TkScrollableFrame(tk_row_frame) # do not use yet! not working
|
col_frame = TkScrollableFrame(tk_row_frame, element.VerticalScrollOnly) # do not use yet! not working
|
||||||
PackFormIntoFrame(element, col_frame.TKFrame, toplevel_form)
|
PackFormIntoFrame(element, col_frame.TKFrame, toplevel_form)
|
||||||
col_frame.TKFrame.update()
|
col_frame.TKFrame.update()
|
||||||
if element.Size == (None, None): # if no size specified, use column width x column height/2
|
if element.Size == (None, None): # if no size specified, use column width x column height/2
|
||||||
|
@ -4327,6 +4445,7 @@ def PackFormIntoFrame(form, containing_frame, toplevel_form):
|
||||||
if element.Tooltip is not None:
|
if element.Tooltip is not None:
|
||||||
element.TooltipObject = ToolTip(element._TKCanvas, text=element.Tooltip,
|
element.TooltipObject = ToolTip(element._TKCanvas, text=element.Tooltip,
|
||||||
timeout=DEFAULT_TOOLTIP_TIME)
|
timeout=DEFAULT_TOOLTIP_TIME)
|
||||||
|
|
||||||
# ------------------------- Graph element ------------------------- #
|
# ------------------------- Graph element ------------------------- #
|
||||||
elif element_type == ELEM_TYPE_GRAPH:
|
elif element_type == ELEM_TYPE_GRAPH:
|
||||||
width, height = element_size
|
width, height = element_size
|
||||||
|
@ -4344,6 +4463,11 @@ def PackFormIntoFrame(form, containing_frame, toplevel_form):
|
||||||
if element.Tooltip is not None:
|
if element.Tooltip is not None:
|
||||||
element.TooltipObject = ToolTip(element._TKCanvas, text=element.Tooltip,
|
element.TooltipObject = ToolTip(element._TKCanvas, text=element.Tooltip,
|
||||||
timeout=DEFAULT_TOOLTIP_TIME)
|
timeout=DEFAULT_TOOLTIP_TIME)
|
||||||
|
if element.ChangeSubmits:
|
||||||
|
element._TKCanvas2.bind('<ButtonRelease-1>', element.ButtonReleaseCallBack)
|
||||||
|
element._TKCanvas2.bind('<ButtonPress-1>', element.ButtonPressCallBack)
|
||||||
|
if element.DragSubmits:
|
||||||
|
element._TKCanvas2.bind('<Motion>', element.MotionCallBack)
|
||||||
# ------------------------- MENUBAR element ------------------------- #
|
# ------------------------- MENUBAR element ------------------------- #
|
||||||
elif element_type == ELEM_TYPE_MENUBAR:
|
elif element_type == ELEM_TYPE_MENUBAR:
|
||||||
menu_def = element.MenuDefinition
|
menu_def = element.MenuDefinition
|
||||||
|
@ -4520,15 +4644,15 @@ def PackFormIntoFrame(form, containing_frame, toplevel_form):
|
||||||
displaycolumns.append(element.ColumnHeadings[i])
|
displaycolumns.append(element.ColumnHeadings[i])
|
||||||
column_headings = element.ColumnHeadings
|
column_headings = element.ColumnHeadings
|
||||||
if element.DisplayRowNumbers: # if display row number, tack on the numbers to front of columns
|
if element.DisplayRowNumbers: # if display row number, tack on the numbers to front of columns
|
||||||
displaycolumns = ['Row', ] + displaycolumns
|
displaycolumns = [element.RowHeaderText, ] + displaycolumns
|
||||||
column_headings = ['Row', ] + element.ColumnHeadings
|
column_headings = [element.RowHeaderText, ] + element.ColumnHeadings
|
||||||
element.TKTreeview = tkinter.ttk.Treeview(frame, columns=column_headings,
|
element.TKTreeview = tkinter.ttk.Treeview(frame, columns=column_headings,
|
||||||
displaycolumns=displaycolumns, show='headings', height=height,
|
displaycolumns=displaycolumns, show='headings', height=height,
|
||||||
selectmode=element.SelectMode)
|
selectmode=element.SelectMode)
|
||||||
treeview = element.TKTreeview
|
treeview = element.TKTreeview
|
||||||
if element.DisplayRowNumbers:
|
if element.DisplayRowNumbers:
|
||||||
treeview.heading('Row', text='Row') # make a dummy heading
|
treeview.heading(element.RowHeaderText, text=element.RowHeaderText) # make a dummy heading
|
||||||
treeview.column('Row', width=50, anchor=anchor)
|
treeview.column(element.RowHeaderText, width=50, anchor=anchor)
|
||||||
for i, heading in enumerate(element.ColumnHeadings):
|
for i, heading in enumerate(element.ColumnHeadings):
|
||||||
treeview.heading(heading, text=heading)
|
treeview.heading(heading, text=heading)
|
||||||
if element.AutoSizeColumns:
|
if element.AutoSizeColumns:
|
||||||
|
@ -4543,7 +4667,7 @@ def PackFormIntoFrame(form, containing_frame, toplevel_form):
|
||||||
# Insert values into the tree
|
# Insert values into the tree
|
||||||
for i, value in enumerate(element.Values):
|
for i, value in enumerate(element.Values):
|
||||||
if element.DisplayRowNumbers:
|
if element.DisplayRowNumbers:
|
||||||
value = [i] + value
|
value = [i+element.StartingRowNumber] + value
|
||||||
id = treeview.insert('', 'end', text=value, iid=i + 1, values=value, tag=i % 2)
|
id = treeview.insert('', 'end', text=value, iid=i + 1, values=value, tag=i % 2)
|
||||||
if element.AlternatingRowColor is not None:
|
if element.AlternatingRowColor is not None:
|
||||||
treeview.tag_configure(1, background=element.AlternatingRowColor)
|
treeview.tag_configure(1, background=element.AlternatingRowColor)
|
||||||
|
@ -4554,7 +4678,9 @@ def PackFormIntoFrame(form, containing_frame, toplevel_form):
|
||||||
tkinter.ttk.Style().configure("Treeview", foreground=element.TextColor)
|
tkinter.ttk.Style().configure("Treeview", foreground=element.TextColor)
|
||||||
# scrollable_frame.pack(side=tk.LEFT, padx=element.Pad[0], pady=element.Pad[1], expand=True, fill='both')
|
# scrollable_frame.pack(side=tk.LEFT, padx=element.Pad[0], pady=element.Pad[1], expand=True, fill='both')
|
||||||
treeview.bind("<<TreeviewSelect>>", element.treeview_selected)
|
treeview.bind("<<TreeviewSelect>>", element.treeview_selected)
|
||||||
|
if element.BindReturnKey:
|
||||||
|
treeview.bind('<Return>', element.treeview_double_click)
|
||||||
|
treeview.bind('<Double-Button-1>', element.treeview_double_click)
|
||||||
scrollbar = tk.Scrollbar(frame)
|
scrollbar = tk.Scrollbar(frame)
|
||||||
scrollbar.pack(side=tk.RIGHT, fill='y')
|
scrollbar.pack(side=tk.RIGHT, fill='y')
|
||||||
scrollbar.config(command=treeview.yview)
|
scrollbar.config(command=treeview.yview)
|
||||||
|
@ -4653,6 +4779,8 @@ def ConvertFlexToTK(MyFlexForm):
|
||||||
pass
|
pass
|
||||||
PackFormIntoFrame(MyFlexForm, master, MyFlexForm)
|
PackFormIntoFrame(MyFlexForm, master, MyFlexForm)
|
||||||
# ....................................... DONE creating and laying out window ..........................#
|
# ....................................... DONE creating and laying out window ..........................#
|
||||||
|
if MyFlexForm._Size != (None, None):
|
||||||
|
master.geometry("%sx%s" % (MyFlexForm._Size[0], MyFlexForm._Size[1]))
|
||||||
screen_width = master.winfo_screenwidth() # get window info to move to middle of screen
|
screen_width = master.winfo_screenwidth() # get window info to move to middle of screen
|
||||||
screen_height = master.winfo_screenheight()
|
screen_height = master.winfo_screenheight()
|
||||||
if MyFlexForm.Location != (None, None):
|
if MyFlexForm.Location != (None, None):
|
||||||
|
@ -4691,9 +4819,9 @@ def StartupTK(my_flex_form):
|
||||||
# hidden window
|
# hidden window
|
||||||
_my_windows.Increment()
|
_my_windows.Increment()
|
||||||
_my_windows.hidden_master_root = tk.Tk()
|
_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.attributes('-alpha', 0) # HIDE this window really really really good
|
||||||
_my_windows.hidden_master_root.wm_overrideredirect(True)
|
_my_windows.hidden_master_root.wm_overrideredirect(True) # damn, what did this do again?
|
||||||
_my_windows.hidden_master_root.withdraw()
|
_my_windows.hidden_master_root.withdraw() # no, REALLY hide it
|
||||||
# root = tk.Tk() # users windows are no longer using tk.Tk. They are all Toplevel windows
|
# root = tk.Tk() # users windows are no longer using tk.Tk. They are all Toplevel windows
|
||||||
root = tk.Toplevel()
|
root = tk.Toplevel()
|
||||||
else:
|
else:
|
||||||
|
@ -4747,7 +4875,8 @@ def StartupTK(my_flex_form):
|
||||||
if my_flex_form.Timeout != None:
|
if my_flex_form.Timeout != None:
|
||||||
my_flex_form.TKAfterID = root.after(my_flex_form.Timeout, my_flex_form._TimeoutAlarmCallback)
|
my_flex_form.TKAfterID = root.after(my_flex_form.Timeout, my_flex_form._TimeoutAlarmCallback)
|
||||||
if my_flex_form.NonBlocking:
|
if my_flex_form.NonBlocking:
|
||||||
pass
|
my_flex_form.TKroot.protocol("WM_DESTROY_WINDOW", my_flex_form.OnClosingCallback)
|
||||||
|
my_flex_form.TKroot.protocol("WM_DELETE_WINDOW", my_flex_form.OnClosingCallback)
|
||||||
else: # it's a blocking form
|
else: # it's a blocking form
|
||||||
# print('..... CALLING MainLoop')
|
# print('..... CALLING MainLoop')
|
||||||
my_flex_form.CurrentlyRunningMainloop = True
|
my_flex_form.CurrentlyRunningMainloop = True
|
||||||
|
@ -4881,6 +5010,13 @@ def _ProgressMeterUpdate(bar, value, text_elem, *args):
|
||||||
if bar.ParentForm.RootNeedsDestroying:
|
if bar.ParentForm.RootNeedsDestroying:
|
||||||
try:
|
try:
|
||||||
bar.ParentForm.TKroot.destroy()
|
bar.ParentForm.TKroot.destroy()
|
||||||
|
# there is a bug with progress meters not decrementing the number of windows
|
||||||
|
# correctly when the X is used to close the window
|
||||||
|
# uncommenting this line fixes that problem, but causes a double-decrement when
|
||||||
|
# the cancel button is used... damned if you do, damned if you don't, so I'm choosing
|
||||||
|
# don't, as in don't decrement too many times. It's OK now to have a mismatch in
|
||||||
|
# number of windows because of the "hidden" master window. This ensures all windows
|
||||||
|
# will be toplevel. Sorry about the bug, but the user never sees any problems as a result
|
||||||
# _my_windows.Decrement()
|
# _my_windows.Decrement()
|
||||||
except:
|
except:
|
||||||
pass
|
pass
|
||||||
|
@ -5781,6 +5917,8 @@ def Popup(*args, **_3to2kwargs):
|
||||||
else: icon = DEFAULT_WINDOW_ICON
|
else: icon = DEFAULT_WINDOW_ICON
|
||||||
if 'non_blocking' in _3to2kwargs: non_blocking = _3to2kwargs['non_blocking']; del _3to2kwargs['non_blocking']
|
if 'non_blocking' in _3to2kwargs: non_blocking = _3to2kwargs['non_blocking']; del _3to2kwargs['non_blocking']
|
||||||
else: non_blocking = False
|
else: non_blocking = False
|
||||||
|
if 'custom_text' in _3to2kwargs: custom_text = _3to2kwargs['custom_text']; del _3to2kwargs['custom_text']
|
||||||
|
else: custom_text = (None, None)
|
||||||
if 'auto_close_duration' in _3to2kwargs: auto_close_duration = _3to2kwargs['auto_close_duration']; del _3to2kwargs['auto_close_duration']
|
if 'auto_close_duration' in _3to2kwargs: auto_close_duration = _3to2kwargs['auto_close_duration']; del _3to2kwargs['auto_close_duration']
|
||||||
else: auto_close_duration = None
|
else: auto_close_duration = None
|
||||||
if 'auto_close' in _3to2kwargs: auto_close = _3to2kwargs['auto_close']; del _3to2kwargs['auto_close']
|
if 'auto_close' in _3to2kwargs: auto_close = _3to2kwargs['auto_close']; del _3to2kwargs['auto_close']
|
||||||
|
@ -5848,7 +5986,15 @@ def Popup(*args, **_3to2kwargs):
|
||||||
else:
|
else:
|
||||||
PopupButton = CloseButton
|
PopupButton = CloseButton
|
||||||
# show either an OK or Yes/No depending on paramater
|
# show either an OK or Yes/No depending on paramater
|
||||||
if button_type is POPUP_BUTTONS_YES_NO:
|
if custom_text != (None, None):
|
||||||
|
if type(custom_text) is not tuple:
|
||||||
|
window.AddRow(PopupButton(custom_text,size=(len(custom_text),1), button_color=button_color, focus=True, bind_return_key=True))
|
||||||
|
elif custom_text[1] is None:
|
||||||
|
window.AddRow(PopupButton(custom_text[0],size=(len(custom_text[0]),1), button_color=button_color, focus=True, bind_return_key=True))
|
||||||
|
else:
|
||||||
|
window.AddRow(PopupButton(custom_text[0], button_color=button_color, focus=True, bind_return_key=True, size=(len(custom_text[0]), 1)),
|
||||||
|
PopupButton(custom_text[1], button_color=button_color, size=(len(custom_text[0]), 1)))
|
||||||
|
elif button_type is POPUP_BUTTONS_YES_NO:
|
||||||
window.AddRow(PopupButton('Yes', button_color=button_color, focus=True, bind_return_key=True, pad=((20, 5), 3),
|
window.AddRow(PopupButton('Yes', button_color=button_color, focus=True, bind_return_key=True, pad=((20, 5), 3),
|
||||||
size=(5, 1)), PopupButton('No', button_color=button_color, size=(5, 1)))
|
size=(5, 1)), PopupButton('No', button_color=button_color, size=(5, 1)))
|
||||||
elif button_type is POPUP_BUTTONS_CANCELLED:
|
elif button_type is POPUP_BUTTONS_CANCELLED:
|
||||||
|
|
|
@ -191,7 +191,7 @@ class MyWindows():
|
||||||
self.user_defined_icon = None
|
self.user_defined_icon = None
|
||||||
self.hidden_master_root = None
|
self.hidden_master_root = None
|
||||||
self.QTApplication = None
|
self.QTApplication = None
|
||||||
|
self.active_popups = {}
|
||||||
def Decrement(self):
|
def Decrement(self):
|
||||||
self.NumOpenWindows -= 1 * (self.NumOpenWindows != 0) # decrement if not 0
|
self.NumOpenWindows -= 1 * (self.NumOpenWindows != 0) # decrement if not 0
|
||||||
# print('---- DECREMENTING Num Open Windows = {} ---'.format(self.NumOpenWindows))
|
# print('---- DECREMENTING Num Open Windows = {} ---'.format(self.NumOpenWindows))
|
||||||
|
@ -281,7 +281,11 @@ POPUP_BUTTONS_NO_BUTTONS = 5
|
||||||
# ------------------------------------------------------------------------- #
|
# ------------------------------------------------------------------------- #
|
||||||
class Element():
|
class Element():
|
||||||
def __init__(self, type, size=(None, None), auto_size_text=None, font=None, background_color=None, text_color=None,
|
def __init__(self, type, size=(None, None), auto_size_text=None, font=None, background_color=None, text_color=None,
|
||||||
key=None, pad=None, tooltip=None, size_px=(None,None)):
|
key=None, pad=None, tooltip=None):
|
||||||
|
|
||||||
|
if size[1] is not None and size[1] < 10: # change from character based size to pixels (roughly)
|
||||||
|
self.Size = size[0]*10, size[1]*25
|
||||||
|
else:
|
||||||
self.Size = size
|
self.Size = size
|
||||||
self.Type = type
|
self.Type = type
|
||||||
self.AutoSizeText = auto_size_text
|
self.AutoSizeText = auto_size_text
|
||||||
|
@ -308,7 +312,6 @@ class Element():
|
||||||
self.Key = key # dictionary key for return values
|
self.Key = key # dictionary key for return values
|
||||||
self.Tooltip = tooltip
|
self.Tooltip = tooltip
|
||||||
self.TooltipObject = None
|
self.TooltipObject = None
|
||||||
self.SizePx = size_px
|
|
||||||
|
|
||||||
def FindReturnKeyBoundButton(self, form):
|
def FindReturnKeyBoundButton(self, form):
|
||||||
for row in form.Rows:
|
for row in form.Rows:
|
||||||
|
@ -1038,7 +1041,7 @@ class MultilineOutput(Element):
|
||||||
# Text #
|
# Text #
|
||||||
# ---------------------------------------------------------------------- #
|
# ---------------------------------------------------------------------- #
|
||||||
class Text(Element):
|
class Text(Element):
|
||||||
def __init__(self, text, size=(None, None), size_px=(None, None), auto_size_text=None, click_submits=None, relief=None, font=None,
|
def __init__(self, text, size=(None, None), auto_size_text=None, click_submits=None, relief=None, font=None,
|
||||||
text_color=None, background_color=None, justification=None, pad=None, key=None, tooltip=None):
|
text_color=None, background_color=None, justification=None, pad=None, key=None, tooltip=None):
|
||||||
'''
|
'''
|
||||||
Text Element
|
Text Element
|
||||||
|
@ -1066,8 +1069,9 @@ class Text(Element):
|
||||||
bg = background_color
|
bg = background_color
|
||||||
self.QT_Label = None
|
self.QT_Label = None
|
||||||
|
|
||||||
|
|
||||||
super().__init__(ELEM_TYPE_TEXT, size, auto_size_text, background_color=bg, font=font if font else DEFAULT_FONT,
|
super().__init__(ELEM_TYPE_TEXT, size, auto_size_text, background_color=bg, font=font if font else DEFAULT_FONT,
|
||||||
text_color=self.TextColor, pad=pad, key=key, tooltip=tooltip, size_px=size_px)
|
text_color=self.TextColor, pad=pad, key=key, tooltip=tooltip)
|
||||||
return
|
return
|
||||||
|
|
||||||
|
|
||||||
|
@ -1327,7 +1331,6 @@ class Button(Element):
|
||||||
if self.ParentForm.CurrentlyRunningMainloop:
|
if self.ParentForm.CurrentlyRunningMainloop:
|
||||||
self.ParentForm.QTApplication.exit()
|
self.ParentForm.QTApplication.exit()
|
||||||
pass # TODO # kick the users out of the mainloop
|
pass # TODO # kick the users out of the mainloop
|
||||||
|
|
||||||
return
|
return
|
||||||
|
|
||||||
def Update(self, text=None, button_color=(None, None), disabled=None, image_data=None, image_filename=None):
|
def Update(self, text=None, button_color=(None, None), disabled=None, image_data=None, image_filename=None):
|
||||||
|
@ -2688,22 +2691,31 @@ class Window:
|
||||||
self.CloseNonBlockingForm()
|
self.CloseNonBlockingForm()
|
||||||
else:
|
else:
|
||||||
window._Close()
|
window._Close()
|
||||||
pass # TODO kick out of mainloop
|
if self.CurrentlyRunningMainloop:
|
||||||
|
self.QTApplication.exit() # kick the users out of the mainloop
|
||||||
self.RootNeedsDestroying = True
|
self.RootNeedsDestroying = True
|
||||||
|
self.QT_QMainWindow.close()
|
||||||
|
|
||||||
except:
|
except:
|
||||||
pass
|
pass
|
||||||
|
|
||||||
def timer_timeout(self):
|
def timer_timeout(self):
|
||||||
# first, get the results table built
|
# first, get the results table built
|
||||||
# modify the Results table in the parent FlexForm object
|
# modify the Results table in the parent FlexForm object
|
||||||
# print('TIMEOUT CALLBACK')
|
|
||||||
if self.TimerCancelled:
|
if self.TimerCancelled:
|
||||||
return
|
return
|
||||||
self.LastButtonClicked = self.TimeoutKey
|
self.LastButtonClicked = self.TimeoutKey
|
||||||
self.FormRemainedOpen = True
|
self.FormRemainedOpen = True
|
||||||
if self.CurrentlyRunningMainloop:
|
if self.CurrentlyRunningMainloop:
|
||||||
self.QTApplication.exit() # kick the users out of the mainloop
|
self.QTApplication.exit() # kick the users out of the mainloop
|
||||||
#TODO # kick the users out of the mainloop
|
|
||||||
|
def autoclose_timer_callback(self):
|
||||||
|
print('*** TIMEOUT CALLBACK ***')
|
||||||
|
self.autoclose_timer.stop()
|
||||||
|
self.QT_QMainWindow.close()
|
||||||
|
if self.CurrentlyRunningMainloop:
|
||||||
|
print("quitting window")
|
||||||
|
self.QTApplication.exit() # kick the users out of the mainloop
|
||||||
|
|
||||||
def Read(self, timeout=None, timeout_key=TIMEOUT_KEY):
|
def Read(self, timeout=None, timeout_key=TIMEOUT_KEY):
|
||||||
if timeout == 0: # timeout of zero runs the old readnonblocking
|
if timeout == 0: # timeout of zero runs the old readnonblocking
|
||||||
|
@ -2749,7 +2761,7 @@ class Window:
|
||||||
# normal read blocking code....
|
# normal read blocking code....
|
||||||
if timeout != None:
|
if timeout != None:
|
||||||
self.TimerCancelled = False
|
self.TimerCancelled = False
|
||||||
timer = start_timer(self, timeout)
|
timer = start_window_read_timer(self, timeout)
|
||||||
else:
|
else:
|
||||||
timer = None
|
timer = None
|
||||||
self.CurrentlyRunningMainloop = True
|
self.CurrentlyRunningMainloop = True
|
||||||
|
@ -3050,6 +3062,19 @@ class Window:
|
||||||
self.Window.QTApplication.exit()
|
self.Window.QTApplication.exit()
|
||||||
return QWidget.eventFilter(self, widget, event)
|
return QWidget.eventFilter(self, widget, event)
|
||||||
|
|
||||||
|
def closeEvent(self, event):
|
||||||
|
# print('GOT A CLOSE EVENT!', event)
|
||||||
|
if not self.Window.CurrentlyRunningMainloop: # quit if this is the current mainloop, otherwise don't quit!
|
||||||
|
self.Window.RootNeedsDestroying = True
|
||||||
|
self.Window.QT_QMainWindow.close()
|
||||||
|
self.Window.TKrootDestroyed = True
|
||||||
|
|
||||||
|
# if self.CurrentlyRunningMainloop:
|
||||||
|
# print("quitting window")
|
||||||
|
# self.QTApplication.exit() # kick the users out of the mainloop
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
def __enter__(self):
|
def __enter__(self):
|
||||||
return self
|
return self
|
||||||
|
@ -3059,6 +3084,7 @@ class Window:
|
||||||
return False
|
return False
|
||||||
|
|
||||||
def __del__(self):
|
def __del__(self):
|
||||||
|
# print(f'+++++ Window {self.Title} being deleted +++++')
|
||||||
for row in self.Rows:
|
for row in self.Rows:
|
||||||
for element in row:
|
for element in row:
|
||||||
element.__del__()
|
element.__del__()
|
||||||
|
@ -3696,7 +3722,7 @@ def PackFormIntoFrame(window, containing_frame, toplevel_win):
|
||||||
# Set foreground color
|
# Set foreground color
|
||||||
text_color = element.TextColor
|
text_color = element.TextColor
|
||||||
# Determine Element size
|
# Determine Element size
|
||||||
element_size = element.Size if element.Size != (None, None) else element.SizePx
|
element_size = element.Size
|
||||||
if (element_size == (None, None) and element_type != ELEM_TYPE_BUTTON): # user did not specify a size
|
if (element_size == (None, None) and element_type != ELEM_TYPE_BUTTON): # user did not specify a size
|
||||||
element_size = toplevel_win.DefaultElementSize
|
element_size = toplevel_win.DefaultElementSize
|
||||||
elif (element_size == (None, None) and element_type == ELEM_TYPE_BUTTON):
|
elif (element_size == (None, None) and element_type == ELEM_TYPE_BUTTON):
|
||||||
|
@ -3783,7 +3809,7 @@ def PackFormIntoFrame(window, containing_frame, toplevel_win):
|
||||||
if element.BorderWidth == 0:
|
if element.BorderWidth == 0:
|
||||||
style += 'border: none;'
|
style += 'border: none;'
|
||||||
element.QT_QPushButton.setStyleSheet(style)
|
element.QT_QPushButton.setStyleSheet(style)
|
||||||
if (element.AutoSizeButton is False or toplevel_win.AutoSizeButtons is False or element_size[0] is not None) and element.ImageData is None:
|
if (element.AutoSizeButton is False or toplevel_win.AutoSizeButtons is False or element.Size[0] is not None) and element.ImageData is None:
|
||||||
if element_size[0] is not None:
|
if element_size[0] is not None:
|
||||||
element.QT_QPushButton.setFixedWidth(element_size[0])
|
element.QT_QPushButton.setFixedWidth(element_size[0])
|
||||||
if element_size[1] is not None:
|
if element_size[1] is not None:
|
||||||
|
@ -4139,7 +4165,7 @@ def PackFormIntoFrame(window, containing_frame, toplevel_win):
|
||||||
element.QT_QMenuBar = QMenuBar(toplevel_win.QT_QMainWindow)
|
element.QT_QMenuBar = QMenuBar(toplevel_win.QT_QMainWindow)
|
||||||
|
|
||||||
for menu_entry in menu_def:
|
for menu_entry in menu_def:
|
||||||
print(f'Adding a Menubar ENTRY {menu_entry}')
|
# print(f'Adding a Menubar ENTRY {menu_entry}')
|
||||||
baritem = QMenu(element.QT_QMenuBar)
|
baritem = QMenu(element.QT_QMenuBar)
|
||||||
baritem.setTitle(menu_entry[0])
|
baritem.setTitle(menu_entry[0])
|
||||||
element.QT_QMenuBar.addAction(baritem.menuAction())
|
element.QT_QMenuBar.addAction(baritem.menuAction())
|
||||||
|
@ -4352,7 +4378,7 @@ def ConvertFlexToTK(window):
|
||||||
screen_width = 000000 # get window info to move to middle of screen
|
screen_width = 000000 # get window info to move to middle of screen
|
||||||
screen_height = 000000
|
screen_height = 000000
|
||||||
if window.Location != (None, None):
|
if window.Location != (None, None):
|
||||||
window.QTWindow.move(window.Location[0], window.Location[1])
|
window.QT_QMainWindow.move(window.Location[0], window.Location[1])
|
||||||
x, y = window.Location
|
x, y = window.Location
|
||||||
elif DEFAULT_WINDOW_LOCATION != (None, None):
|
elif DEFAULT_WINDOW_LOCATION != (None, None):
|
||||||
x, y = DEFAULT_WINDOW_LOCATION
|
x, y = DEFAULT_WINDOW_LOCATION
|
||||||
|
@ -4372,12 +4398,20 @@ def ConvertFlexToTK(window):
|
||||||
|
|
||||||
# ----====----====----====----====----==== Start timer ====----====----====----====----====----#
|
# ----====----====----====----====----==== Start timer ====----====----====----====----====----#
|
||||||
|
|
||||||
def start_timer(window, amount):
|
def start_window_read_timer(window, amount):
|
||||||
timer = QtCore.QTimer()
|
timer = QtCore.QTimer()
|
||||||
timer.timeout.connect(window.timer_timeout)
|
timer.timeout.connect(window.timer_timeout)
|
||||||
timer.start(amount)
|
timer.start(amount)
|
||||||
return timer
|
return timer
|
||||||
|
|
||||||
|
|
||||||
|
def start_window_autoclose_timer(window, amount):
|
||||||
|
timer = QtCore.QTimer()
|
||||||
|
window.autoclose_timer = timer
|
||||||
|
timer.timeout.connect(window.autoclose_timer_callback)
|
||||||
|
timer.start(amount)
|
||||||
|
return timer
|
||||||
|
|
||||||
def stop_timer(timer):
|
def stop_timer(timer):
|
||||||
timer.stop()
|
timer.stop()
|
||||||
|
|
||||||
|
@ -4448,7 +4482,6 @@ def StartupTK(window):
|
||||||
|
|
||||||
window.QT_QMainWindow.setWindowTitle(window.Title)
|
window.QT_QMainWindow.setWindowTitle(window.Title)
|
||||||
|
|
||||||
|
|
||||||
if (window.GrabAnywhere is not False and not (
|
if (window.GrabAnywhere is not False and not (
|
||||||
window.NonBlocking and window.GrabAnywhere is not True)):
|
window.NonBlocking and window.GrabAnywhere is not True)):
|
||||||
pass
|
pass
|
||||||
|
@ -4481,8 +4514,13 @@ def StartupTK(window):
|
||||||
if window.FocusElement is not None:
|
if window.FocusElement is not None:
|
||||||
window.FocusElement.setFocus()
|
window.FocusElement.setFocus()
|
||||||
|
|
||||||
|
timer = None
|
||||||
|
if window.AutoClose:
|
||||||
|
timer = start_window_autoclose_timer(window, window.AutoCloseDuration*1000)
|
||||||
|
|
||||||
if not window.NonBlocking:
|
if not window.NonBlocking:
|
||||||
timer = start_timer(window, window.Timeout) if window.Timeout else None
|
if window.Timeout:
|
||||||
|
timer = start_window_read_timer(window, window.Timeout)
|
||||||
window.QT_QMainWindow.show() ####### The thing that causes the window to be visible ######
|
window.QT_QMainWindow.show() ####### The thing that causes the window to be visible ######
|
||||||
#### ------------------------------ RUN MAIN LOOP HERE ------------------------------ #####
|
#### ------------------------------ RUN MAIN LOOP HERE ------------------------------ #####
|
||||||
window.QTApplication.exec_()
|
window.QTApplication.exec_()
|
||||||
|
@ -4831,6 +4869,7 @@ _easy_print_data = None # global variable... I'm cheating
|
||||||
|
|
||||||
|
|
||||||
class DebugWin():
|
class DebugWin():
|
||||||
|
global _my_windows
|
||||||
def __init__(self, size=(None, None), location=(None, None), font=None, no_titlebar=False, no_button=False,
|
def __init__(self, size=(None, None), location=(None, None), font=None, no_titlebar=False, no_button=False,
|
||||||
grab_anywhere=False, keep_on_top=False):
|
grab_anywhere=False, keep_on_top=False):
|
||||||
# Show a form that's a running counter
|
# Show a form that's a running counter
|
||||||
|
@ -4847,6 +4886,7 @@ class DebugWin():
|
||||||
]
|
]
|
||||||
self.window.AddRows(self.layout)
|
self.window.AddRows(self.layout)
|
||||||
self.window.Read(timeout=0) # Show a non-blocking form, returns immediately
|
self.window.Read(timeout=0) # Show a non-blocking form, returns immediately
|
||||||
|
_my_windows.active_popups[self.window] = 'debug window'
|
||||||
return
|
return
|
||||||
|
|
||||||
def Print(self, *args, end=None, sep=None):
|
def Print(self, *args, end=None, sep=None):
|
||||||
|
@ -4856,7 +4896,7 @@ class DebugWin():
|
||||||
if self.window is None: # if window was destroyed already, just print
|
if self.window is None: # if window was destroyed already, just print
|
||||||
print(*args, sep=sepchar, end=endchar)
|
print(*args, sep=sepchar, end=endchar)
|
||||||
return
|
return
|
||||||
|
_my_windows.active_popups[self.window] = 'debug window'
|
||||||
event, values = self.window.Read(timeout=0)
|
event, values = self.window.Read(timeout=0)
|
||||||
if event == 'Quit' or event is None:
|
if event == 'Quit' or event is None:
|
||||||
self.Close()
|
self.Close()
|
||||||
|
@ -5478,6 +5518,8 @@ def Popup(*args, button_color=None, background_color=None, text_color=None, butt
|
||||||
:param location:
|
:param location:
|
||||||
:return:
|
:return:
|
||||||
"""
|
"""
|
||||||
|
global _my_windows
|
||||||
|
|
||||||
if not args:
|
if not args:
|
||||||
args_to_print = ['']
|
args_to_print = ['']
|
||||||
else:
|
else:
|
||||||
|
@ -5509,6 +5551,8 @@ def Popup(*args, button_color=None, background_color=None, text_color=None, butt
|
||||||
Text(message_wrapped, auto_size_text=True, text_color=text_color, background_color=background_color))
|
Text(message_wrapped, auto_size_text=True, text_color=text_color, background_color=background_color))
|
||||||
total_lines += height
|
total_lines += height
|
||||||
|
|
||||||
|
if total_lines < 3:
|
||||||
|
[window.AddRow(Text('')) for i in range(2)]
|
||||||
if non_blocking:
|
if non_blocking:
|
||||||
PopupButton = DummyButton # important to use or else button will close other windows too!
|
PopupButton = DummyButton # important to use or else button will close other windows too!
|
||||||
else:
|
else:
|
||||||
|
@ -5529,11 +5573,11 @@ def Popup(*args, button_color=None, background_color=None, text_color=None, butt
|
||||||
elif button_type is POPUP_BUTTONS_NO_BUTTONS:
|
elif button_type is POPUP_BUTTONS_NO_BUTTONS:
|
||||||
pass
|
pass
|
||||||
else:
|
else:
|
||||||
window.AddRow(PopupButton('OK', size=(60, 20), button_color=button_color, focus=True, bind_return_key=True,
|
window.AddRow(PopupButton('OK', size=(60, 20), button_color=button_color, focus=True, bind_return_key=True))
|
||||||
pad=((20, 0), 3)))
|
|
||||||
|
|
||||||
if non_blocking:
|
if non_blocking:
|
||||||
button, values = window.Read(timeout=0)
|
button, values = window.Read(timeout=0)
|
||||||
|
_my_windows.active_popups[window] = title
|
||||||
else:
|
else:
|
||||||
button, values = window.Read()
|
button, values = window.Read()
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue