Automatic conversion from tkinter size to pixels, Better multi-window support, Auto-close feature for windows
This commit is contained in:
parent
b85d6e826c
commit
1a29393e8c
|
@ -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,8 +281,12 @@ 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):
|
||||||
self.Size = size
|
|
||||||
|
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.Type = type
|
self.Type = type
|
||||||
self.AutoSizeText = auto_size_text
|
self.AutoSizeText = auto_size_text
|
||||||
self.Pad = DEFAULT_ELEMENT_PADDING if pad is None else pad
|
self.Pad = DEFAULT_ELEMENT_PADDING if pad is None else pad
|
||||||
|
@ -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