commit
3bb8380f40
|
@ -12,6 +12,8 @@ from queue import Queue
|
||||||
# from remi import start, App
|
# from remi import start, App
|
||||||
import remi
|
import remi
|
||||||
import logging
|
import logging
|
||||||
|
import traceback
|
||||||
|
|
||||||
|
|
||||||
g_time_start = 0
|
g_time_start = 0
|
||||||
g_time_end = 0
|
g_time_end = 0
|
||||||
|
@ -229,9 +231,11 @@ ELEM_TYPE_INPUT_COMBO = 'combo'
|
||||||
ELEM_TYPE_INPUT_OPTION_MENU = 'option menu'
|
ELEM_TYPE_INPUT_OPTION_MENU = 'option menu'
|
||||||
ELEM_TYPE_INPUT_RADIO = 'radio'
|
ELEM_TYPE_INPUT_RADIO = 'radio'
|
||||||
ELEM_TYPE_INPUT_MULTILINE = 'multiline'
|
ELEM_TYPE_INPUT_MULTILINE = 'multiline'
|
||||||
|
ELEM_TYPE_MULTILINE_OUTPUT = 'multioutput'
|
||||||
ELEM_TYPE_INPUT_CHECKBOX = 'checkbox'
|
ELEM_TYPE_INPUT_CHECKBOX = 'checkbox'
|
||||||
ELEM_TYPE_INPUT_SPIN = 'spind'
|
ELEM_TYPE_INPUT_SPIN = 'spin'
|
||||||
ELEM_TYPE_BUTTON = 'button'
|
ELEM_TYPE_BUTTON = 'button'
|
||||||
|
ELEM_TYPE_BUTTONMENU = 'buttonmenu'
|
||||||
ELEM_TYPE_IMAGE = 'image'
|
ELEM_TYPE_IMAGE = 'image'
|
||||||
ELEM_TYPE_CANVAS = 'canvas'
|
ELEM_TYPE_CANVAS = 'canvas'
|
||||||
ELEM_TYPE_FRAME = 'frame'
|
ELEM_TYPE_FRAME = 'frame'
|
||||||
|
@ -387,6 +391,12 @@ class Element():
|
||||||
return rc
|
return rc
|
||||||
return None
|
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):
|
def TextClickedHandler(self, event):
|
||||||
if self.Key is not None:
|
if self.Key is not None:
|
||||||
self.ParentForm.LastButtonClicked = self.Key
|
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,
|
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)
|
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):
|
def Update(self, value=None, disabled=None):
|
||||||
if disabled is True:
|
if disabled is True:
|
||||||
self.TKEntry['state'] = 'disabled'
|
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)
|
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):
|
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:
|
if values is not None:
|
||||||
|
@ -678,14 +688,14 @@ InputOptionMenu = OptionMenu
|
||||||
# Listbox #
|
# Listbox #
|
||||||
# ---------------------------------------------------------------------- #
|
# ---------------------------------------------------------------------- #
|
||||||
class Listbox(Element):
|
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,
|
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)):
|
||||||
text_color=None, key=None, pad=None, tooltip=None, visible=True, size_px=(None,None)):
|
"""
|
||||||
'''
|
|
||||||
Listbox Element
|
|
||||||
:param values:
|
:param values:
|
||||||
:param default_values:
|
:param default_values:
|
||||||
:param select_mode:
|
:param select_mode:
|
||||||
:param change_submits:
|
:param change_submits:
|
||||||
|
:param enable_events:
|
||||||
:param bind_return_key:
|
:param bind_return_key:
|
||||||
:param size:
|
:param size:
|
||||||
:param disabled:
|
:param disabled:
|
||||||
|
@ -696,7 +706,9 @@ class Listbox(Element):
|
||||||
:param key:
|
:param key:
|
||||||
:param pad:
|
:param pad:
|
||||||
:param tooltip:
|
:param tooltip:
|
||||||
'''
|
:param visible:
|
||||||
|
:param size_px:
|
||||||
|
"""
|
||||||
self.Values = values
|
self.Values = values
|
||||||
self.DefaultValues = default_values
|
self.DefaultValues = default_values
|
||||||
self.TKListbox = None
|
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,
|
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)
|
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):
|
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:
|
if values is not None:
|
||||||
self.Values = values
|
self.Values = values
|
||||||
|
@ -849,20 +856,21 @@ class Checkbox(Element):
|
||||||
background_color=background_color, text_color=self.TextColor, key=key, pad=pad,
|
background_color=background_color, text_color=self.TextColor, key=key, pad=pad,
|
||||||
tooltip=tooltip, visible=visible, size_px=size_px)
|
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):
|
def Get(self):
|
||||||
return self.WxCheckbox.GetValue()
|
return self.Widget.get_value()
|
||||||
|
|
||||||
def Update(self, value=None, disabled=None):
|
def Update(self, value=None, disabled=None):
|
||||||
if value is not None:
|
if value is not None:
|
||||||
try:
|
self.Widget.set_value(value)
|
||||||
self.WxCheckbox.SetValue(value)
|
|
||||||
self.InitialState = value
|
|
||||||
except:
|
|
||||||
pass
|
|
||||||
if disabled == True:
|
if disabled == True:
|
||||||
self.WxCheckbox.Disable()
|
self.Widget.set_enabled(False)
|
||||||
elif disabled == False:
|
elif disabled == False:
|
||||||
self.WxCheckbox.Enable()
|
self.Widget.set_enabled(True)
|
||||||
|
|
||||||
def __del__(self):
|
def __del__(self):
|
||||||
super().__del__()
|
super().__del__()
|
||||||
|
@ -882,9 +890,8 @@ Check = Checkbox
|
||||||
class Spin(Element):
|
class Spin(Element):
|
||||||
# Values = None
|
# Values = None
|
||||||
# TKSpinBox = None
|
# TKSpinBox = None
|
||||||
def __init__(self, values, initial_value=None, disabled=False, change_submits=False, size=(None, 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,
|
||||||
auto_size_text=None, font=None, background_color=None, text_color=None, key=None, pad=None,
|
tooltip=None, visible=True, size_px=(None,None)):
|
||||||
tooltip=None):
|
|
||||||
'''
|
'''
|
||||||
Spinner Element
|
Spinner Element
|
||||||
:param values:
|
:param values:
|
||||||
|
@ -901,50 +908,41 @@ class Spin(Element):
|
||||||
:param tooltip:
|
:param tooltip:
|
||||||
'''
|
'''
|
||||||
self.Values = values
|
self.Values = values
|
||||||
self.DefaultValue = initial_value
|
self.DefaultValue = initial_value or values[0]
|
||||||
self.ChangeSubmits = change_submits
|
self.ChangeSubmits = change_submits or enable_events
|
||||||
self.TKSpinBox = None
|
|
||||||
self.Disabled = disabled
|
self.Disabled = disabled
|
||||||
bg = background_color if background_color else DEFAULT_INPUT_ELEMENTS_COLOR
|
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
|
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,
|
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
|
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:
|
if values != None:
|
||||||
old_value = self.TKStringVar.get()
|
|
||||||
self.Values = values
|
self.Values = values
|
||||||
self.TKSpinBox.configure(values=values)
|
self.QT_Spinner.setStrings(values)
|
||||||
self.TKStringVar.set(old_value)
|
# self.QT_Spinner.setRange(self.Values[0], self.Values[1])
|
||||||
if value is not None:
|
if value is not None:
|
||||||
|
# self.QT_Spinner.setValue(value)
|
||||||
try:
|
try:
|
||||||
self.TKStringVar.set(value)
|
self.QT_Spinner.setValue(self.QT_Spinner.valueFromText(value))
|
||||||
|
self.DefaultValue = value
|
||||||
except:
|
except:
|
||||||
pass
|
pass
|
||||||
self.DefaultValue = value
|
|
||||||
if disabled == True:
|
if disabled == True:
|
||||||
self.TKSpinBox.configure(state='disabled')
|
self.QT_Spinner.setDisabled(True)
|
||||||
elif disabled == False:
|
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):
|
def Get(self):
|
||||||
# first, get the results table built
|
return self.Widget.get_value()
|
||||||
# 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 __del__(self):
|
def __del__(self):
|
||||||
try:
|
|
||||||
self.TKSpinBox.__del__()
|
|
||||||
except:
|
|
||||||
pass
|
|
||||||
super().__del__()
|
super().__del__()
|
||||||
|
|
||||||
|
|
||||||
|
@ -953,9 +951,8 @@ class Spin(Element):
|
||||||
# ---------------------------------------------------------------------- #
|
# ---------------------------------------------------------------------- #
|
||||||
class Multiline(Element):
|
class Multiline(Element):
|
||||||
def __init__(self, default_text='', enter_submits=False, disabled=False, autoscroll=False, size=(None, None),
|
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,
|
auto_size_text=None, background_color=None, text_color=None, change_submits=False, enable_events=False, do_not_clear=False,
|
||||||
key=None, focus=False,
|
key=None, focus=False, font=None, pad=None, tooltip=None, visible=True, size_px=(None,None)):
|
||||||
font=None, pad=None, tooltip=None):
|
|
||||||
'''
|
'''
|
||||||
Multiline Element
|
Multiline Element
|
||||||
:param default_text:
|
:param default_text:
|
||||||
|
@ -981,42 +978,122 @@ class Multiline(Element):
|
||||||
fg = text_color if text_color is not None else DEFAULT_INPUT_TEXT_COLOR
|
fg = text_color if text_color is not None else DEFAULT_INPUT_TEXT_COLOR
|
||||||
self.Autoscroll = autoscroll
|
self.Autoscroll = autoscroll
|
||||||
self.Disabled = disabled
|
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,
|
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)
|
text_color=fg, key=key, pad=pad, tooltip=tooltip, font=font or DEFAULT_FONT, visible=visible, size_px=size_px)
|
||||||
return
|
return
|
||||||
|
|
||||||
def Update(self, value=None, disabled=None, append=False, font=None, text_color=None, background_color=None):
|
def InputTextCallback(self, widget:remi.Widget, value, keycode):
|
||||||
if value is not None:
|
# print(f'text widget value = {widget.get_value()}')
|
||||||
try:
|
self.ParentForm.LastButtonClicked = chr(int(keycode))
|
||||||
if not append:
|
self.ParentForm.MessageQueue.put(self.ParentForm.LastButtonClicked)
|
||||||
self.TKText.delete('1.0', tk.END)
|
|
||||||
self.TKText.insert(tk.END, value)
|
def Update(self, value=None, disabled=None, append=False, background_color=None, text_color=None, font=None, visible=None):
|
||||||
except:
|
if value is not None and not append:
|
||||||
pass
|
self.Widget.set_value(value)
|
||||||
self.DefaultText = value
|
elif value is not None and append:
|
||||||
if self.Autoscroll:
|
text = self.Widget.get_value() + str(value)
|
||||||
self.TKText.see(tk.END)
|
self.Widget.set_value(text)
|
||||||
if disabled == True:
|
# if background_color is not None:
|
||||||
self.TKText.configure(state='disabled')
|
# self.WxTextCtrl.SetBackgroundColour(background_color)
|
||||||
elif disabled == False:
|
# if text_color is not None:
|
||||||
self.TKText.configure(state='normal')
|
# self.WxTextCtrl.SetForegroundColour(text_color)
|
||||||
if background_color is not None:
|
# if font is not None:
|
||||||
self.TKText.configure(background=background_color)
|
# self.WxTextCtrl.SetFont(font)
|
||||||
if text_color is not None:
|
# if disabled:
|
||||||
self.TKText.configure(fg=text_color)
|
# self.WxTextCtrl.Enable(True)
|
||||||
if font is not None:
|
# elif disabled is False:
|
||||||
self.TKText.configure(font=font)
|
# 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):
|
def Get(self):
|
||||||
return self.TKText.get(1.0, tk.END)
|
self.WxTextCtrl.GetValue()
|
||||||
|
|
||||||
def SetFocus(self):
|
def SetFocus(self):
|
||||||
try:
|
self.WxTextCtrl.SetFocus()
|
||||||
self.TKText.focus_set()
|
|
||||||
except:
|
|
||||||
pass
|
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):
|
def __del__(self):
|
||||||
super().__del__()
|
super().__del__()
|
||||||
|
@ -2101,26 +2178,23 @@ class TabGroup(Element):
|
||||||
# ---------------------------------------------------------------------- #
|
# ---------------------------------------------------------------------- #
|
||||||
class Slider(Element):
|
class Slider(Element):
|
||||||
def __init__(self, range=(None, None), default_value=None, resolution=None, tick_interval=None, orientation=None,
|
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,
|
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):
|
background_color=None, text_color=None, key=None, pad=None, tooltip=None, visible=True, size_px=(None,None)):
|
||||||
'''
|
"""
|
||||||
Slider Element
|
|
||||||
:param range:
|
:param range:
|
||||||
:param default_value:
|
:param default_value:
|
||||||
:param resolution:
|
:param resolution:
|
||||||
|
:param tick_interval:
|
||||||
:param orientation:
|
:param orientation:
|
||||||
:param border_width:
|
:param border_width:
|
||||||
:param relief:
|
:param relief:
|
||||||
:param change_submits:
|
:param change_submits:
|
||||||
|
:param enable_events:
|
||||||
:param disabled:
|
:param disabled:
|
||||||
:param size:
|
:param visible:
|
||||||
:param font:
|
:param size_px:
|
||||||
:param background_color:
|
"""
|
||||||
:param text_color:
|
|
||||||
:param key:
|
|
||||||
:param pad:
|
|
||||||
:param tooltip:
|
|
||||||
'''
|
|
||||||
self.TKScale = None
|
self.TKScale = None
|
||||||
self.Range = (1, 10) if range == (None, None) else range
|
self.Range = (1, 10) if range == (None, None) else range
|
||||||
self.DefaultValue = self.Range[0] if default_value is None else default_value
|
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.BorderWidth = border_width if border_width else DEFAULT_SLIDER_BORDER_WIDTH
|
||||||
self.Relief = relief if relief else DEFAULT_SLIDER_RELIEF
|
self.Relief = relief if relief else DEFAULT_SLIDER_RELIEF
|
||||||
self.Resolution = 1 if resolution is None else resolution
|
self.Resolution = 1 if resolution is None else resolution
|
||||||
self.ChangeSubmits = change_submits
|
self.ChangeSubmits = change_submits or enable_events
|
||||||
self.Disabled = disabled
|
self.Disabled = disabled
|
||||||
self.TickInterval = tick_interval
|
self.TickInterval = tick_interval
|
||||||
temp_size = size
|
temp_size = size
|
||||||
if temp_size == (None, None):
|
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,
|
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
|
return
|
||||||
|
|
||||||
def Update(self, value=None, range=(None, None), disabled=None):
|
def Update(self, value=None, range=(None, None), disabled=None):
|
||||||
|
@ -2153,21 +2230,15 @@ class Slider(Element):
|
||||||
elif disabled == False:
|
elif disabled == False:
|
||||||
self.TKScale['state'] = 'normal'
|
self.TKScale['state'] = 'normal'
|
||||||
|
|
||||||
def SliderChangedHandler(self, event):
|
def SliderCallback(self, widget:remi.Widget, value):
|
||||||
# first, get the results table built
|
self.ParentForm.LastButtonClicked = self.Key if self.Key is not None else ''
|
||||||
# modify the Results table in the parent FlexForm object
|
self.ParentForm.MessageQueue.put(self.ParentForm.LastButtonClicked)
|
||||||
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 __del__(self):
|
def __del__(self):
|
||||||
super().__del__()
|
super().__del__()
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
#
|
#
|
||||||
# ---------------------------------------------------------------------- #
|
# ---------------------------------------------------------------------- #
|
||||||
# Column #
|
# Column #
|
||||||
|
@ -2544,6 +2615,7 @@ class Window:
|
||||||
highest_level_app = None
|
highest_level_app = None
|
||||||
stdout_is_rerouted = False
|
stdout_is_rerouted = False
|
||||||
stdout_location = None
|
stdout_location = None
|
||||||
|
port_number = 6900
|
||||||
|
|
||||||
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),
|
||||||
|
@ -2763,22 +2835,18 @@ class Window:
|
||||||
# print("** REALTIME PROBLEM FOUND **", results)
|
# print("** REALTIME PROBLEM FOUND **", results)
|
||||||
# print('****************** CALLING MESSAGE QUEUE GET ***********************')
|
# print('****************** CALLING MESSAGE QUEUE GET ***********************')
|
||||||
self.CurrentlyRunningMainloop = True
|
self.CurrentlyRunningMainloop = True
|
||||||
if timeout is not None and timeout != 0:
|
if timeout is not None:
|
||||||
try:
|
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
|
except: # timeout
|
||||||
self.LastButtonClicked = timeout_key
|
self.LastButtonClicked = timeout_key
|
||||||
elif timeout == 0:
|
|
||||||
try:
|
|
||||||
self.LastButtonClicked = self.MessageQueue.get_nowait()
|
|
||||||
except:
|
|
||||||
self.LastButtonClicked = timeout_key
|
|
||||||
else:
|
else:
|
||||||
self.LastButtonClicked = self.MessageQueue.get()
|
self.LastButtonClicked = self.MessageQueue.get()
|
||||||
|
# print(f'Got event {self.LastButtonClicked}')
|
||||||
# print('--------------------- BACK FROM MESSAGE QUEUE GET ----------------------')
|
# print('--------------------- BACK FROM MESSAGE QUEUE GET ----------------------')
|
||||||
|
|
||||||
results = BuildResults(self, False, self)
|
results = BuildResults(self, False, self)
|
||||||
# print('Results = ', results)
|
|
||||||
return results
|
return results
|
||||||
# print(f'In main {self.Title}')
|
# print(f'In main {self.Title}')
|
||||||
################################# CALL GUWxTextCtrlI MAINLOOP ############################
|
################################# CALL GUWxTextCtrlI MAINLOOP ############################
|
||||||
|
@ -2815,7 +2883,6 @@ class Window:
|
||||||
# print("*** Faking timeout ***")
|
# print("*** Faking timeout ***")
|
||||||
# self.ReturnValues = self.TimeoutKey, self.ReturnValues[1] # fake a timeout
|
# self.ReturnValues = self.TimeoutKey, self.ReturnValues[1] # fake a timeout
|
||||||
# return self.ReturnValues
|
# return self.ReturnValues
|
||||||
return None, None
|
|
||||||
|
|
||||||
def _ReadNonBlocking(self):
|
def _ReadNonBlocking(self):
|
||||||
if self.TKrootDestroyed:
|
if self.TKrootDestroyed:
|
||||||
|
@ -3001,7 +3068,8 @@ class Window:
|
||||||
|
|
||||||
def Close(self):
|
def Close(self):
|
||||||
self.App.close()
|
self.App.close()
|
||||||
|
self.App.server.server_starter_instance._alive = False
|
||||||
|
self.App.server.server_starter_instance._sserver.shutdown()
|
||||||
if self.TKrootDestroyed:
|
if self.TKrootDestroyed:
|
||||||
return
|
return
|
||||||
# try:
|
# try:
|
||||||
|
@ -3112,6 +3180,7 @@ class Window:
|
||||||
|
|
||||||
|
|
||||||
def remi_thread(self):
|
def remi_thread(self):
|
||||||
|
logging.getLogger('remi').setLevel(logging.WARNING)
|
||||||
logging.getLogger('remi').disabled = True
|
logging.getLogger('remi').disabled = True
|
||||||
logging.getLogger('remi.server.ws').disabled = True
|
logging.getLogger('remi.server.ws').disabled = True
|
||||||
logging.getLogger('remi.server').disabled = True
|
logging.getLogger('remi.server').disabled = True
|
||||||
|
@ -3122,8 +3191,15 @@ class Window:
|
||||||
# logging.getLogger('remi').setLevel(level=logging.CRITICAL)
|
# logging.getLogger('remi').setLevel(level=logging.CRITICAL)
|
||||||
# logging.getLogger('remi').disabled = True
|
# logging.getLogger('remi').disabled = True
|
||||||
# logging.disable(logging.CRITICAL)
|
# 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)
|
# s = remi.server.StandaloneServer(self.MyApp, width=1100, height=600)
|
||||||
self.MessageQueue.put(None)
|
# 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):
|
class MyApp(remi.App):
|
||||||
|
@ -3142,33 +3218,29 @@ class Window:
|
||||||
wid.style['align-items'] = 'baseline'
|
wid.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
|
wid.style['background-color'] = self.window.BackgroundColor
|
||||||
|
try:
|
||||||
PackFormIntoFrame(self.window, wid, self.window)
|
PackFormIntoFrame(self.window, wid, self.window)
|
||||||
#
|
except:
|
||||||
# lbl = remi.gui.Label("Close or reload the page, the console thread will stop automatically.")
|
print('* ERROR PACKING FORM *')
|
||||||
# wid.append(lbl)
|
print(traceback.format_exc())
|
||||||
# self.bt = remi.gui.Button('Close')
|
|
||||||
# self.bt.onclick.connect(self.on_close_button)
|
|
||||||
# wid.append(self.bt)
|
|
||||||
|
|
||||||
|
|
||||||
# add the following 3 lines to your app and the on_window_close method to make the console close automatically
|
# 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 = 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)
|
wid.add_child("onunloadevent", tag)
|
||||||
# TODO: Send message that layout is complete
|
self.window.MessageQueue.put('Layout complete') # signal the main code that the layout is all done
|
||||||
|
return wid # returning the root widget
|
||||||
self.window.MessageQueue.put('Layout complete')
|
|
||||||
# returning the root widget
|
|
||||||
return wid
|
|
||||||
|
|
||||||
|
|
||||||
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.window.MessageQueue.put(None)
|
|
||||||
self.close()
|
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
|
FlexForm = Window
|
||||||
|
|
||||||
|
@ -3184,8 +3256,11 @@ def element_callback_quit_mainloop(element):
|
||||||
element.ParentForm.LastButtonClicked = element.Key
|
element.ParentForm.LastButtonClicked = element.Key
|
||||||
else:
|
else:
|
||||||
element.ParentForm.LastButtonClicked = ''
|
element.ParentForm.LastButtonClicked = ''
|
||||||
element.ParentForm.FormRemainedOpen = True
|
try:
|
||||||
element.ParentForm.LastButtonClicked = element.Key if element.Key is not None else element.ButtonText
|
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)
|
element.ParentForm.MessageQueue.put(element.ParentForm.LastButtonClicked)
|
||||||
|
|
||||||
|
|
||||||
|
@ -3628,22 +3703,14 @@ def BuildResultsForSubform(form, initialize_only, top_level_form):
|
||||||
# items = element.TKListbox.curselection()
|
# items = element.TKListbox.curselection()
|
||||||
# value = [element.Values[int(item)] for item in items]
|
# value = [element.Values[int(item)] for item in items]
|
||||||
elif element.Type == ELEM_TYPE_INPUT_SPIN:
|
elif element.Type == ELEM_TYPE_INPUT_SPIN:
|
||||||
try:
|
element = element # type: Spin
|
||||||
value = element.TKStringVar.get()
|
value = element.Widget.get_value()
|
||||||
except:
|
|
||||||
value = 0
|
|
||||||
elif element.Type == ELEM_TYPE_INPUT_SLIDER:
|
elif element.Type == ELEM_TYPE_INPUT_SLIDER:
|
||||||
try:
|
element = element # type: Slider
|
||||||
value = element.TKIntVar.get()
|
value = element.Widget.get_value()
|
||||||
except:
|
|
||||||
value = 0
|
|
||||||
elif element.Type == ELEM_TYPE_INPUT_MULTILINE:
|
elif element.Type == ELEM_TYPE_INPUT_MULTILINE:
|
||||||
try:
|
element = element # type: Multiline
|
||||||
value = element.TKText.get(1.0, tk.END)
|
value = element.Widget.get_value()
|
||||||
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
|
|
||||||
elif element.Type == ELEM_TYPE_TAB_GROUP:
|
elif element.Type == ELEM_TYPE_TAB_GROUP:
|
||||||
try:
|
try:
|
||||||
value = element.TKNotebook.tab(element.TKNotebook.index('current'))['text']
|
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)
|
widget.style['margin'] = '{}px {}px {}px {}px'.format(*full_element_pad)
|
||||||
if element.Disabled:
|
if element.Disabled:
|
||||||
widget.set_enabled(False)
|
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)
|
# widget.SetMinSize(element_size)
|
||||||
# if element.Disabled:
|
# if element.Disabled:
|
||||||
|
@ -3982,8 +4053,6 @@ def PackFormIntoFrame(form, containing_frame, toplevel_form):
|
||||||
else:
|
else:
|
||||||
full_element_pad[0], full_element_pad[2] = elementpad[1]
|
full_element_pad[0], full_element_pad[2] = elementpad[1]
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
# ------------------------- COLUMN element ------------------------- #
|
# ------------------------- COLUMN element ------------------------- #
|
||||||
if element_type == ELEM_TYPE_COLUMN:
|
if element_type == ELEM_TYPE_COLUMN:
|
||||||
pass
|
pass
|
||||||
|
@ -4022,55 +4091,11 @@ def PackFormIntoFrame(form, containing_frame, toplevel_form):
|
||||||
element.Widget.style['text-align'] = 'center'
|
element.Widget.style['text-align'] = 'center'
|
||||||
elif element.Justification.startswith('r'):
|
elif element.Justification.startswith('r'):
|
||||||
element.Widget.style['text-align'] = 'right'
|
element.Widget.style['text-align'] = 'right'
|
||||||
|
if element.ClickSubmits:
|
||||||
|
element.Widget.onclick.connect(element.ChangedCallback)
|
||||||
tk_row_frame.append(element.Widget)
|
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 ------------------------- #
|
# ------------------------- BUTTON element ------------------------- #
|
||||||
elif element_type == ELEM_TYPE_BUTTON:
|
elif element_type == ELEM_TYPE_BUTTON:
|
||||||
element = element # type: Button
|
element = element # type: Button
|
||||||
|
@ -4153,18 +4178,15 @@ def PackFormIntoFrame(form, containing_frame, toplevel_form):
|
||||||
# if element.Tooltip is not None:
|
# if element.Tooltip is not None:
|
||||||
# element.TooltipObject = ToolTip(element.TKButton, text=element.Tooltip,
|
# element.TooltipObject = ToolTip(element.TKButton, text=element.Tooltip,
|
||||||
# timeout=DEFAULT_TOOLTIP_TIME)
|
# timeout=DEFAULT_TOOLTIP_TIME)
|
||||||
# # ------------------------- INPUT (Single Line) element ------------------------- #
|
# # ------------------------- INPUT element ------------------------- #
|
||||||
elif element_type == ELEM_TYPE_INPUT_TEXT:
|
elif element_type == ELEM_TYPE_INPUT_TEXT:
|
||||||
element = element # type: InputText
|
element = element # type: InputText
|
||||||
element.Widget = remi.gui.TextInput()
|
element.Widget = remi.gui.TextInput(hint=element.DefaultText)
|
||||||
if element.DefaultText:
|
|
||||||
element.Widget.set_value(element.DefaultText)
|
|
||||||
do_font_and_color(element.Widget)
|
do_font_and_color(element.Widget)
|
||||||
|
if element.ChangeSubmits:
|
||||||
|
element.Widget.onkeydown.connect(element.InputTextCallback)
|
||||||
tk_row_frame.append(element.Widget)
|
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 ""
|
# show = element.PasswordCharacter if element.PasswordCharacter else ""
|
||||||
# if element.Justification is not None:
|
# if element.Justification is not None:
|
||||||
# justification = element.Justification
|
# justification = element.Justification
|
||||||
|
@ -4196,93 +4218,20 @@ def PackFormIntoFrame(form, containing_frame, toplevel_form):
|
||||||
if element.DefaultValue is not None:
|
if element.DefaultValue is not None:
|
||||||
element.Widget.select_by_value(element.DefaultValue)
|
element.Widget.select_by_value(element.DefaultValue)
|
||||||
do_font_and_color(element.Widget)
|
do_font_and_color(element.Widget)
|
||||||
|
if element.ChangeSubmits:
|
||||||
|
element.Widget.onchange.connect(element.ChangedCallback)
|
||||||
tk_row_frame.append(element.Widget)
|
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 ------------------------- #
|
# ------------------------- OPTION MENU (Like ComboBox but different) element ------------------------- #
|
||||||
elif element_type == ELEM_TYPE_INPUT_OPTION_MENU:
|
elif element_type == ELEM_TYPE_INPUT_OPTION_MENU:
|
||||||
pass
|
pass
|
||||||
# max_line_len = max([len(str(l)) for l in element.Values])
|
# ------------------------- LISTBOX element ------------------------- #
|
||||||
# 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 ------------------------- #
|
|
||||||
elif element_type == ELEM_TYPE_INPUT_LISTBOX:
|
elif element_type == ELEM_TYPE_INPUT_LISTBOX:
|
||||||
element = element # type: Listbox
|
element = element # type: Listbox
|
||||||
element.Widget = remi.gui.ListView.new_from_list(element.Values)
|
element.Widget = remi.gui.ListView.new_from_list(element.Values)
|
||||||
do_font_and_color(element.Widget)
|
do_font_and_color(element.Widget)
|
||||||
|
if element.ChangeSubmits:
|
||||||
|
element.Widget.onselection.connect(element.ChangedCallback)
|
||||||
tk_row_frame.append(element.Widget)
|
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
|
# 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:
|
# if auto_size_text is False:
|
||||||
|
@ -4318,7 +4267,12 @@ def PackFormIntoFrame(form, containing_frame, toplevel_form):
|
||||||
# timeout=DEFAULT_TOOLTIP_TIME)
|
# timeout=DEFAULT_TOOLTIP_TIME)
|
||||||
# ------------------------- INPUT MULTI LINE element ------------------------- #
|
# ------------------------- INPUT MULTI LINE element ------------------------- #
|
||||||
elif element_type == ELEM_TYPE_INPUT_MULTILINE:
|
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
|
# default_text = element.DefaultText
|
||||||
# width, height = element_size
|
# width, height = element_size
|
||||||
# element.TKText = tk.scrolledtext.ScrolledText(tk_row_frame, width=width, height=height, wrap='word',
|
# 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'
|
# element.TKText['state'] = 'disabled'
|
||||||
# if element.Tooltip is not None:
|
# if element.Tooltip is not None:
|
||||||
# element.TooltipObject = ToolTip(element.TKText, text=element.Tooltip, timeout=DEFAULT_TOOLTIP_TIME)
|
# 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 ------------------------- #
|
# ------------------------- INPUT CHECKBOX element ------------------------- #
|
||||||
elif element_type == ELEM_TYPE_INPUT_CHECKBOX:
|
elif element_type == ELEM_TYPE_INPUT_CHECKBOX:
|
||||||
element = element # type: Checkbox
|
element = element # type: Checkbox
|
||||||
element.Widget = remi.gui.CheckBoxLabel(element.Text)
|
element.Widget = remi.gui.CheckBoxLabel(element.Text)
|
||||||
if element.InitialState:
|
if element.InitialState:
|
||||||
element.Widget.set_value(element.InitialState)
|
element.Widget.set_value(element.InitialState)
|
||||||
|
if element.ChangeSubmits:
|
||||||
|
element.Widget.onchange.connect(element.ChangedCallback)
|
||||||
do_font_and_color(element.Widget)
|
do_font_and_color(element.Widget)
|
||||||
tk_row_frame.append(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])
|
# element.TKRadio.pack(side=tk.LEFT, padx=element.Pad[0], pady=element.Pad[1])
|
||||||
# if element.Tooltip is not None:
|
# if element.Tooltip is not None:
|
||||||
# element.TooltipObject = ToolTip(element.TKRadio, text=element.Tooltip, timeout=DEFAULT_TOOLTIP_TIME)
|
# 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:
|
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, height = element_size
|
||||||
# width = 0 if auto_size_text else element_size[0]
|
# width = 0 if auto_size_text else element_size[0]
|
||||||
# element.TKStringVar = tk.StringVar()
|
# element.TKStringVar = tk.StringVar()
|
||||||
|
@ -4640,10 +4612,18 @@ def PackFormIntoFrame(form, containing_frame, toplevel_form):
|
||||||
# if element.Tooltip is not None:
|
# if element.Tooltip is not None:
|
||||||
# element.TooltipObject = ToolTip(element.TKNotebook, text=element.Tooltip,
|
# element.TooltipObject = ToolTip(element.TKNotebook, text=element.Tooltip,
|
||||||
# timeout=DEFAULT_TOOLTIP_TIME)
|
# timeout=DEFAULT_TOOLTIP_TIME)
|
||||||
# ------------------------- SLIDER Box element ------------------------- #
|
# ------------------------- SLIDER element ------------------------- #
|
||||||
elif element_type == ELEM_TYPE_INPUT_SLIDER:
|
elif element_type == ELEM_TYPE_INPUT_SLIDER:
|
||||||
pass
|
element = element # type: Slider
|
||||||
# slider_length = element_size[0] * CharWidthInPixels()
|
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]
|
# slider_width = element_size[1]
|
||||||
# element.TKIntVar = tk.IntVar()
|
# element.TKIntVar = tk.IntVar()
|
||||||
# element.TKIntVar.set(element.DefaultValue)
|
# element.TKIntVar.set(element.DefaultValue)
|
||||||
|
@ -6499,25 +6479,52 @@ def PopupGetText(message, default_text='', password_char='', size=(None, None),
|
||||||
|
|
||||||
def main():
|
def main():
|
||||||
ChangeLookAndFeel('GreenTan' )
|
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:
|
while True:
|
||||||
event, values = window.Read()
|
event, values = window.Read(timeout=0)
|
||||||
print(event, values)
|
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'):
|
if event in (None, 'Exit'):
|
||||||
break
|
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()
|
window.Close()
|
||||||
|
|
||||||
|
|
||||||
if __name__ == '__main__':
|
if __name__ == '__main__':
|
||||||
main()
|
main()
|
||||||
print('back from main')
|
|
||||||
exit(69)
|
exit(69)
|
||||||
|
|
|
@ -1,20 +1,22 @@
|
||||||
|
|
||||||
![pysimplegui_logo](https://user-images.githubusercontent.com/13696193/43165867-fe02e3b2-8f62-11e8-9fd0-cc7c86b11772.png)
|
![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/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
|
# 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
|
## 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.
|
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)
|
[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.
|
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.
|
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:
|
To use PySimpleGUIWeb you need to import it:
|
||||||
`import PySimpleGUIWeb as sg`
|
`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
|
## Requirements
|
||||||
|
@ -63,10 +74,9 @@ You can learn more about Remi on its homepage.
|
||||||
|
|
||||||
https://github.com/dddomodossola/remi
|
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
|
## What Works
|
||||||
|
|
||||||
* Text Element
|
* Text Element
|
||||||
|
@ -115,6 +125,30 @@ Day 2 of development brings fonts, sizes, and colors...
|
||||||
* Listbox Element
|
* Listbox Element
|
||||||
* Element padding for all elements
|
* 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
|
# Acknowledgments
|
||||||
<!--stackedit_data:
|
<!--stackedit_data:
|
||||||
eyJoaXN0b3J5IjpbLTExNjA2ODQzMzldfQ==
|
eyJoaXN0b3J5IjpbLTEwNTcxMDM2NDMsMTIxMzM1MjYzNiwtMT
|
||||||
|
E2MDY4NDMzOV19
|
||||||
-->
|
-->
|
Loading…
Reference in New Issue