commit
3bb8380f40
|
@ -12,6 +12,8 @@ from queue import Queue
|
|||
# from remi import start, App
|
||||
import remi
|
||||
import logging
|
||||
import traceback
|
||||
|
||||
|
||||
g_time_start = 0
|
||||
g_time_end = 0
|
||||
|
@ -229,9 +231,11 @@ ELEM_TYPE_INPUT_COMBO = 'combo'
|
|||
ELEM_TYPE_INPUT_OPTION_MENU = 'option menu'
|
||||
ELEM_TYPE_INPUT_RADIO = 'radio'
|
||||
ELEM_TYPE_INPUT_MULTILINE = 'multiline'
|
||||
ELEM_TYPE_MULTILINE_OUTPUT = 'multioutput'
|
||||
ELEM_TYPE_INPUT_CHECKBOX = 'checkbox'
|
||||
ELEM_TYPE_INPUT_SPIN = 'spind'
|
||||
ELEM_TYPE_INPUT_SPIN = 'spin'
|
||||
ELEM_TYPE_BUTTON = 'button'
|
||||
ELEM_TYPE_BUTTONMENU = 'buttonmenu'
|
||||
ELEM_TYPE_IMAGE = 'image'
|
||||
ELEM_TYPE_CANVAS = 'canvas'
|
||||
ELEM_TYPE_FRAME = 'frame'
|
||||
|
@ -387,6 +391,12 @@ class Element():
|
|||
return rc
|
||||
return None
|
||||
|
||||
# ------------------------- REMI CHANGED CALLBACK -----------------------
|
||||
# called when a widget has changed and the element has events enabled
|
||||
def ChangedCallback(self, widget:remi.Widget, *args):
|
||||
self.ParentForm.LastButtonClicked = self.Key if self.Key is not None else ''
|
||||
self.ParentForm.MessageQueue.put(self.ParentForm.LastButtonClicked)
|
||||
|
||||
def TextClickedHandler(self, event):
|
||||
if self.Key is not None:
|
||||
self.ParentForm.LastButtonClicked = self.Key
|
||||
|
@ -521,6 +531,11 @@ class InputText(Element):
|
|||
super().__init__(ELEM_TYPE_INPUT_TEXT, size=size, background_color=bg, text_color=fg, key=key, pad=pad,
|
||||
font=font, tooltip=tooltip, visible=visible, size_px=size_px)
|
||||
|
||||
def InputTextCallback(self, widget:remi.Widget, value, keycode):
|
||||
# print(f'text widget value = {widget.get_value()}')
|
||||
self.ParentForm.LastButtonClicked = chr(int(keycode))
|
||||
self.ParentForm.MessageQueue.put(self.ParentForm.LastButtonClicked)
|
||||
|
||||
def Update(self, value=None, disabled=None):
|
||||
if disabled is True:
|
||||
self.TKEntry['state'] = 'disabled'
|
||||
|
@ -580,11 +595,6 @@ class Combo(Element):
|
|||
text_color=fg, key=key, pad=pad, tooltip=tooltip, font=font or DEFAULT_FONT, visible=visible, size_px=size_px)
|
||||
|
||||
|
||||
def QtCurrentItemChanged(self, state):
|
||||
if self.ChangeSubmits:
|
||||
element_callback_quit_mainloop(self)
|
||||
|
||||
|
||||
|
||||
def Update(self, value=None, values=None, set_to_index=None, disabled=None, readonly=None, background_color=None, text_color=None, font=None, visible=None):
|
||||
if values is not None:
|
||||
|
@ -678,14 +688,14 @@ InputOptionMenu = OptionMenu
|
|||
# Listbox #
|
||||
# ---------------------------------------------------------------------- #
|
||||
class Listbox(Element):
|
||||
def __init__(self, values, default_values=None, select_mode=None, change_submits=False, enable_events=False, bind_return_key=False, size=(None, None), disabled=False, auto_size_text=None, font=None, background_color=None,
|
||||
text_color=None, key=None, pad=None, tooltip=None, visible=True, size_px=(None,None)):
|
||||
'''
|
||||
Listbox Element
|
||||
def __init__(self, values, default_values=None, select_mode=None, change_submits=False, enable_events=False, bind_return_key=False, size=(None, None), disabled=False, auto_size_text=None, font=None, background_color=None, text_color=None, key=None, pad=None, tooltip=None, visible=True, size_px=(None,None)):
|
||||
"""
|
||||
|
||||
:param values:
|
||||
:param default_values:
|
||||
:param select_mode:
|
||||
:param change_submits:
|
||||
:param enable_events:
|
||||
:param bind_return_key:
|
||||
:param size:
|
||||
:param disabled:
|
||||
|
@ -696,7 +706,9 @@ class Listbox(Element):
|
|||
:param key:
|
||||
:param pad:
|
||||
:param tooltip:
|
||||
'''
|
||||
:param visible:
|
||||
:param size_px:
|
||||
"""
|
||||
self.Values = values
|
||||
self.DefaultValues = default_values
|
||||
self.TKListbox = None
|
||||
|
@ -725,11 +737,6 @@ class Listbox(Element):
|
|||
super().__init__(ELEM_TYPE_INPUT_LISTBOX, size=tsize, auto_size_text=auto_size_text, font=font,
|
||||
background_color=bg, text_color=fg, key=key, pad=pad, tooltip=tooltip, visible=visible, size_px=size_px)
|
||||
|
||||
def QtCurrentRowChanged(self, state):
|
||||
if self.ChangeSubmits:
|
||||
element_callback_quit_mainloop(self)
|
||||
|
||||
|
||||
def Update(self, values=None, disabled=None, set_to_index=None,background_color=None, text_color=None, font=None, visible=None):
|
||||
if values is not None:
|
||||
self.Values = values
|
||||
|
@ -849,20 +856,21 @@ class Checkbox(Element):
|
|||
background_color=background_color, text_color=self.TextColor, key=key, pad=pad,
|
||||
tooltip=tooltip, visible=visible, size_px=size_px)
|
||||
|
||||
def ChangedCallback(self, widget:remi.Widget, value):
|
||||
# print(f'text widget value = {widget.get_value()}')
|
||||
self.ParentForm.LastButtonClicked = self.Key
|
||||
self.ParentForm.MessageQueue.put(self.ParentForm.LastButtonClicked)
|
||||
|
||||
def Get(self):
|
||||
return self.WxCheckbox.GetValue()
|
||||
return self.Widget.get_value()
|
||||
|
||||
def Update(self, value=None, disabled=None):
|
||||
if value is not None:
|
||||
try:
|
||||
self.WxCheckbox.SetValue(value)
|
||||
self.InitialState = value
|
||||
except:
|
||||
pass
|
||||
self.Widget.set_value(value)
|
||||
if disabled == True:
|
||||
self.WxCheckbox.Disable()
|
||||
self.Widget.set_enabled(False)
|
||||
elif disabled == False:
|
||||
self.WxCheckbox.Enable()
|
||||
self.Widget.set_enabled(True)
|
||||
|
||||
def __del__(self):
|
||||
super().__del__()
|
||||
|
@ -882,9 +890,8 @@ Check = Checkbox
|
|||
class Spin(Element):
|
||||
# Values = None
|
||||
# TKSpinBox = None
|
||||
def __init__(self, values, initial_value=None, disabled=False, change_submits=False, size=(None, None),
|
||||
auto_size_text=None, font=None, background_color=None, text_color=None, key=None, pad=None,
|
||||
tooltip=None):
|
||||
def __init__(self, values, initial_value=None, disabled=False, change_submits=False, enable_events=False, size=(None, None), readonly=True, auto_size_text=None, font=None, background_color=None, text_color=None, key=None, pad=None,
|
||||
tooltip=None, visible=True, size_px=(None,None)):
|
||||
'''
|
||||
Spinner Element
|
||||
:param values:
|
||||
|
@ -901,50 +908,41 @@ class Spin(Element):
|
|||
:param tooltip:
|
||||
'''
|
||||
self.Values = values
|
||||
self.DefaultValue = initial_value
|
||||
self.ChangeSubmits = change_submits
|
||||
self.TKSpinBox = None
|
||||
self.DefaultValue = initial_value or values[0]
|
||||
self.ChangeSubmits = change_submits or enable_events
|
||||
self.Disabled = disabled
|
||||
bg = background_color if background_color else DEFAULT_INPUT_ELEMENTS_COLOR
|
||||
fg = text_color if text_color is not None else DEFAULT_INPUT_TEXT_COLOR
|
||||
|
||||
self.CurrentValue = self.DefaultValue
|
||||
self.ReadOnly = readonly
|
||||
self.Widget = None # type: remi.gui.SpinBox
|
||||
super().__init__(ELEM_TYPE_INPUT_SPIN, size, auto_size_text, font=font, background_color=bg, text_color=fg,
|
||||
key=key, pad=pad, tooltip=tooltip)
|
||||
key=key, pad=pad, tooltip=tooltip, visible=visible, size_px=size_px)
|
||||
return
|
||||
|
||||
def Update(self, value=None, values=None, disabled=None):
|
||||
|
||||
def Update(self, value=None, values=None, disabled=None, background_color=None, text_color=None, font=None, visible=None):
|
||||
if values != None:
|
||||
old_value = self.TKStringVar.get()
|
||||
self.Values = values
|
||||
self.TKSpinBox.configure(values=values)
|
||||
self.TKStringVar.set(old_value)
|
||||
self.QT_Spinner.setStrings(values)
|
||||
# self.QT_Spinner.setRange(self.Values[0], self.Values[1])
|
||||
if value is not None:
|
||||
# self.QT_Spinner.setValue(value)
|
||||
try:
|
||||
self.TKStringVar.set(value)
|
||||
self.QT_Spinner.setValue(self.QT_Spinner.valueFromText(value))
|
||||
self.DefaultValue = value
|
||||
except:
|
||||
pass
|
||||
self.DefaultValue = value
|
||||
if disabled == True:
|
||||
self.TKSpinBox.configure(state='disabled')
|
||||
self.QT_Spinner.setDisabled(True)
|
||||
elif disabled == False:
|
||||
self.TKSpinBox.configure(state='normal')
|
||||
self.QT_Spinner.setDisabled(False)
|
||||
super().Update(self.QT_Spinner, background_color=background_color, text_color=text_color, font=font, visible=visible)
|
||||
|
||||
def SpinChangedHandler(self, event):
|
||||
# first, get the results table built
|
||||
# modify the Results table in the parent FlexForm object
|
||||
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() # kick the users out of the mainloop
|
||||
def Get(self):
|
||||
return self.Widget.get_value()
|
||||
|
||||
def __del__(self):
|
||||
try:
|
||||
self.TKSpinBox.__del__()
|
||||
except:
|
||||
pass
|
||||
super().__del__()
|
||||
|
||||
|
||||
|
@ -953,9 +951,8 @@ 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,
|
||||
font=None, pad=None, tooltip=None):
|
||||
auto_size_text=None, background_color=None, text_color=None, change_submits=False, enable_events=False, do_not_clear=False,
|
||||
key=None, focus=False, font=None, pad=None, tooltip=None, visible=True, size_px=(None,None)):
|
||||
'''
|
||||
Multiline Element
|
||||
:param default_text:
|
||||
|
@ -981,42 +978,122 @@ class Multiline(Element):
|
|||
fg = text_color if text_color is not None else DEFAULT_INPUT_TEXT_COLOR
|
||||
self.Autoscroll = autoscroll
|
||||
self.Disabled = disabled
|
||||
self.ChangeSubmits = change_submits
|
||||
self.ChangeSubmits = change_submits or enable_events
|
||||
tsize = size # convert tkinter size to pixels
|
||||
if size[0] is not None and size[0] < 100:
|
||||
tsize = size[0]*DEFAULT_PIXELS_TO_CHARS_SCALING[0], size[1]*DEFAULT_PIXELS_TO_CHARS_SCALING[1]
|
||||
self.Widget = None # type: remi.gui.TextInput
|
||||
|
||||
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, font=font or DEFAULT_FONT)
|
||||
super().__init__(ELEM_TYPE_INPUT_MULTILINE, size=tsize, auto_size_text=auto_size_text, background_color=bg,
|
||||
text_color=fg, key=key, pad=pad, tooltip=tooltip, font=font or DEFAULT_FONT, visible=visible, size_px=size_px)
|
||||
return
|
||||
|
||||
def Update(self, value=None, disabled=None, append=False, font=None, text_color=None, background_color=None):
|
||||
if value is not None:
|
||||
try:
|
||||
if not append:
|
||||
self.TKText.delete('1.0', tk.END)
|
||||
self.TKText.insert(tk.END, value)
|
||||
except:
|
||||
pass
|
||||
self.DefaultText = value
|
||||
if self.Autoscroll:
|
||||
self.TKText.see(tk.END)
|
||||
if disabled == True:
|
||||
self.TKText.configure(state='disabled')
|
||||
elif disabled == False:
|
||||
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:
|
||||
self.TKText.configure(font=font)
|
||||
def InputTextCallback(self, widget:remi.Widget, value, keycode):
|
||||
# print(f'text widget value = {widget.get_value()}')
|
||||
self.ParentForm.LastButtonClicked = chr(int(keycode))
|
||||
self.ParentForm.MessageQueue.put(self.ParentForm.LastButtonClicked)
|
||||
|
||||
def Update(self, value=None, disabled=None, append=False, background_color=None, text_color=None, font=None, visible=None):
|
||||
if value is not None and not append:
|
||||
self.Widget.set_value(value)
|
||||
elif value is not None and append:
|
||||
text = self.Widget.get_value() + str(value)
|
||||
self.Widget.set_value(text)
|
||||
# if background_color is not None:
|
||||
# self.WxTextCtrl.SetBackgroundColour(background_color)
|
||||
# if text_color is not None:
|
||||
# self.WxTextCtrl.SetForegroundColour(text_color)
|
||||
# if font is not None:
|
||||
# self.WxTextCtrl.SetFont(font)
|
||||
# if disabled:
|
||||
# self.WxTextCtrl.Enable(True)
|
||||
# elif disabled is False:
|
||||
# self.WxTextCtrl.Enable(False)
|
||||
super().Update(self.Widget, background_color=background_color, text_color=text_color, font=font, visible=visible)
|
||||
|
||||
#
|
||||
# def Update(self, value=None, disabled=None, append=False, background_color=None, text_color=None, font=None, visible=None):
|
||||
# if value is not None and not append:
|
||||
# self.DefaultText = value
|
||||
# self.QT_TextEdit.setText(str(value))
|
||||
# elif value is not None and append:
|
||||
# self.DefaultText = value
|
||||
# self.QT_TextEdit.setText(self.QT_TextEdit.toPlainText() + str(value))
|
||||
# if disabled == True:
|
||||
# self.QT_TextEdit.setDisabled(True)
|
||||
# elif disabled == False:
|
||||
# self.QT_TextEdit.setDisabled(False)
|
||||
# super().Update(self.QT_TextEdit, background_color=background_color, text_color=text_color, font=font, visible=visible)
|
||||
|
||||
|
||||
def Get(self):
|
||||
return self.TKText.get(1.0, tk.END)
|
||||
self.WxTextCtrl.GetValue()
|
||||
|
||||
def SetFocus(self):
|
||||
try:
|
||||
self.TKText.focus_set()
|
||||
except:
|
||||
pass
|
||||
self.WxTextCtrl.SetFocus()
|
||||
|
||||
|
||||
def __del__(self):
|
||||
super().__del__()
|
||||
|
||||
|
||||
# ---------------------------------------------------------------------- #
|
||||
# Multiline Output #
|
||||
# ---------------------------------------------------------------------- #
|
||||
class MultilineOutput(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, enable_events=False, do_not_clear=False, key=None, focus=False, font=None, pad=None, tooltip=None, visible=True, size_px=(None,None)):
|
||||
'''
|
||||
Multiline Element
|
||||
:param default_text:
|
||||
:param enter_submits:
|
||||
:param disabled:
|
||||
:param autoscroll:
|
||||
:param size:
|
||||
:param auto_size_text:
|
||||
:param background_color:
|
||||
:param text_color:
|
||||
:param do_not_clear:
|
||||
:param key:
|
||||
:param focus:
|
||||
:param pad:
|
||||
:param tooltip:
|
||||
:param font:
|
||||
'''
|
||||
self.DefaultText = default_text
|
||||
self.EnterSubmits = enter_submits
|
||||
bg = background_color if background_color else DEFAULT_INPUT_ELEMENTS_COLOR
|
||||
self.Focus = focus
|
||||
self.do_not_clear = do_not_clear
|
||||
fg = text_color if text_color is not None else DEFAULT_INPUT_TEXT_COLOR
|
||||
self.Autoscroll = autoscroll
|
||||
self.Disabled = disabled
|
||||
self.ChangeSubmits = change_submits or enable_events
|
||||
tsize = size # convert tkinter size to pixels
|
||||
if size[0] is not None and size[0] < 100:
|
||||
tsize = size[0]*DEFAULT_PIXELS_TO_CHARS_SCALING[0], size[1]*DEFAULT_PIXELS_TO_CHARS_SCALING[1]
|
||||
self.Widget = None # type: remi.gui.TextInput
|
||||
self.CurrentValue = ''
|
||||
|
||||
super().__init__(ELEM_TYPE_MULTILINE_OUTPUT, size=tsize, auto_size_text=auto_size_text, background_color=bg,
|
||||
text_color=fg, key=key, pad=pad, tooltip=tooltip, font=font or DEFAULT_FONT, visible=visible, size_px=size_px)
|
||||
return
|
||||
|
||||
|
||||
def Update(self, value=None, disabled=None, append=False, background_color=None, text_color=None, font=None, visible=None):
|
||||
if value is not None and not append:
|
||||
self.Widget.set_value(value)
|
||||
elif value is not None and append:
|
||||
self.CurrentValue = self.CurrentValue + '\n' + value
|
||||
self.Widget.set_value(self.CurrentValue)
|
||||
|
||||
super().Update(self.Widget, background_color=background_color, text_color=text_color, font=font, visible=visible)
|
||||
|
||||
|
||||
def Get(self):
|
||||
self.WxTextCtrl.GetValue()
|
||||
|
||||
def SetFocus(self):
|
||||
self.WxTextCtrl.SetFocus()
|
||||
|
||||
def __del__(self):
|
||||
super().__del__()
|
||||
|
@ -2101,26 +2178,23 @@ class TabGroup(Element):
|
|||
# ---------------------------------------------------------------------- #
|
||||
class Slider(Element):
|
||||
def __init__(self, range=(None, None), default_value=None, resolution=None, tick_interval=None, orientation=None,
|
||||
border_width=None, relief=None, change_submits=False, disabled=False, size=(None, None), font=None,
|
||||
background_color=None, text_color=None, key=None, pad=None, tooltip=None):
|
||||
'''
|
||||
Slider Element
|
||||
border_width=None, relief=None, change_submits=False, enable_events=False, disabled=False, size=(None, None), font=None,
|
||||
background_color=None, text_color=None, key=None, pad=None, tooltip=None, visible=True, size_px=(None,None)):
|
||||
"""
|
||||
|
||||
:param range:
|
||||
:param default_value:
|
||||
:param resolution:
|
||||
:param tick_interval:
|
||||
:param orientation:
|
||||
:param border_width:
|
||||
:param relief:
|
||||
:param change_submits:
|
||||
:param enable_events:
|
||||
:param disabled:
|
||||
:param size:
|
||||
:param font:
|
||||
:param background_color:
|
||||
:param text_color:
|
||||
:param key:
|
||||
:param pad:
|
||||
:param tooltip:
|
||||
'''
|
||||
:param visible:
|
||||
:param size_px:
|
||||
"""
|
||||
self.TKScale = None
|
||||
self.Range = (1, 10) if range == (None, None) else range
|
||||
self.DefaultValue = self.Range[0] if default_value is None else default_value
|
||||
|
@ -2128,15 +2202,18 @@ class Slider(Element):
|
|||
self.BorderWidth = border_width if border_width else DEFAULT_SLIDER_BORDER_WIDTH
|
||||
self.Relief = relief if relief else DEFAULT_SLIDER_RELIEF
|
||||
self.Resolution = 1 if resolution is None else resolution
|
||||
self.ChangeSubmits = change_submits
|
||||
self.ChangeSubmits = change_submits or enable_events
|
||||
self.Disabled = disabled
|
||||
self.TickInterval = tick_interval
|
||||
temp_size = size
|
||||
if temp_size == (None, None):
|
||||
temp_size = (20, 20) if orientation.startswith('h') else (8, 20)
|
||||
temp_size = (200, 20) if self.Orientation.startswith('h') else (200, 20)
|
||||
elif size[0] is not None and size[0] < 100:
|
||||
temp_size = size[0]*10, size[1]*3
|
||||
self.Widget = None # type: remi.gui.Slider
|
||||
|
||||
super().__init__(ELEM_TYPE_INPUT_SLIDER, size=temp_size, font=font, background_color=background_color,
|
||||
text_color=text_color, key=key, pad=pad, tooltip=tooltip)
|
||||
text_color=text_color, key=key, pad=pad, tooltip=tooltip, visible=visible, size_px=size_px)
|
||||
return
|
||||
|
||||
def Update(self, value=None, range=(None, None), disabled=None):
|
||||
|
@ -2153,21 +2230,15 @@ class Slider(Element):
|
|||
elif disabled == False:
|
||||
self.TKScale['state'] = 'normal'
|
||||
|
||||
def SliderChangedHandler(self, event):
|
||||
# first, get the results table built
|
||||
# modify the Results table in the parent FlexForm object
|
||||
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() # kick the users out of the mainloop
|
||||
def SliderCallback(self, widget:remi.Widget, value):
|
||||
self.ParentForm.LastButtonClicked = self.Key if self.Key is not None else ''
|
||||
self.ParentForm.MessageQueue.put(self.ParentForm.LastButtonClicked)
|
||||
|
||||
def __del__(self):
|
||||
super().__del__()
|
||||
|
||||
|
||||
|
||||
#
|
||||
# ---------------------------------------------------------------------- #
|
||||
# Column #
|
||||
|
@ -2544,6 +2615,7 @@ class Window:
|
|||
highest_level_app = None
|
||||
stdout_is_rerouted = False
|
||||
stdout_location = None
|
||||
port_number = 6900
|
||||
|
||||
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),
|
||||
|
@ -2763,22 +2835,18 @@ class Window:
|
|||
# print("** REALTIME PROBLEM FOUND **", results)
|
||||
# print('****************** CALLING MESSAGE QUEUE GET ***********************')
|
||||
self.CurrentlyRunningMainloop = True
|
||||
if timeout is not None and timeout != 0:
|
||||
if timeout is not None:
|
||||
try:
|
||||
self.LastButtonClicked = self.MessageQueue.get(timeout=timeout/1000)
|
||||
self.LastButtonClicked = self.MessageQueue.get(timeout=(timeout if timeout else .001)/1000)
|
||||
# print(f'Got event {self.LastButtonClicked}')
|
||||
except: # timeout
|
||||
self.LastButtonClicked = timeout_key
|
||||
elif timeout == 0:
|
||||
try:
|
||||
self.LastButtonClicked = self.MessageQueue.get_nowait()
|
||||
except:
|
||||
self.LastButtonClicked = timeout_key
|
||||
else:
|
||||
self.LastButtonClicked = self.MessageQueue.get()
|
||||
# print(f'Got event {self.LastButtonClicked}')
|
||||
# print('--------------------- BACK FROM MESSAGE QUEUE GET ----------------------')
|
||||
|
||||
results = BuildResults(self, False, self)
|
||||
# print('Results = ', results)
|
||||
return results
|
||||
# print(f'In main {self.Title}')
|
||||
################################# CALL GUWxTextCtrlI MAINLOOP ############################
|
||||
|
@ -2815,7 +2883,6 @@ class Window:
|
|||
# print("*** Faking timeout ***")
|
||||
# self.ReturnValues = self.TimeoutKey, self.ReturnValues[1] # fake a timeout
|
||||
# return self.ReturnValues
|
||||
return None, None
|
||||
|
||||
def _ReadNonBlocking(self):
|
||||
if self.TKrootDestroyed:
|
||||
|
@ -3001,7 +3068,8 @@ class Window:
|
|||
|
||||
def Close(self):
|
||||
self.App.close()
|
||||
|
||||
self.App.server.server_starter_instance._alive = False
|
||||
self.App.server.server_starter_instance._sserver.shutdown()
|
||||
if self.TKrootDestroyed:
|
||||
return
|
||||
# try:
|
||||
|
@ -3112,6 +3180,7 @@ class Window:
|
|||
|
||||
|
||||
def remi_thread(self):
|
||||
logging.getLogger('remi').setLevel(logging.WARNING)
|
||||
logging.getLogger('remi').disabled = True
|
||||
logging.getLogger('remi.server.ws').disabled = True
|
||||
logging.getLogger('remi.server').disabled = True
|
||||
|
@ -3122,8 +3191,15 @@ class Window:
|
|||
# logging.getLogger('remi').setLevel(level=logging.CRITICAL)
|
||||
# logging.getLogger('remi').disabled = True
|
||||
# logging.disable(logging.CRITICAL)
|
||||
remi.start(self.MyApp, title=self.Title ,debug=False, address='0.0.0.0', port=0, start_browser=True, userdata=(self,)) # standalone=True)
|
||||
self.MessageQueue.put(None)
|
||||
# s = remi.server.StandaloneServer(self.MyApp, width=1100, height=600)
|
||||
# s.start()
|
||||
Window.port_number += 1
|
||||
remi.start(self.MyApp, title=self.Title ,debug=False, address='0.0.0.0', port=Window.port_number, start_browser=True, update_interval=.00001, userdata=(self,))
|
||||
# remi.start(self.MyApp, title=self.Title ,debug=False, userdata=(self,), standalone=True) # standalone=True)
|
||||
print('Returned from Remi Start command... now sending None event')
|
||||
# self.App.server_starter_instance._alive = False
|
||||
# self.App.server_starter_instance._sserver.shutdown()
|
||||
self.MessageQueue.put(None) # if returned from start call, then the window has been destroyed and a None event should be generated
|
||||
|
||||
|
||||
class MyApp(remi.App):
|
||||
|
@ -3142,33 +3218,29 @@ class Window:
|
|||
wid.style['align-items'] = 'baseline'
|
||||
if self.window.BackgroundColor not in (None, COLOR_SYSTEM_DEFAULT):
|
||||
wid.style['background-color'] = self.window.BackgroundColor
|
||||
|
||||
PackFormIntoFrame(self.window, wid, self.window)
|
||||
#
|
||||
# lbl = remi.gui.Label("Close or reload the page, the console thread will stop automatically.")
|
||||
# wid.append(lbl)
|
||||
# self.bt = remi.gui.Button('Close')
|
||||
# self.bt.onclick.connect(self.on_close_button)
|
||||
# wid.append(self.bt)
|
||||
|
||||
try:
|
||||
PackFormIntoFrame(self.window, wid, self.window)
|
||||
except:
|
||||
print('* ERROR PACKING FORM *')
|
||||
print(traceback.format_exc())
|
||||
|
||||
# add the following 3 lines to your app and the on_window_close method to make the console close automatically
|
||||
tag = remi.gui.Tag(_type='script')
|
||||
tag.add_child("javascript", """window.onunload=function(e){sendCallback('%s','%s');return "close?";};""" % (
|
||||
str(id(self)), "on_window_close"))
|
||||
wid.add_child("onunloadevent", tag)
|
||||
# TODO: Send message that layout is complete
|
||||
|
||||
self.window.MessageQueue.put('Layout complete')
|
||||
# returning the root widget
|
||||
return wid
|
||||
self.window.MessageQueue.put('Layout complete') # signal the main code that the layout is all done
|
||||
return wid # returning the root widget
|
||||
|
||||
|
||||
def on_window_close(self):
|
||||
# here you can handle the unload
|
||||
# print("app closing")
|
||||
self.window.MessageQueue.put(None)
|
||||
self.close()
|
||||
self.server.server_starter_instance._alive = False
|
||||
self.server.server_starter_instance._sserver.shutdown()
|
||||
self.window.MessageQueue.put(None)
|
||||
print("server stopped")
|
||||
|
||||
FlexForm = Window
|
||||
|
||||
|
@ -3184,8 +3256,11 @@ def element_callback_quit_mainloop(element):
|
|||
element.ParentForm.LastButtonClicked = element.Key
|
||||
else:
|
||||
element.ParentForm.LastButtonClicked = ''
|
||||
element.ParentForm.FormRemainedOpen = True
|
||||
element.ParentForm.LastButtonClicked = element.Key if element.Key is not None else element.ButtonText
|
||||
try:
|
||||
element.ParentForm.LastButtonClicked = element.Key if element.Key is not None else element.ButtonText
|
||||
except:
|
||||
element.ParentForm.LastButtonClicked = element.Key
|
||||
# print(f'Putting into message queue {element.ParentForm.LastButtonClicked}')
|
||||
element.ParentForm.MessageQueue.put(element.ParentForm.LastButtonClicked)
|
||||
|
||||
|
||||
|
@ -3628,22 +3703,14 @@ def BuildResultsForSubform(form, initialize_only, top_level_form):
|
|||
# items = element.TKListbox.curselection()
|
||||
# value = [element.Values[int(item)] for item in items]
|
||||
elif element.Type == ELEM_TYPE_INPUT_SPIN:
|
||||
try:
|
||||
value = element.TKStringVar.get()
|
||||
except:
|
||||
value = 0
|
||||
element = element # type: Spin
|
||||
value = element.Widget.get_value()
|
||||
elif element.Type == ELEM_TYPE_INPUT_SLIDER:
|
||||
try:
|
||||
value = element.TKIntVar.get()
|
||||
except:
|
||||
value = 0
|
||||
element = element # type: Slider
|
||||
value = element.Widget.get_value()
|
||||
elif element.Type == ELEM_TYPE_INPUT_MULTILINE:
|
||||
try:
|
||||
value = element.TKText.get(1.0, tk.END)
|
||||
if not top_level_form.NonBlocking and not element.do_not_clear and not top_level_form.ReturnKeyboardEvents:
|
||||
element.TKText.delete('1.0', tk.END)
|
||||
except:
|
||||
value = None
|
||||
element = element # type: Multiline
|
||||
value = element.Widget.get_value()
|
||||
elif element.Type == ELEM_TYPE_TAB_GROUP:
|
||||
try:
|
||||
value = element.TKNotebook.tab(element.TKNotebook.index('current'))['text']
|
||||
|
@ -3914,6 +3981,10 @@ def PackFormIntoFrame(form, containing_frame, toplevel_form):
|
|||
widget.style['margin'] = '{}px {}px {}px {}px'.format(*full_element_pad)
|
||||
if element.Disabled:
|
||||
widget.set_enabled(False)
|
||||
if not element.Visible:
|
||||
widget.attributes['hidden'] = 'true'
|
||||
if element.Tooltip is not None:
|
||||
widget.attributes['title'] = element.Tooltip
|
||||
#
|
||||
# widget.SetMinSize(element_size)
|
||||
# if element.Disabled:
|
||||
|
@ -3982,8 +4053,6 @@ def PackFormIntoFrame(form, containing_frame, toplevel_form):
|
|||
else:
|
||||
full_element_pad[0], full_element_pad[2] = elementpad[1]
|
||||
|
||||
|
||||
|
||||
# ------------------------- COLUMN element ------------------------- #
|
||||
if element_type == ELEM_TYPE_COLUMN:
|
||||
pass
|
||||
|
@ -4022,55 +4091,11 @@ def PackFormIntoFrame(form, containing_frame, toplevel_form):
|
|||
element.Widget.style['text-align'] = 'center'
|
||||
elif element.Justification.startswith('r'):
|
||||
element.Widget.style['text-align'] = 'right'
|
||||
if element.ClickSubmits:
|
||||
element.Widget.onclick.connect(element.ChangedCallback)
|
||||
tk_row_frame.append(element.Widget)
|
||||
|
||||
# auto_size_text = element.AutoSizeText
|
||||
# display_text = element.DisplayText # text to display
|
||||
# if auto_size_text is False:
|
||||
# width, height = element_size
|
||||
# else:
|
||||
# lines = display_text.split('\n')
|
||||
# max_line_len = max([len(l) for l in lines])
|
||||
# num_lines = len(lines)
|
||||
# if max_line_len > element_size[0]: # if text exceeds element size, the will have to wrap
|
||||
# width = element_size[0]
|
||||
# else:
|
||||
# width = max_line_len
|
||||
# height = num_lines
|
||||
# ---===--- LABEL widget create and place --- #
|
||||
# stringvar = tk.StringVar()
|
||||
# element.TKStringVar = stringvar
|
||||
# stringvar.set(display_text)
|
||||
# if auto_size_text:
|
||||
# width = 0
|
||||
# if element.Justification is not None:
|
||||
# justification = element.Justification
|
||||
# elif toplevel_form.TextJustification is not None:
|
||||
# justification = toplevel_form.TextJustification
|
||||
# else:
|
||||
# justification = DEFAULT_TEXT_JUSTIFICATION
|
||||
# justify = tk.LEFT if justification == 'left' else tk.CENTER if justification == 'center' else tk.RIGHT
|
||||
# anchor = tk.NW if justification == 'left' else tk.N if justification == 'center' else tk.NE
|
||||
# tktext_label = tk.Label(tk_row_frame, textvariable=stringvar, width=width, height=height,
|
||||
# justify=justify, bd=border_depth, font=font)
|
||||
# Set wrap-length for text (in PIXELS) == PAIN IN THE ASS
|
||||
# wraplen = tktext_label.winfo_reqwidth() + 40 # width of widget in Pixels
|
||||
# if not auto_size_text and height == 1:
|
||||
# wraplen = 0
|
||||
# print("wraplen, width, height", wraplen, width, height)
|
||||
# tktext_label.configure(anchor=anchor, wraplen=wraplen) # set wrap to width of widget
|
||||
# if element.Relief is not None:
|
||||
# tktext_label.configure(relief=element.Relief)
|
||||
# if element.BackgroundColor is not None and element.BackgroundColor != COLOR_SYSTEM_DEFAULT:
|
||||
# tktext_label.configure(background=element.BackgroundColor)
|
||||
# if element.TextColor != COLOR_SYSTEM_DEFAULT and element.TextColor is not None:
|
||||
# tktext_label.configure(fg=element.TextColor)
|
||||
# tktext_label.pack(side=tk.LEFT, padx=element.Pad[0], pady=element.Pad[1], expand=True)
|
||||
# element.TKText = tktext_label
|
||||
# if element.ClickSubmits:
|
||||
# tktext_label.bind('<Button-1>', element.TextClickedHandler)
|
||||
# if element.Tooltip is not None:
|
||||
# element.TooltipObject = ToolTip(element.TKText, text=element.Tooltip, timeout=DEFAULT_TOOLTIP_TIME)
|
||||
|
||||
# ------------------------- BUTTON element ------------------------- #
|
||||
elif element_type == ELEM_TYPE_BUTTON:
|
||||
element = element # type: Button
|
||||
|
@ -4153,18 +4178,15 @@ def PackFormIntoFrame(form, containing_frame, toplevel_form):
|
|||
# if element.Tooltip is not None:
|
||||
# element.TooltipObject = ToolTip(element.TKButton, text=element.Tooltip,
|
||||
# timeout=DEFAULT_TOOLTIP_TIME)
|
||||
# # ------------------------- INPUT (Single Line) element ------------------------- #
|
||||
# # ------------------------- INPUT element ------------------------- #
|
||||
elif element_type == ELEM_TYPE_INPUT_TEXT:
|
||||
element = element # type: InputText
|
||||
element.Widget = remi.gui.TextInput()
|
||||
if element.DefaultText:
|
||||
element.Widget.set_value(element.DefaultText)
|
||||
element.Widget = remi.gui.TextInput(hint=element.DefaultText)
|
||||
do_font_and_color(element.Widget)
|
||||
if element.ChangeSubmits:
|
||||
element.Widget.onkeydown.connect(element.InputTextCallback)
|
||||
tk_row_frame.append(element.Widget)
|
||||
|
||||
# default_text = element.DefaultText
|
||||
# element.TKStringVar = tk.StringVar()
|
||||
# element.TKStringVar.set(default_text)
|
||||
# show = element.PasswordCharacter if element.PasswordCharacter else ""
|
||||
# if element.Justification is not None:
|
||||
# justification = element.Justification
|
||||
|
@ -4196,93 +4218,20 @@ def PackFormIntoFrame(form, containing_frame, toplevel_form):
|
|||
if element.DefaultValue is not None:
|
||||
element.Widget.select_by_value(element.DefaultValue)
|
||||
do_font_and_color(element.Widget)
|
||||
if element.ChangeSubmits:
|
||||
element.Widget.onchange.connect(element.ChangedCallback)
|
||||
tk_row_frame.append(element.Widget)
|
||||
# max_line_len = max([len(str(l)) for l in element.Values])
|
||||
# if auto_size_text is False:
|
||||
# width = element_size[0]
|
||||
# else:
|
||||
# width = max_line_len
|
||||
# element.TKStringVar = tk.StringVar()
|
||||
# if element.BackgroundColor is not None and element.BackgroundColor != COLOR_SYSTEM_DEFAULT:
|
||||
# combostyle = ttk.Style()
|
||||
# try:
|
||||
# combostyle.theme_create('combostyle',
|
||||
# settings={'TCombobox':
|
||||
# {'configure':
|
||||
# {'selectbackground': element.BackgroundColor,
|
||||
# 'fieldbackground': element.BackgroundColor,
|
||||
# 'foreground': text_color,
|
||||
# 'background': element.BackgroundColor}
|
||||
# }})
|
||||
# except:
|
||||
# try:
|
||||
# combostyle.theme_settings('combostyle',
|
||||
# settings={'TCombobox':
|
||||
# {'configure':
|
||||
# {'selectbackground': element.BackgroundColor,
|
||||
# 'fieldbackground': element.BackgroundColor,
|
||||
# 'foreground': text_color,
|
||||
# 'background': element.BackgroundColor}
|
||||
# }})
|
||||
# except:
|
||||
# pass
|
||||
# # ATTENTION: this applies the new style 'combostyle' to all ttk.Combobox
|
||||
# combostyle.theme_use('combostyle')
|
||||
# element.TKCombo = ttk.Combobox(tk_row_frame, width=width, textvariable=element.TKStringVar, font=font)
|
||||
# if element.Size[1] != 1 and element.Size[1] is not None:
|
||||
# element.TKCombo.configure(height=element.Size[1])
|
||||
# # element.TKCombo['state']='readonly'
|
||||
# element.TKCombo['values'] = element.Values
|
||||
#
|
||||
# # if element.InitializeAsDisabled:
|
||||
# # element.TKCombo['state'] = 'disabled'
|
||||
# # if element.BackgroundColor is not None:
|
||||
# # element.TKCombo.configure(background=element.BackgroundColor)
|
||||
# element.TKCombo.pack(side=tk.LEFT, padx=element.Pad[0], pady=element.Pad[1])
|
||||
# if element.DefaultValue:
|
||||
# for i, v in enumerate(element.Values):
|
||||
# if v == element.DefaultValue:
|
||||
# element.TKCombo.current(i)
|
||||
# break
|
||||
# else:
|
||||
# element.TKCombo.current(0)
|
||||
# if element.ChangeSubmits:
|
||||
# element.TKCombo.bind('<<ComboboxSelected>>', element.ComboboxSelectHandler)
|
||||
# if element.Readonly:
|
||||
# element.TKCombo['state'] = 'readonly'
|
||||
# if element.Disabled is True: # note overrides readonly if disabled
|
||||
# element.TKCombo['state'] = 'disabled'
|
||||
# if element.Tooltip is not None:
|
||||
# element.TooltipObject = ToolTip(element.TKCombo, text=element.Tooltip, timeout=DEFAULT_TOOLTIP_TIME)
|
||||
|
||||
# ------------------------- OPTION MENU (Like ComboBox but different) element ------------------------- #
|
||||
elif element_type == ELEM_TYPE_INPUT_OPTION_MENU:
|
||||
pass
|
||||
# max_line_len = max([len(str(l)) for l in element.Values])
|
||||
# if auto_size_text is False:
|
||||
# width = element_size[0]
|
||||
# else:
|
||||
# width = max_line_len
|
||||
# element.TKStringVar = tk.StringVar()
|
||||
# default = element.DefaultValue if element.DefaultValue else element.Values[0]
|
||||
# element.TKStringVar.set(default)
|
||||
# element.TKOptionMenu = tk.OptionMenu(tk_row_frame, element.TKStringVar, *element.Values)
|
||||
# element.TKOptionMenu.config(highlightthickness=0, font=font, width=width)
|
||||
# element.TKOptionMenu.config(borderwidth=border_depth)
|
||||
# if element.BackgroundColor is not None and element.BackgroundColor != COLOR_SYSTEM_DEFAULT:
|
||||
# element.TKOptionMenu.configure(background=element.BackgroundColor)
|
||||
# if element.TextColor != COLOR_SYSTEM_DEFAULT and element.TextColor is not None:
|
||||
# element.TKOptionMenu.configure(fg=element.TextColor)
|
||||
# element.TKOptionMenu.pack(side=tk.LEFT, padx=element.Pad[0], pady=element.Pad[1])
|
||||
# if element.Disabled == True:
|
||||
# element.TKOptionMenu['state'] = 'disabled'
|
||||
# if element.Tooltip is not None:
|
||||
# element.TooltipObject = ToolTip(element.TKOptionMenu, text=element.Tooltip,
|
||||
# timeout=DEFAULT_TOOLTIP_TIME)
|
||||
# # ------------------------- LISTBOX element ------------------------- #
|
||||
# ------------------------- LISTBOX element ------------------------- #
|
||||
elif element_type == ELEM_TYPE_INPUT_LISTBOX:
|
||||
element = element # type: Listbox
|
||||
element.Widget = remi.gui.ListView.new_from_list(element.Values)
|
||||
do_font_and_color(element.Widget)
|
||||
if element.ChangeSubmits:
|
||||
element.Widget.onselection.connect(element.ChangedCallback)
|
||||
tk_row_frame.append(element.Widget)
|
||||
# max_line_len = max([len(str(l)) for l in element.Values]) if len(element.Values) != 0 else 0
|
||||
# if auto_size_text is False:
|
||||
|
@ -4318,7 +4267,12 @@ def PackFormIntoFrame(form, containing_frame, toplevel_form):
|
|||
# timeout=DEFAULT_TOOLTIP_TIME)
|
||||
# ------------------------- INPUT MULTI LINE element ------------------------- #
|
||||
elif element_type == ELEM_TYPE_INPUT_MULTILINE:
|
||||
pass
|
||||
element = element # type: Multiline
|
||||
element.Widget = remi.gui.TextInput(single_line=False, hint=element.DefaultText)
|
||||
do_font_and_color(element.Widget)
|
||||
if element.ChangeSubmits:
|
||||
element.Widget.onkeydown.connect(element.InputTextCallback)
|
||||
tk_row_frame.append(element.Widget)
|
||||
# default_text = element.DefaultText
|
||||
# width, height = element_size
|
||||
# element.TKText = tk.scrolledtext.ScrolledText(tk_row_frame, width=width, height=height, wrap='word',
|
||||
|
@ -4341,12 +4295,23 @@ def PackFormIntoFrame(form, containing_frame, toplevel_form):
|
|||
# element.TKText['state'] = 'disabled'
|
||||
# if element.Tooltip is not None:
|
||||
# element.TooltipObject = ToolTip(element.TKText, text=element.Tooltip, timeout=DEFAULT_TOOLTIP_TIME)
|
||||
# ------------------------- OUTPUT MULTI LINE element ------------------------- #
|
||||
elif element_type == ELEM_TYPE_MULTILINE_OUTPUT:
|
||||
element = element # type: MultilineOutput
|
||||
element.Widget = remi.gui.TextInput(single_line=False)
|
||||
element.Disabled = True
|
||||
if element.DefaultText:
|
||||
element.Widget.set_value(element.DefaultText)
|
||||
do_font_and_color(element.Widget)
|
||||
tk_row_frame.append(element.Widget)
|
||||
# ------------------------- INPUT CHECKBOX element ------------------------- #
|
||||
elif element_type == ELEM_TYPE_INPUT_CHECKBOX:
|
||||
element = element # type: Checkbox
|
||||
element.Widget = remi.gui.CheckBoxLabel(element.Text)
|
||||
if element.InitialState:
|
||||
element.Widget.set_value(element.InitialState)
|
||||
if element.ChangeSubmits:
|
||||
element.Widget.onchange.connect(element.ChangedCallback)
|
||||
do_font_and_color(element.Widget)
|
||||
tk_row_frame.append(element.Widget)
|
||||
|
||||
|
@ -4425,9 +4390,16 @@ def PackFormIntoFrame(form, containing_frame, toplevel_form):
|
|||
# element.TKRadio.pack(side=tk.LEFT, padx=element.Pad[0], pady=element.Pad[1])
|
||||
# if element.Tooltip is not None:
|
||||
# element.TooltipObject = ToolTip(element.TKRadio, text=element.Tooltip, timeout=DEFAULT_TOOLTIP_TIME)
|
||||
# ------------------------- INPUT SPIN Box element ------------------------- #
|
||||
# ------------------------- INPUT SPIN element ------------------------- #
|
||||
elif element_type == ELEM_TYPE_INPUT_SPIN:
|
||||
pass
|
||||
element = element # type: Spin
|
||||
element.Widget = remi.gui.SpinBox(50, 0, 100)
|
||||
if element.DefaultValue is not None:
|
||||
element.Widget.set_value(element.DefaultValue)
|
||||
do_font_and_color(element.Widget)
|
||||
if element.ChangeSubmits:
|
||||
element.Widget.onchange.connect(element.ChangedCallback)
|
||||
tk_row_frame.append(element.Widget)
|
||||
# width, height = element_size
|
||||
# width = 0 if auto_size_text else element_size[0]
|
||||
# element.TKStringVar = tk.StringVar()
|
||||
|
@ -4640,10 +4612,18 @@ def PackFormIntoFrame(form, containing_frame, toplevel_form):
|
|||
# if element.Tooltip is not None:
|
||||
# element.TooltipObject = ToolTip(element.TKNotebook, text=element.Tooltip,
|
||||
# timeout=DEFAULT_TOOLTIP_TIME)
|
||||
# ------------------------- SLIDER Box element ------------------------- #
|
||||
# ------------------------- SLIDER element ------------------------- #
|
||||
elif element_type == ELEM_TYPE_INPUT_SLIDER:
|
||||
pass
|
||||
# slider_length = element_size[0] * CharWidthInPixels()
|
||||
element = element # type: Slider
|
||||
element.Widget = remi.gui.Slider(layout_orientation = remi.gui.Widget.LAYOUT_HORIZONTAL, default_value=element.DefaultValue, min=element.Range[0], max=element.Range[1],step=element.Resolution)
|
||||
if element.DefaultValue:
|
||||
element.Widget.set_value(element.DefaultValue)
|
||||
# if element.Orientation.startswith('v'):
|
||||
# element.Widget.layout_orientation = remi.gui.Widget.LAYOUT_VERTICAL
|
||||
do_font_and_color(element.Widget)
|
||||
if element.ChangeSubmits:
|
||||
element.Widget.onchange.connect(element.SliderCallback)
|
||||
tk_row_frame.append(element.Widget) # slider_length = element_size[0] * CharWidthInPixels()
|
||||
# slider_width = element_size[1]
|
||||
# element.TKIntVar = tk.IntVar()
|
||||
# element.TKIntVar.set(element.DefaultValue)
|
||||
|
@ -6499,25 +6479,52 @@ def PopupGetText(message, default_text='', password_char='', size=(None, None),
|
|||
|
||||
def main():
|
||||
ChangeLookAndFeel('GreenTan' )
|
||||
# SetOptions(background_color='blue', text_element_background_color='blue', text_color='white')
|
||||
layout = [[Text('You are running the PySimpleGUI.py file itself', font='Courier 20')],
|
||||
[Text('You should be importing it rather than running it', size=(60, 1))],
|
||||
[Text('Here is your sample window....')],
|
||||
[Text('Source Folder', justification='right', size=(40,1)), InputText('Source', focus=True, disabled=True),
|
||||
FolderBrowse()],
|
||||
[Text('Destination Folder', justification='right', size=(40,1)), InputText('Dest'), FolderBrowse()],
|
||||
[Ok(), Cancel(disabled=True), Exit()]]
|
||||
|
||||
window = Window('Demo window..', font='Arial 18').Layout(layout)
|
||||
# Popup('Popup Test')
|
||||
|
||||
# SetOptions(background_color='blue', text_element_background_color='blue', text_color='white')
|
||||
# layout = [[Text('You are running the PySimpleGUI.py file itself', font='Any 25', size=(60,1), tooltip='My tooltip!')],
|
||||
# [Text('You should be importing it rather than running it', size=(60, 1))],
|
||||
# [Text('Here is your sample window....')],
|
||||
# [Text('Source Folder', justification='right', size=(40,1)), InputText('Source', focus=True, disabled=True),
|
||||
# FolderBrowse()],
|
||||
# [Text('Destination Folder', justification='right', size=(40,1)), InputText('Dest'), FolderBrowse()],
|
||||
# [Ok(), Cancel(disabled=True), Exit(tooltip='Exit button'), Button('Hidden Button', visible=False)]]
|
||||
|
||||
layout = [
|
||||
[Text('PySimpleGUIWeb Demo of Working Elements', tooltip='text', font=('Comic sans ms', 20), text_color='red', enable_events=True, key='_PySimpleGUIWeb_')],
|
||||
[T('Current Time '), Text('Text', key='_TEXT_', 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))],
|
||||
[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_')],
|
||||
[Checkbox('Checkbox 1', enable_events=True, key='_CB1_'), Checkbox('Checkbox 2', default=True, key='_CB2_', enable_events=True)],
|
||||
[Combo(values=['Combo 1', 'Combo 2', 'Combo 3'], default_value='Combo 2', key='_COMBO_', enable_events=True,
|
||||
readonly=False, tooltip='Combo box', disabled=False, size=(12, 1))],
|
||||
[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)],
|
||||
[Spin(values=(1, 2, 3), initial_value='2', size=(4, 1), key='_SPIN_', enable_events=True)],
|
||||
[OK(), Button('Hidden', visible=False), Button('Exit', button_color=('white', 'red'))]
|
||||
]
|
||||
|
||||
|
||||
window = Window('PySimpleGUIWeb Window', font='Arial 18', default_element_size=(12,1)).Layout(layout)
|
||||
|
||||
start_time = datetime.datetime.now()
|
||||
while True:
|
||||
event, values = window.Read()
|
||||
print(event, values)
|
||||
event, values = window.Read(timeout=0)
|
||||
window.Element('_TEXT_').Update(str(datetime.datetime.now()))
|
||||
window.Element('_TEXT_UPTIME_').Update(str(datetime.datetime.now()-start_time))
|
||||
print(event, values) if event != TIMEOUT_KEY else None
|
||||
if event in (None, 'Exit'):
|
||||
break
|
||||
elif event == 'OK':
|
||||
window.Element('_MULTIOUT_').Update('You clicked the OK button', append=True)
|
||||
elif event != TIMEOUT_KEY:
|
||||
window.Element('_MULTIOUT_').Update(str(event) + '\n'+str(values), append=True)
|
||||
window.Close()
|
||||
|
||||
|
||||
if __name__ == '__main__':
|
||||
main()
|
||||
print('back from main')
|
||||
exit(69)
|
||||
|
|
|
@ -1,20 +1,22 @@
|
|||
|
||||
![pysimplegui_logo](https://user-images.githubusercontent.com/13696193/43165867-fe02e3b2-8f62-11e8-9fd0-cc7c86b11772.png)
|
||||
|
||||
![Downloads](http://pepy.tech/badge/pysimpleguiweb)]
|
||||
![Downloads](http://pepy.tech/badge/pysimpleguiweb)
|
||||
|
||||
|
||||
![Awesome Meter](https://img.shields.io/badge/Awesome_meter-1000-yellow.svg)
|
||||
![Awesome Meter](https://img.shields.io/badge/Awesome_meter-10,000-yellow.svg)
|
||||
|
||||
![Python Version](https://img.shields.io/badge/Python-3.x-yellow.svg)
|
||||
|
||||
![Python Version](https://img.shields.io/badge/PySimpleGUIWeb_Version-0.3.0-orange.svg?longCache=true&style=for-the-badge)
|
||||
![Python Version](https://img.shields.io/badge/PySimpleGUIWeb_-0.4.0-orange.svg?longCache=true&style=for-the-badge)
|
||||
|
||||
|
||||
|
||||
# PySimpleGUIWeb
|
||||
|
||||
PySimpleGUI running in your web browser
|
||||
PySimpleGUI running in your web browser!
|
||||
|
||||
Your source code will work on tkinter, Qt, WxPython and now in a browser (thanks to Remi)
|
||||
|
||||
## Primary PySimpleGUI Documentation
|
||||
|
||||
|
@ -26,9 +28,18 @@ This Readme is for information ***specific to*** the Web port of PySimpleGUI.
|
|||
|
||||
PySimpleGUIWeb enables you to run your PySimpleGUI programs in your web browser. It utilizes a package called Remi to achieve this amazing package.
|
||||
|
||||
At the moment (22-Jan-2019) the port has barely begun but it's far enough along to see that it's going to work. The Text, Input Text and Button elements are "functional". You can run simple PySimpleGUI programs and they actually WORK correctly.
|
||||
At the moment (Jan 26 2019) these elements are operational:
|
||||
* Text
|
||||
* Single line text input
|
||||
* Multiline Input
|
||||
* Multiline Output
|
||||
* Listbox
|
||||
* Combobox
|
||||
* Checkbox
|
||||
* Slider
|
||||
* Spinner (numbers only...hardcoded to 0 to 100)
|
||||
|
||||
## Engineering Pre-Release Version 0.2.0
|
||||
## Engineering Pre-Release Version 0.4.0
|
||||
|
||||
[Announcements of Latest Developments](https://github.com/MikeTheWatchGuy/PySimpleGUI/issues/142)
|
||||
|
||||
|
@ -43,14 +54,14 @@ Installation is quite simple:
|
|||
|
||||
Should this not work, you can copy and paste the file PySimpleGUIWeb.py into your application folder.
|
||||
|
||||
## Using
|
||||
## Using PySimpleGUIWeb
|
||||
|
||||
There are a lot of examples in the PySimpleGUI Cookbook as well as on the GitHub site. At the moment very few will work due to the limited number of features of the 0.1.0 release. It shouldn't be too long before they'll work.
|
||||
|
||||
To use PySimpleGUIWeb you need to import it:
|
||||
`import PySimpleGUIWeb as sg`
|
||||
|
||||
From there follow the code examples in the Coookbook and the Demo Programs. The only difference in those programs is the import statement. The remainder of the code should work without modification.
|
||||
From there follow the code examples in the Cookbook and the Demo Programs. The only difference in those programs is the import statement. The remainder of the code should work without modification.
|
||||
|
||||
|
||||
## Requirements
|
||||
|
@ -63,10 +74,9 @@ You can learn more about Remi on its homepage.
|
|||
|
||||
https://github.com/dddomodossola/remi
|
||||
|
||||
PySimpleGUIWeb runs only on Python 3. Legacy Python is not supported.
|
||||
|
||||
|
||||
PySimpleGUIWeb runs only on Python 3. Legacy Python (2.7) is not supported.
|
||||
|
||||
|
||||
## What Works
|
||||
|
||||
* Text Element
|
||||
|
@ -115,6 +125,30 @@ Day 2 of development brings fonts, sizes, and colors...
|
|||
* Listbox Element
|
||||
* Element padding for all elements
|
||||
|
||||
## 0.4.0 PySimpleGUIWeb 26-Jan-2019
|
||||
|
||||
Functioning Elements
|
||||
* Text
|
||||
* Single line text input
|
||||
* Multiline Input
|
||||
* Multiline Output
|
||||
* Listbox
|
||||
* Combobox
|
||||
* Checkbox
|
||||
* Slider
|
||||
* Spinner (numbers only...hardcoded to 0 to 100)
|
||||
|
||||
New features
|
||||
* Tooltips for all elements (so cool this works)
|
||||
* Input Text events
|
||||
* Text clicked event
|
||||
* Listbox selected event
|
||||
* Combobox selected event
|
||||
* Checkbox Update
|
||||
* Disable parameter for all elements
|
||||
* Window.Close shuts down the server
|
||||
* Enabled exceptions during packing operation
|
||||
* New test harness exercises all element types
|
||||
|
||||
|
||||
|
||||
|
@ -128,5 +162,6 @@ Day 2 of development brings fonts, sizes, and colors...
|
|||
|
||||
# Acknowledgments
|
||||
<!--stackedit_data:
|
||||
eyJoaXN0b3J5IjpbLTExNjA2ODQzMzldfQ==
|
||||
eyJoaXN0b3J5IjpbLTEwNTcxMDM2NDMsMTIxMzM1MjYzNiwtMT
|
||||
E2MDY4NDMzOV19
|
||||
-->
|
Loading…
Reference in New Issue