Merge pull request #1356 from PySimpleGUI/Dev-latest

Dev latest
This commit is contained in:
MikeTheWatchGuy 2019-04-30 19:38:22 -04:00 committed by GitHub
commit 18460be48b
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
3 changed files with 120 additions and 71 deletions

View File

@ -1,6 +1,9 @@
import sys
if sys.version_info[0] >= 3:
import PySimpleGUIWeb as sg
# import PySimpleGUIQt as sg
# import PySimpleGUI as sg
else:
import PySimpleGUI27 as sg
import math
@ -36,7 +39,7 @@ layout = [[sg.Text('Example of Using Math with a Graph', justification='center',
[sg.Text('x1'),sg.Slider((0,200), orientation='h', enable_events=True,key='_SLIDER_')],
[sg.Text('x2'),sg.Slider((1,200), orientation='h', enable_events=True,key='_SLIDER2_')]]
window = sg.Window('Graph of Sine Function', grab_anywhere=False).Layout(layout)
window = sg.Window('Graph of Sine Function', layout)
while True:
event, values = window.Read()

View File

@ -920,6 +920,10 @@ class Radio(Element):
elif visible is True:
self.TKRadio.pack()
def ResetGroup(self):
self.TKIntVar.set(0)
def __del__(self):
try:
self.TKRadio.__del__()
@ -2012,8 +2016,8 @@ class Graph(Element):
self.CanvasSize = canvas_size
self.BottomLeft = graph_bottom_left
self.TopRight = graph_top_right
self._TKCanvas = None
self._TKCanvas2 = None # Type: tk.Canvas
# self._TKCanvas = None # type: tk.Canvas
self._TKCanvas2 = None # type: tk.Canvas
self.ChangeSubmits = change_submits or enable_events
self.DragSubmits = drag_submits
self.ClickPosition = (None, None)
@ -2292,7 +2296,9 @@ class Graph(Element):
self.ParentForm.TKroot.quit() # kick out of loop if read was called
def SetFocus(self):
self._TKCanvas2.focus_set()
# self._TKCanvas2.focus_force()
def __del__(self):
super().__del__()
@ -5583,23 +5589,25 @@ def PackFormIntoFrame(form, containing_frame, toplevel_form):
element._TKCanvas.bind('<Button-3>', element.RightClickMenuCallback)
# ------------------------- Graph element ------------------------- #
elif element_type == ELEM_TYPE_GRAPH:
element = element # type: Graph
width, height = element_size
if element._TKCanvas is None:
element._TKCanvas = tk.Canvas(tk_row_frame, width=width, height=height, bd=border_depth)
else:
element._TKCanvas.master = tk_row_frame
element._TKCanvas2 = tk.Canvas(element._TKCanvas, width=width, height=height, bd=border_depth)
# I don't know why TWO canvases were being defined, on inside the other. Was it so entire canvas can move?
# if element._TKCanvas is None:
# element._TKCanvas = tk.Canvas(tk_row_frame, width=width, height=height, bd=border_depth)
# else:
# element._TKCanvas.master = tk_row_frame
element._TKCanvas2 = tk.Canvas(tk_row_frame, width=width, height=height, bd=border_depth)
element._TKCanvas2.pack(side=tk.LEFT)
element._TKCanvas2.addtag_all('mytag')
if element.BackgroundColor is not None and element.BackgroundColor != COLOR_SYSTEM_DEFAULT:
element._TKCanvas2.configure(background=element.BackgroundColor, highlightthickness=0)
element._TKCanvas.configure(background=element.BackgroundColor, highlightthickness=0)
element._TKCanvas.pack(side=tk.LEFT, padx=elementpad[0], pady=elementpad[1])
# element._TKCanvas.configure(background=element.BackgroundColor, highlightthickness=0)
element._TKCanvas2.pack(side=tk.LEFT, padx=elementpad[0], pady=elementpad[1])
if element.Visible is False:
element._TKCanvas.pack_forget()
# element._TKCanvas.pack_forget()
element._TKCanvas2.pack_forget()
if element.Tooltip is not None:
element.TooltipObject = ToolTip(element._TKCanvas, text=element.Tooltip,
element.TooltipObject = ToolTip(element._TKCanvas2, text=element.Tooltip,
timeout=DEFAULT_TOOLTIP_TIME)
if element.ChangeSubmits:
element._TKCanvas2.bind('<ButtonRelease-1>', element.ButtonReleaseCallBack)

View File

@ -603,7 +603,7 @@ class Combo(Element):
:param auto_size_text: True if should shrink field to fit the default text
:param background_color: Color for Element. Text or RGB Hex
'''
self.Values = values
self.Values = [str(v) for v in values]
self.DefaultValue = default_value
self.ChangeSubmits = change_submits or enable_events
# self.InitializeAsDisabled = disabled
@ -1638,7 +1638,7 @@ class Image(Element):
self.Disabled = False
self.EnableEvents = enable_events
sz = (0,0) if size == (None, None) else size
self.Widget = None #type: remi.gui.Image
self.Widget = None #type: SuperImage
if data is None and filename is None:
print('* Warning... no image specified in Image Element! *')
super().__init__(ELEM_TYPE_IMAGE, size=sz, background_color=background_color, pad=pad, key=key,
@ -1647,15 +1647,17 @@ class Image(Element):
def Update(self, filename=None, data=None, size=(None,None), visible=None):
if data is not None:
decoded = base64.b64decode(data)
with open(r'.\decoded.out', 'wb') as f:
f.write(decoded)
filename = r'.\decoded.out'
self.Widget.load(data)
# decoded = base64.b64decode(data)
# with open(r'.\decoded.out', 'wb') as f:
# f.write(decoded)
# filename = r'.\decoded.out'
if filename is not None:
self.Widget.set_image(filename=filename)
if size != (None, None):
self.Widget.style['height'] = '{}px'.format(size[1])
self.Widget.style['width'] = '{}px'.format(size[0])
self.Widget.load(filename)
# self.Widget.set_image(filename=filename)
# if size != (None, None):
# self.Widget.style['height'] = '{}px'.format(size[1])
# self.Widget.style['width'] = '{}px'.format(size[0])
super().Update(self.Widget, visible=visible)
def __del__(self):
@ -2729,7 +2731,7 @@ class Window:
element_padding=None, button_color=None, font=None,
progress_bar_color=(None, None), background_color=None, border_depth=None, auto_close=False,
auto_close_duration=None, icon=DEFAULT_BASE64_ICON, force_toplevel=False,
alpha_channel=1, return_keyboard_events=False, use_default_focus=True, text_justification=None,
alpha_channel=1, return_keyboard_events=False, return_key_down_events=False, use_default_focus=True, text_justification=None,
no_titlebar=False, grab_anywhere=False, keep_on_top=False, resizable=True, disable_close=False,
disable_minimize=False, background_image=None,
web_debug=False, web_ip='0.0.0.0', web_port=0, web_start_browser=True, web_update_interval=.0000001, web_multiple_instance=False ):
@ -2799,6 +2801,8 @@ class Window:
self.UseDictionary = False
self.UseDefaultFocus = use_default_focus
self.ReturnKeyboardEvents = return_keyboard_events
self.ReturnKeyDownEvents = return_key_down_events
self.KeyInfoDict = {}
self.LastKeyboardEvent = None
self.TextJustification = text_justification
self.NoTitleBar = no_titlebar
@ -2831,7 +2835,6 @@ class Window:
self.web_start_browser = web_start_browser
self.web_update_interval = web_update_interval
self.web_multiple_instance = web_multiple_instance
self.MessageQueue = Queue()
self.master_widget = None # type: remi.gui.VBox
@ -3082,6 +3085,17 @@ class Window:
if self.CurrentlyRunningMainloop:
self.App.ExitMainLoop()
def on_key_down(self, emitter, key, keycode, ctrl, shift, alt):
self.LastButtonClicked = 'DOWN'+key
self.MessageQueue.put(self.LastButtonClicked)
self.KeyInfoDict = { 'key':key, 'keycode':keycode, 'ctrl': ctrl, 'shift':shift, 'alt':alt }
def on_key_up(self, emitter, key, keycode, ctrl, shift, alt):
self.LastButtonClicked = key
self.MessageQueue.put(self.LastButtonClicked)
self.KeyInfoDict = { 'key':key, 'keycode':keycode, 'ctrl': ctrl, 'shift':shift, 'alt':alt }
def callback_keyboard_char(self, event):
self.LastButtonClicked = None
self.FormRemainedOpen = True
@ -3300,7 +3314,7 @@ class Window:
def remi_thread(self):
logging.getLogger('remi').setLevel(logging.WARNING)
logging.getLogger('remi').setLevel(logging.CRITICAL)
logging.getLogger('remi').disabled = True
logging.getLogger('remi.server.ws').disabled = True
logging.getLogger('remi.server').disabled = True
@ -3350,6 +3364,9 @@ class Window:
# print('res path', res_path)
super(Window.MyApp, self).__init__(*args, static_file_path={'C':'c:','c':'c:','D':'d:', 'd':'d:', 'E':'e:', 'e':'e:', 'dot':'.', '.':'.'})
def log_message(self, *args, **kwargs):
pass
def idle(self):
if Window.stdout_is_rerouted:
Window.stdout_string_io.seek(0)
@ -3360,29 +3377,29 @@ class Window:
def main(self, name='world'):
# margin 0px auto allows to center the app to the screen
self.master_widget = remi.gui.VBox()
self.master_widget.style['justify-content'] = 'flex-start'
self.master_widget.style['align-items'] = 'baseline'
if self.window.BackgroundColor not in (None, COLOR_SYSTEM_DEFAULT):
self.master_widget.style['background-color'] = self.window.BackgroundColor
try:
PackFormIntoFrame(self.window, self.master_widget, self.window)
except:
print('* ERROR PACKING FORM *')
print(traceback.format_exc())
if self.window.BackgroundImage:
self.master_widget.style['background-image'] = "url('{}')".format('/'+self.window.BackgroundImage)
# print(f'background info',self.master_widget.attributes['background-image'] )
if not self.window.DisableClose:
# 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"))
self.master_widget.add_child("onunloadevent", tag)
# self.master_widget = remi.gui.VBox()
# self.master_widget.style['justify-content'] = 'flex-start'
# self.master_widget.style['align-items'] = 'baseline'
# if self.window.BackgroundColor not in (None, COLOR_SYSTEM_DEFAULT):
# self.master_widget.style['background-color'] = self.window.BackgroundColor
# try:
# PackFormIntoFrame(self.window, self.master_widget, self.window)
# except:
# print('* ERROR PACKING FORM *')
# print(traceback.format_exc())
#
# if self.window.BackgroundImage:
# self.master_widget.style['background-image'] = "url('{}')".format('/'+self.window.BackgroundImage)
# # print(f'background info',self.master_widget.attributes['background-image'] )
#
# if not self.window.DisableClose:
# # 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"))
# self.master_widget.add_child("onunloadevent", tag)
self.master_widget = setup_remi_window(self, self.window)
self.window.MessageQueue.put('Layout complete') # signal the main code that the layout is all done
self.window.master_widget = self.master_widget
return self.master_widget # returning the root widget
@ -5142,6 +5159,36 @@ def PackFormIntoFrame(form, containing_frame, toplevel_form):
return
def setup_remi_window(app:Window.MyApp, window:Window):
master_widget = remi.gui.VBox()
master_widget.style['justify-content'] = 'flex-start'
master_widget.style['align-items'] = 'baseline'
if window.BackgroundColor not in (None, COLOR_SYSTEM_DEFAULT):
master_widget.style['background-color'] = window.BackgroundColor
try:
PackFormIntoFrame(window, master_widget, window)
except:
print('* ERROR PACKING FORM *')
print(traceback.format_exc())
if window.BackgroundImage:
master_widget.style['background-image'] = "url('{}')".format('/' + window.BackgroundImage)
# print(f'background info',self.master_widget.attributes['background-image'] )
if not window.DisableClose:
# 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(app)), "on_window_close"))
master_widget.add_child("onunloadevent", tag)
if window.ReturnKeyboardEvents:
app.page.children['body'].onkeyup.connect(window.on_key_up)
if window.ReturnKeyDownEvents:
app.page.children['body'].onkeydown.connect(window.on_key_down)
return master_widget
# ----====----====----====----====----==== STARTUP TK ====----====----====----====----====----#
def StartupTK(window:Window):
global _my_windows
@ -5150,20 +5197,8 @@ def StartupTK(window:Window):
# print('Starting TK open Windows = {}'.format(ow))
# root.attributes('-alpha', 0) # hide window while building it. makes for smoother 'paint'
# root.wm_overrideredirect(True)
# if my_flex_form.BackgroundColor is not None and my_flex_form.BackgroundColor != COLOR_SYSTEM_DEFAULT:
# root.configure(background=my_flex_form.BackgroundColor)
_my_windows.Increment()
# my_flex_form.TKroot = root
# Make moveable window
# if (my_flex_form.GrabAnywhere is not False and not (
# my_flex_form.NonBlocking and my_flex_form.GrabAnywhere is not True)):
# root.bind("<ButtonPress-1>", my_flex_form.StartMove)
# root.bind("<ButtonRelease-1>", my_flex_form.StopMove)
# root.bind("<B1-Motion>", my_flex_form.OnMotion)
# if not my_flex_form.Resizable:
# root.resizable(False, False)
@ -5176,6 +5211,8 @@ def StartupTK(window:Window):
InitializeResults(window)
# Does all of the window setup, starting up Remi
# if no windows exist, start Remi thread which will call same setup_remi_window call as shown below
if len(Window.active_windows) == 0:
window.thread_id = threading.Thread(target=window.remi_thread, daemon=True)
window.thread_id.daemon = True
@ -5185,12 +5222,13 @@ def StartupTK(window:Window):
Window.App = window.App
else:
# margin 0px auto allows to center the app to the screen
master_widget = remi.gui.VBox()
master_widget.style['justify-content'] = 'flex-start'
master_widget.style['align-items'] = 'baseline'
if window.BackgroundColor not in (None, COLOR_SYSTEM_DEFAULT):
master_widget.style['background-color'] = window.BackgroundColor
PackFormIntoFrame(window, master_widget, window)
# master_widget = remi.gui.VBox()
# master_widget.style['justify-content'] = 'flex-start'
# master_widget.style['align-items'] = 'baseline'
# if window.BackgroundColor not in (None, COLOR_SYSTEM_DEFAULT):
# master_widget.style['background-color'] = window.BackgroundColor
# PackFormIntoFrame(window, master_widget, window)
master_widget = setup_remi_window(Window.App, window)
window.master_widget = master_widget
Window.active_windows.append(window)
Window.App.set_root_widget(master_widget)
@ -6770,6 +6808,7 @@ def main():
col1 = [[Text('Column 1 line 1', background_color='red')], [Text('Column 1 line 2')]]
layout = [
[Image(data=DEFAULT_BASE64_ICON)],
[Text('PySimpleGUIWeb Welcomes You...', tooltip='text', font=('Comic sans ms', 20),size=(40,1), text_color='red', enable_events=True, key='_PySimpleGUIWeb_')],
[T('Current Time '), Text('Text', key='_TEXT_', font='Arial 18', text_color='black', size=(30,1)), Column(col1, background_color='red')],
[T('Up Time'), Text('Text', key='_TEXT_UPTIME_', font='Arial 18', text_color='black', size=(30,1))],
@ -6781,15 +6820,12 @@ def main():
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_')],
# [Image(filename=r'C:\Python\PycharmProjects\GooeyGUI\logo200.png', enable_events=True)],
[Image(data=DEFAULT_BASE64_ICON)],
[Slider((1, 100), default_value=80, key='_SLIDER_', visible=True, enable_events=True, orientation='v')],
[Spin(values=(1, 2, 3), initial_value='2', size=(4, 1), key='_SPIN_', enable_events=True)],
[OK(), Button('Hidden', visible=False, key='_HIDDEN_'), Button('Values'), Button('Exit', button_color=('white', 'red')), Button('UnHide')]
[OK(), Button('Hidden', visible=False, key='_HIDDEN_'), Button('Values'), Button('Exit', button_color=('white', 'red')), Button('UnHide'), B('Popup')]
]
window = Window('PySimpleGUIWeb Window', font='Arial 18',default_element_size=(12,1), auto_size_buttons=False, background_image=''
).Layout(layout)
window = Window('PySimpleGUIWeb Test Harness Window', layout, font='Arial 18',default_element_size=(12,1), auto_size_buttons=False)
start_time = datetime.datetime.now()
while True:
@ -6807,6 +6843,8 @@ def main():
window.Element('_MULTIOUT_').Update(str(values), append=True)
elif event != TIMEOUT_KEY:
window.Element('_MULTIOUT_').Update('EVENT: ' + str(event), append=True)
if event == 'Popup':
Popup('This is a popup!')
if event == 'UnHide':
print('Unhiding...')
window.Element('_HIDDEN_').Update(visible=True)