Multi-window support!!
This commit is contained in:
parent
5020aa7382
commit
bf2da43a48
|
@ -442,7 +442,7 @@ class Element():
|
||||||
if visible is False:
|
if visible is False:
|
||||||
widget.attributes['hidden'] = 'true'
|
widget.attributes['hidden'] = 'true'
|
||||||
elif visible is True:
|
elif visible is True:
|
||||||
widget.attributes['hidden'] = 'false'
|
del(widget.attributes['hidden'])
|
||||||
|
|
||||||
def __del__(self):
|
def __del__(self):
|
||||||
pass
|
pass
|
||||||
|
@ -1482,14 +1482,7 @@ class Button(Element):
|
||||||
self.ParentForm.FormRemainedOpen = True
|
self.ParentForm.FormRemainedOpen = True
|
||||||
element_callback_quit_mainloop(self)
|
element_callback_quit_mainloop(self)
|
||||||
elif self.BType == BUTTON_TYPE_CLOSES_WIN_ONLY: # special kind of button that does not exit main loop
|
elif self.BType == BUTTON_TYPE_CLOSES_WIN_ONLY: # special kind of button that does not exit main loop
|
||||||
if self.Key is not None:
|
element_callback_quit_mainloop(self)
|
||||||
self.ParentForm.LastButtonClicked = self.Key
|
|
||||||
else:
|
|
||||||
self.ParentForm.LastButtonClicked = self.ButtonText
|
|
||||||
if self.ParentForm.CurrentlyRunningMainloop: # if this window is running the mainloop, kick out
|
|
||||||
self.ParentForm.App.ExitMainLoop()
|
|
||||||
self.ParentForm.IgnoreClose = True
|
|
||||||
self.ParentForm.MasterFrame.Close()
|
|
||||||
self.ParentForm._Close()
|
self.ParentForm._Close()
|
||||||
Window.DecrementOpenCount()
|
Window.DecrementOpenCount()
|
||||||
elif self.BType == BUTTON_TYPE_CALENDAR_CHOOSER: # this is a return type button so GET RESULTS and destroy window
|
elif self.BType == BUTTON_TYPE_CALENDAR_CHOOSER: # this is a return type button so GET RESULTS and destroy window
|
||||||
|
@ -2592,6 +2585,8 @@ class Window:
|
||||||
stdout_is_rerouted = False
|
stdout_is_rerouted = False
|
||||||
stdout_location = None
|
stdout_location = None
|
||||||
port_number = 6900
|
port_number = 6900
|
||||||
|
active_windows = [ ] # type: Window []
|
||||||
|
App = None
|
||||||
|
|
||||||
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), size=(None, None),
|
auto_size_text=None, auto_size_buttons=None, location=(None, None), size=(None, None),
|
||||||
|
@ -2693,6 +2688,7 @@ class Window:
|
||||||
self.thread_id = None
|
self.thread_id = None
|
||||||
self.App = None # type: Window.MyApp
|
self.App = None # type: Window.MyApp
|
||||||
self.MessageQueue = Queue()
|
self.MessageQueue = Queue()
|
||||||
|
self.master_widget = None
|
||||||
|
|
||||||
@classmethod
|
@classmethod
|
||||||
def IncrementOpenCount(self):
|
def IncrementOpenCount(self):
|
||||||
|
@ -3028,25 +3024,31 @@ class Window:
|
||||||
self.MasterFrame.Maximize()
|
self.MasterFrame.Maximize()
|
||||||
|
|
||||||
def _Close(self):
|
def _Close(self):
|
||||||
try:
|
|
||||||
self.TKroot.update()
|
|
||||||
except:
|
|
||||||
pass
|
|
||||||
if not self.NonBlocking:
|
if not self.NonBlocking:
|
||||||
BuildResults(self, False, self)
|
BuildResults(self, False, self)
|
||||||
if self.TKrootDestroyed:
|
if self.TKrootDestroyed:
|
||||||
return None
|
return None
|
||||||
self.TKrootDestroyed = True
|
self.TKrootDestroyed = True
|
||||||
self.RootNeedsDestroying = True
|
self.RootNeedsDestroying = True
|
||||||
|
self.Close()
|
||||||
self.__del__()
|
self.__del__()
|
||||||
return None
|
|
||||||
|
|
||||||
def Close(self):
|
def Close(self):
|
||||||
|
if len(Window.active_windows) != 0:
|
||||||
|
del(Window.active_windows[-1]) # delete current window from active windows
|
||||||
|
if len(Window.active_windows) != 0:
|
||||||
|
window = Window.active_windows[-1] # get prior window to change to
|
||||||
|
print(f'In close, changing to widget {window.master_widget}')
|
||||||
|
Window.App.set_root_widget(window.master_widget)
|
||||||
|
else:
|
||||||
|
self.App.close()
|
||||||
|
self.App.server.server_starter_instance._alive = False
|
||||||
|
self.App.server.server_starter_instance._sserver.shutdown()
|
||||||
|
return
|
||||||
|
|
||||||
self.App.close()
|
self.App.close()
|
||||||
self.App.server.server_starter_instance._alive = False
|
self.App.server.server_starter_instance._alive = False
|
||||||
self.App.server.server_starter_instance._sserver.shutdown()
|
self.App.server.server_starter_instance._sserver.shutdown()
|
||||||
if self.TKrootDestroyed:
|
|
||||||
return
|
|
||||||
# try:
|
# try:
|
||||||
# self.MasterFrame.Close()
|
# self.MasterFrame.Close()
|
||||||
# except:
|
# except:
|
||||||
|
@ -3183,23 +3185,28 @@ class Window:
|
||||||
|
|
||||||
|
|
||||||
class MyApp(remi.App):
|
class MyApp(remi.App):
|
||||||
def __init__(self,*args):
|
def __init__(self,*args, userdata2=None):
|
||||||
# self.window = window # type: Window
|
# self.window = window # type: Window
|
||||||
# print(args[-1])
|
# print(args[-1])
|
||||||
userdata = args[-1].userdata
|
if userdata2 is None:
|
||||||
self.window = userdata[0] # type: Window
|
userdata = args[-1].userdata
|
||||||
|
self.window = userdata[0] # type: Window
|
||||||
|
else:
|
||||||
|
self.window = userdata2
|
||||||
self.window.App = self
|
self.window.App = self
|
||||||
super(Window.MyApp, self).__init__(*args)
|
self.master_widget = None
|
||||||
|
if userdata2 is None:
|
||||||
|
super(Window.MyApp, self).__init__(*args)
|
||||||
|
|
||||||
def main(self, name='world'):
|
def main(self, name='world'):
|
||||||
# margin 0px auto allows to center the app to the screen
|
# margin 0px auto allows to center the app to the screen
|
||||||
wid = remi.gui.VBox()
|
self.master_widget = remi.gui.VBox()
|
||||||
wid.style['justify-content'] = 'flex-start'
|
self.master_widget.style['justify-content'] = 'flex-start'
|
||||||
wid.style['align-items'] = 'baseline'
|
self.master_widget.style['align-items'] = 'baseline'
|
||||||
if self.window.BackgroundColor not in (None, COLOR_SYSTEM_DEFAULT):
|
if self.window.BackgroundColor not in (None, COLOR_SYSTEM_DEFAULT):
|
||||||
wid.style['background-color'] = self.window.BackgroundColor
|
self.master_widget.style['background-color'] = self.window.BackgroundColor
|
||||||
try:
|
try:
|
||||||
PackFormIntoFrame(self.window, wid, self.window)
|
PackFormIntoFrame(self.window, self.master_widget, self.window)
|
||||||
except:
|
except:
|
||||||
print('* ERROR PACKING FORM *')
|
print('* ERROR PACKING FORM *')
|
||||||
print(traceback.format_exc())
|
print(traceback.format_exc())
|
||||||
|
@ -3208,14 +3215,15 @@ class Window:
|
||||||
tag = remi.gui.Tag(_type='script')
|
tag = remi.gui.Tag(_type='script')
|
||||||
tag.add_child("javascript", """window.onunload=function(e){sendCallback('%s','%s');return "close?";};""" % (
|
tag.add_child("javascript", """window.onunload=function(e){sendCallback('%s','%s');return "close?";};""" % (
|
||||||
str(id(self)), "on_window_close"))
|
str(id(self)), "on_window_close"))
|
||||||
wid.add_child("onunloadevent", tag)
|
self.master_widget.add_child("onunloadevent", tag)
|
||||||
self.window.MessageQueue.put('Layout complete') # signal the main code that the layout is all done
|
self.window.MessageQueue.put('Layout complete') # signal the main code that the layout is all done
|
||||||
return wid # returning the root widget
|
self.window.master_widget = self.master_widget
|
||||||
|
return self.master_widget # returning the root widget
|
||||||
|
|
||||||
|
|
||||||
def on_window_close(self):
|
def on_window_close(self):
|
||||||
# here you can handle the unload
|
# here you can handle the unload
|
||||||
# print("app closing")
|
print("app closing")
|
||||||
self.close()
|
self.close()
|
||||||
self.server.server_starter_instance._alive = False
|
self.server.server_starter_instance._alive = False
|
||||||
self.server.server_starter_instance._sserver.shutdown()
|
self.server.server_starter_instance._sserver.shutdown()
|
||||||
|
@ -4821,80 +4829,28 @@ def StartupTK(window:Window):
|
||||||
master = 00000
|
master = 00000
|
||||||
|
|
||||||
InitializeResults(window)
|
InitializeResults(window)
|
||||||
# REMI - this call moved to inside of the REMI thread
|
|
||||||
# PackFormIntoFrame(window, master, window)
|
|
||||||
# ....................................... DONE creating and laying out window ..........................#
|
|
||||||
# if MyFlexForm._Size != (None, None):
|
|
||||||
# master.geometry("%sx%s" % (MyFlexForm._Size[0], MyFlexForm._Size[1]))
|
|
||||||
|
|
||||||
# Center in middle of screen
|
if len(Window.active_windows) == 0:
|
||||||
# screen_width = master.winfo_screenwidth() # get window info to move to middle of screen
|
window.thread_id = threading.Thread(target=window.remi_thread, daemon=True)
|
||||||
# screen_height = master.winfo_screenheight()
|
window.thread_id.daemon = True
|
||||||
# if window.Location != (None, None):
|
window.thread_id.start()
|
||||||
# x, y = window.Location
|
item = window.MessageQueue.get() # Get the layout complete message
|
||||||
# elif DEFAULT_WINDOW_LOCATION != (None, None):
|
Window.active_windows.append(window)
|
||||||
# x, y = DEFAULT_WINDOW_LOCATION
|
Window.App = window.App
|
||||||
# else:
|
else:
|
||||||
# master.update_idletasks() # don't forget to do updates or values are bad
|
# margin 0px auto allows to center the app to the screen
|
||||||
# win_width = master.winfo_width()
|
master_widget = remi.gui.VBox()
|
||||||
# win_height = master.winfo_height()
|
master_widget.style['justify-content'] = 'flex-start'
|
||||||
# x = screen_width / 2 - win_width / 2
|
master_widget.style['align-items'] = 'baseline'
|
||||||
# y = screen_height / 2 - win_height / 2
|
if window.BackgroundColor not in (None, COLOR_SYSTEM_DEFAULT):
|
||||||
# if y + win_height > screen_height:
|
master_widget.style['background-color'] = window.BackgroundColor
|
||||||
# y = screen_height - win_height
|
PackFormIntoFrame(window, master_widget, window)
|
||||||
# if x + win_width > screen_width:
|
window.master_widget = master_widget
|
||||||
# x = screen_width - win_width
|
Window.active_windows.append(window)
|
||||||
#
|
Window.App.set_root_widget(master_widget)
|
||||||
# move_string = '+%i+%i' % (int(x), int(y))
|
|
||||||
# master.geometry(move_string)
|
|
||||||
#
|
|
||||||
# master.update_idletasks() # don't forget
|
|
||||||
|
|
||||||
|
|
||||||
window.thread_id = threading.Thread(target=window.remi_thread, daemon=True)
|
|
||||||
window.thread_id.daemon = True
|
|
||||||
window.thread_id.start()
|
|
||||||
item = window.MessageQueue.get() # Get the layout complete message
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
# my_flex_form.SetIcon(my_flex_form.WindowIcon)
|
|
||||||
|
|
||||||
# root.attributes('-alpha', my_flex_form.AlphaChannel) # Make window visible again
|
|
||||||
|
|
||||||
# if my_flex_form.ReturnKeyboardEvents and not my_flex_form.NonBlocking:
|
|
||||||
# root.bind("<KeyRelease>", my_flex_form._KeyboardCallback)
|
|
||||||
# root.bind("<MouseWheel>", my_flex_form._MouseWheelCallback)
|
|
||||||
# elif my_flex_form.ReturnKeyboardEvents:
|
|
||||||
# root.bind("<Key>", my_flex_form._KeyboardCallback)
|
|
||||||
# root.bind("<MouseWheel>", my_flex_form._MouseWheelCallback)
|
|
||||||
|
|
||||||
# if my_flex_form.AutoClose:
|
|
||||||
# duration = DEFAULT_AUTOCLOSE_TIME if my_flex_form.AutoCloseDuration is None else my_flex_form.AutoCloseDuration
|
|
||||||
# my_flex_form.TKAfterID = root.after(duration * 1000, my_flex_form._AutoCloseAlarmCallback)
|
|
||||||
#
|
|
||||||
# if my_flex_form.Timeout != None:
|
|
||||||
# my_flex_form.TKAfterID = root.after(my_flex_form.Timeout, my_flex_form._TimeoutAlarmCallback)
|
|
||||||
# if my_flex_form.NonBlocking:
|
|
||||||
# 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
|
|
||||||
# print('..... CALLING MainLoop')
|
|
||||||
# my_flex_form.CurrentlyRunningMainloop = True
|
|
||||||
# my_flex_form.TKroot.protocol("WM_DESTROY_WINDOW", my_flex_form.OnClosingCallback)
|
|
||||||
# my_flex_form.TKroot.protocol("WM_DELETE_WINDOW", my_flex_form.OnClosingCallback)
|
|
||||||
# my_flex_form.TKroot.mainloop()
|
|
||||||
# my_flex_form.CurrentlyRunningMainloop = False
|
|
||||||
# my_flex_form.TimerCancelled = True
|
|
||||||
# print('..... BACK from MainLoop')
|
|
||||||
# if not my_flex_form.FormRemainedOpen:
|
|
||||||
# _my_windows.Decrement()
|
|
||||||
# if my_flex_form.RootNeedsDestroying:
|
|
||||||
# my_flex_form.TKroot.destroy()
|
|
||||||
# my_flex_form.RootNeedsDestroying = False
|
|
||||||
return
|
return
|
||||||
|
|
||||||
|
|
||||||
# ==============================_GetNumLinesNeeded ==#
|
# ==============================_GetNumLinesNeeded ==#
|
||||||
# Helper function for determining how to wrap text #
|
# Helper function for determining how to wrap text #
|
||||||
# ===================================================#
|
# ===================================================#
|
||||||
|
@ -5937,7 +5893,7 @@ def Popup(*args, button_color=None, background_color=None, text_color=None, butt
|
||||||
button, values = window.Read(timeout=0)
|
button, values = window.Read(timeout=0)
|
||||||
else:
|
else:
|
||||||
button, values = window.Read()
|
button, values = window.Read()
|
||||||
window.Close()
|
window.Close()
|
||||||
return button
|
return button
|
||||||
|
|
||||||
|
|
||||||
|
@ -6469,7 +6425,7 @@ def main():
|
||||||
[Text('PySimpleGUIWeb Welcomes You...', tooltip='text', font=('Comic sans ms', 20),size=(40,1), text_color='red', enable_events=True, key='_PySimpleGUIWeb_')],
|
[Text('PySimpleGUIWeb Welcomes You...', tooltip='text', font=('Comic sans ms', 20),size=(40,1), text_color='red', enable_events=True, key='_PySimpleGUIWeb_')],
|
||||||
[T('Current Time '), Text('Text', key='_TEXT_', font='Arial 18', text_color='black', size=(30,1)), Column(col1, background_color='red')],
|
[T('Current Time '), Text('Text', key='_TEXT_', font='Arial 18', text_color='black', size=(30,1)), Column(col1, background_color='red')],
|
||||||
[T('Up Time'), Text('Text', key='_TEXT_UPTIME_', font='Arial 18', text_color='black', size=(30,1))],
|
[T('Up Time'), Text('Text', key='_TEXT_UPTIME_', font='Arial 18', text_color='black', size=(30,1))],
|
||||||
[Input('Single Line Input', do_not_clear=True, enable_events=True, size=(30, 1), text_color='red')],
|
[Input('Single Line Input', do_not_clear=True, enable_events=False, size=(30, 1), text_color='red')],
|
||||||
[Multiline('Multiline Input', do_not_clear=True, size=(40, 4), enable_events=True, key='_MULTI_IN_')],
|
[Multiline('Multiline Input', do_not_clear=True, size=(40, 4), enable_events=True, key='_MULTI_IN_')],
|
||||||
[MultilineOutput('Multiline Output', size=(80, 8), text_color='blue', font='Courier 12', key='_MULTIOUT_')],
|
[MultilineOutput('Multiline Output', size=(80, 8), text_color='blue', font='Courier 12', key='_MULTIOUT_')],
|
||||||
[Checkbox('Checkbox 1', enable_events=True, key='_CB1_'), Checkbox('Checkbox 2', default=True, key='_CB2_', enable_events=True)],
|
[Checkbox('Checkbox 1', enable_events=True, key='_CB1_'), Checkbox('Checkbox 2', default=True, key='_CB2_', enable_events=True)],
|
||||||
|
@ -6478,7 +6434,7 @@ def main():
|
||||||
[Listbox(values=('Listbox 1', 'Listbox 2', 'Listbox 3'), enable_events =True, size=(10, 3), key='_LIST_')],
|
[Listbox(values=('Listbox 1', 'Listbox 2', 'Listbox 3'), enable_events =True, size=(10, 3), key='_LIST_')],
|
||||||
[Slider((1, 100), default_value=80, key='_SLIDER_', visible=True, enable_events=True)],
|
[Slider((1, 100), default_value=80, key='_SLIDER_', visible=True, enable_events=True)],
|
||||||
[Spin(values=(1, 2, 3), initial_value='2', size=(4, 1), key='_SPIN_', enable_events=True)],
|
[Spin(values=(1, 2, 3), initial_value='2', size=(4, 1), key='_SPIN_', enable_events=True)],
|
||||||
[OK(), Button('Hidden', visible=False), Button('Values'), Button('Exit', button_color=('white', 'red'))]
|
[OK(), Button('Hidden', visible=False, key='_HIDDEN_'), Button('Values'), Button('Exit', button_color=('white', 'red')), Button('UnHide')]
|
||||||
]
|
]
|
||||||
|
|
||||||
window = Window('PySimpleGUIWeb Window', font='Arial 18',default_element_size=(12,1), auto_size_buttons=False).Layout(layout)
|
window = Window('PySimpleGUIWeb Window', font='Arial 18',default_element_size=(12,1), auto_size_buttons=False).Layout(layout)
|
||||||
|
@ -6499,6 +6455,10 @@ def main():
|
||||||
window.Element('_MULTIOUT_').Update(str(values), append=True)
|
window.Element('_MULTIOUT_').Update(str(values), append=True)
|
||||||
elif event != TIMEOUT_KEY:
|
elif event != TIMEOUT_KEY:
|
||||||
window.Element('_MULTIOUT_').Update('EVENT: ' + str(event), append=True)
|
window.Element('_MULTIOUT_').Update('EVENT: ' + str(event), append=True)
|
||||||
|
if event == 'UnHide':
|
||||||
|
print('Unhiding...')
|
||||||
|
window.Element('_HIDDEN_').Update(visible=True)
|
||||||
|
|
||||||
window.Close()
|
window.Close()
|
||||||
|
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue