From 2414e90e1eeda55633e18cc74510925e99489cea Mon Sep 17 00:00:00 2001 From: MikeTheWatchGuy Date: Mon, 17 Sep 2018 21:59:11 -0400 Subject: [PATCH] New element! Frame - A frame with a label, Demo program from Frame, Graph elements --- Demo_Graph_Noise.py | 69 +++++++++++++++++++++++ Demo_Graph__Element.py | 24 +++++--- Demo_Machine_Learning.py | 47 +++++++++------- PySimpleGUI.py | 119 +++++++++++++++++++++++++++++++++------ 4 files changed, 215 insertions(+), 44 deletions(-) create mode 100644 Demo_Graph_Noise.py diff --git a/Demo_Graph_Noise.py b/Demo_Graph_Noise.py new file mode 100644 index 00000000..da52464d --- /dev/null +++ b/Demo_Graph_Noise.py @@ -0,0 +1,69 @@ +import time +import random +import PySimpleGUI as sg + + +STEP_SIZE=1 +SAMPLES = 300 +SAMPLE_MAX = 300 +CANVAS_SIZE = (300,300) + + +def main(): + global g_exit, g_response_time + + with sg.FlexForm('Enter graph size') as form: + layout = [[sg.T('Enter width, height of graph')], + [sg.In(size=(6, 1)), sg.In(size=(6, 1))], + [sg.Ok(), sg.Cancel()]] + + b,v = form.LayoutAndRead(layout) + if b is None or b == 'Cancel': + exit(69) + w, h = int(v[0]), int(v[1]) + CANVAS_SIZE = (w,h) + + # start ping measurement thread + + sg.ChangeLookAndFeel('Black') + sg.SetOptions(element_padding=(0,0)) + + layout = [ [sg.Quit( button_color=('white','black'))], + [sg.Graph(CANVAS_SIZE, (0,0), (SAMPLES,SAMPLE_MAX),background_color='black', key='graph')],] + + form = sg.FlexForm('Canvas test', grab_anywhere=True, background_color='black', no_titlebar=False, use_default_focus=False) + form.Layout(layout) + + form.Finalize() + graph = form.FindElement('graph') + + prev_response_time = None + i=0 + prev_x, prev_y = 0, 0 + graph_value = 250 + while True: + # time.sleep(.2) + button, values = form.ReadNonBlocking() + if button == 'Quit' or values is None: + break + graph_offset = random.randint(-10, 10) + graph_value = graph_value + graph_offset + if graph_value > SAMPLE_MAX: + graph_value = SAMPLE_MAX + if graph_value < 0: + graph_value = 0 + new_x, new_y = i, graph_value + prev_value = graph_value + if i >= SAMPLES: + graph.Move(-STEP_SIZE,0) + prev_x = prev_x - STEP_SIZE + graph.DrawLine((prev_x, prev_y), (new_x, new_y), color='white') + # form.FindElement('graph').DrawPoint((new_x, new_y), color='red') + prev_x, prev_y = new_x, new_y + i += STEP_SIZE if i < SAMPLES else 0 + + + +if __name__ == '__main__': + main() + exit(69) \ No newline at end of file diff --git a/Demo_Graph__Element.py b/Demo_Graph__Element.py index 21f85b9e..e9547e55 100644 --- a/Demo_Graph__Element.py +++ b/Demo_Graph__Element.py @@ -3,6 +3,10 @@ from threading import Thread import time import PySimpleGUI as sg + +STEP_SIZE=1 +SAMPLES = 6000 + # globale used to communicate with thread.. yea yea... it's working fine g_exit = False g_response_time = None @@ -17,11 +21,14 @@ def main(): thread = Thread(target=ping_thread, args=(None,)) thread.start() + # sg.ChangeLookAndFeel('Black') + sg.SetOptions(element_padding=(0,0)) + layout = [ [sg.T('Ping times to Google.com', font='Any 18')], - [sg.Graph((300,300), (0,0), (100,500),background_color='white', key='graph')], + [sg.Graph((6000,200), (0,0), (SAMPLES,500),background_color='black', key='graph')], [sg.Quit()]] - form = sg.FlexForm('Canvas test', grab_anywhere=True) + form = sg.FlexForm('Canvas test', grab_anywhere=True, background_color='black') form.Layout(layout) prev_response_time = None @@ -33,19 +40,18 @@ def main(): button, values = form.ReadNonBlocking() if button == 'Quit' or values is None: break - + graph = form.FindElement('graph') if g_response_time is None or prev_response_time == g_response_time: continue new_x, new_y = i, g_response_time[0] prev_response_time = g_response_time - form.FindElement('graph').DrawLine((prev_x, prev_y), (new_x, new_y), color='red') + if i >= SAMPLES: + graph.Move(-STEP_SIZE,0) + prev_x = prev_x - STEP_SIZE + graph.DrawLine((prev_x, prev_y), (new_x, new_y), color='white') # form.FindElement('graph').DrawPoint((new_x, new_y), color='red') prev_x, prev_y = new_x, new_y - if i >= 100: - i = 0 - prev_x = prev_y = last_x = last_y = 0 - form.FindElement('graph').Erase() - else: i += 4 + i += STEP_SIZE if i < SAMPLES else 0 # tell thread we're done. wait for thread to exit g_exit = True diff --git a/Demo_Machine_Learning.py b/Demo_Machine_Learning.py index 118de02e..2ade40d5 100644 --- a/Demo_Machine_Learning.py +++ b/Demo_Machine_Learning.py @@ -2,26 +2,35 @@ import PySimpleGUI as sg def MachineLearningGUI(): sg.SetOptions(text_justification='right') - form = sg.FlexForm('Machine Learning Front End', font=("Helvetica", 12)) # begin with a blank form - layout = [[sg.Text('Machine Learning Command Line Parameters', font=('Helvetica', 16))], - [sg.Text('Passes', size=(15, 1)), sg.Spin(values=[i for i in range(1, 1000)], initial_value=20, size=(6, 1)), - sg.Text('Steps', size=(18, 1)), sg.Spin(values=[i for i in range(1, 1000)], initial_value=20, size=(6, 1))], - [sg.Text('ooa', size=(15, 1)), sg.In(default_text='6', size=(10, 1)), sg.Text('nn', size=(15, 1)), sg.In(default_text='10', size=(10, 1))], - [sg.Text('q', size=(15, 1)), sg.In(default_text='ff', size=(10, 1)), sg.Text('ngram', size=(15, 1)), sg.In(default_text='5', size=(10, 1))], - [sg.Text('l', size=(15, 1)), sg.In(default_text='0.4', size=(10, 1)), sg.Text('Layers', size=(15, 1)), sg.Drop(values=('BatchNorm', 'other'),auto_size_text=True)], - [sg.Text('_' * 100, size=(65, 1))], - [sg.Text('Flags', font=('Helvetica', 15), justification='left')], - [sg.Checkbox('Normalize', size=(12, 1), default=True), sg.Checkbox('Verbose', size=(20, 1))], - [sg.Checkbox('Cluster', size=(12, 1)), sg.Checkbox('Flush Output', size=(20, 1), default=True)], - [sg.Checkbox('Write Results', size=(12, 1)), sg.Checkbox('Keep Intermediate Data', size=(20, 1))], - [sg.Text('_' * 100, size=(65, 1))], - [sg.Text('Loss Functions', font=('Helvetica', 15), justification='left')], - [sg.Radio('Cross-Entropy', 'loss', size=(12, 1)), sg.Radio('Logistic', 'loss', default=True, size=(12, 1))], - [sg.Radio('Hinge', 'loss', size=(12, 1)), sg.Radio('Huber', 'loss', size=(12, 1))], - [sg.Radio('Kullerback', 'loss', size=(12, 1)), sg.Radio('MAE(L1)', 'loss', size=(12, 1))], - [sg.Radio('MSE(L2)', 'loss', size=(12, 1)), sg.Radio('MB(L0)', 'loss', size=(12, 1))], + flags = [[sg.Checkbox('Normalize', size=(12, 1), default=True), sg.Checkbox('Verbose', size=(20, 1))], + [sg.Checkbox('Cluster', size=(12, 1)), sg.Checkbox('Flush Output', size=(20, 1), default=True)], + [sg.Checkbox('Write Results', size=(12, 1)), sg.Checkbox('Keep Intermediate Data', size=(20, 1))], + [sg.Checkbox('Normalize', size=(12, 1), default=True), sg.Checkbox('Verbose', size=(20, 1))], + [sg.Checkbox('Cluster', size=(12, 1)), sg.Checkbox('Flush Output', size=(20, 1), default=True)], + [sg.Checkbox('Write Results', size=(12, 1)), sg.Checkbox('Keep Intermediate Data', size=(20, 1))],] + + loss_functions = [[sg.Radio('Cross-Entropy', 'loss', size=(12, 1)), sg.Radio('Logistic', 'loss', default=True, size=(12, 1))], + [sg.Radio('Hinge', 'loss', size=(12, 1)), sg.Radio('Huber', 'loss', size=(12, 1))], + [sg.Radio('Kullerback', 'loss', size=(12, 1)), sg.Radio('MAE(L1)', 'loss', size=(12, 1))], + [sg.Radio('MSE(L2)', 'loss', size=(12, 1)), sg.Radio('MB(L0)', 'loss', size=(12, 1))],] + + command_line_parms = [[sg.Text('Passes', size=(8, 1)), sg.Spin(values=[i for i in range(1, 1000)], initial_value=20, size=(6, 1)), + sg.Text('Steps', size=(8, 1), pad=((7,3))), sg.Spin(values=[i for i in range(1, 1000)], initial_value=20, size=(6, 1))], + [sg.Text('ooa', size=(8, 1)), sg.In(default_text='6', size=(8, 1)), sg.Text('nn', size=(8, 1)), + sg.In(default_text='10', size=(10, 1))], + [sg.Text('q', size=(8, 1)), sg.In(default_text='ff', size=(8, 1)), sg.Text('ngram', size=(8, 1)), + sg.In(default_text='5', size=(10, 1))], + [sg.Text('l', size=(8, 1)), sg.In(default_text='0.4', size=(8, 1)), sg.Text('Layers', size=(8, 1)), + sg.Drop(values=('BatchNorm', 'other'), auto_size_text=True)],] + + layout = [[sg.Frame('Command Line Parameteres', command_line_parms, text_color='green', font='Any 12')], + [sg.Frame('Flags', flags, font='Any 12', text_color='blue')], + [sg.Frame('Loss Functions', loss_functions, font='Any 12', text_color='red')], [sg.Submit(), sg.Cancel()]] + + + form = sg.FlexForm('Machine Learning Front End', font=("Helvetica", 12)) button, values = form.LayoutAndRead(layout) del(form) sg.SetOptions(text_justification='left') @@ -53,5 +62,5 @@ def CustomMeter(): form.CloseNonBlockingForm() if __name__ == '__main__': - CustomMeter() + # CustomMeter() MachineLearningGUI() diff --git a/PySimpleGUI.py b/PySimpleGUI.py index 107821f8..f9d26aa8 100644 --- a/PySimpleGUI.py +++ b/PySimpleGUI.py @@ -12,6 +12,23 @@ import pickle import calendar +g_time_start = 0 +g_time_end = 0 +g_time_delta = 0 + +import time +def TimerStart(): + global g_time_start + + g_time_start = time.time() + +def TimerStop(): + global g_time_delta, g_time_end + + g_time_end = time.time() + g_time_delta = g_time_end - g_time_start + print(g_time_delta) + # ----====----====----==== Constants the user CAN safely change ====----====----====----# DEFAULT_WINDOW_ICON = 'default_icon.ico' DEFAULT_ELEMENT_SIZE = (45,1) # In CHARACTERS @@ -84,6 +101,7 @@ DEFAULT_METER_ORIENTATION = 'Horizontal' DEFAULT_SLIDER_ORIENTATION = 'vertical' DEFAULT_SLIDER_BORDER_WIDTH=1 DEFAULT_SLIDER_RELIEF = tk.FLAT +DEFAULT_FRAME_RELIEF = tk.GROOVE DEFAULT_LISTBOX_SELECT_MODE = tk.SINGLE SELECT_MODE_MULTIPLE = tk.MULTIPLE @@ -223,6 +241,11 @@ class Element(): rc = self.FindReturnKeyBoundButton(element) if rc is not None: return rc + if element.Type == ELEM_TYPE_FRAME: + rc = self.FindReturnKeyBoundButton(element) + if rc is not None: + return rc + return None def ReturnKeyHandler(self, event): @@ -1180,7 +1203,6 @@ class Graph(Element): zero_converted = self._convert_xy_to_canvas_xy(0,0) shift_converted = self._convert_xy_to_canvas_xy(x_direction, y_direction) shift_amount = (shift_converted[0]-zero_converted[0], shift_converted[1]-zero_converted[1]) - print(shift_amount) self._TKCanvas2.move('all', *shift_amount) @property @@ -1195,13 +1217,50 @@ class Graph(Element): # Frame # # ---------------------------------------------------------------------- # class Frame(Element): - def __init__(self, frame=None, background_color=None, scale=(None, None), size=(None, None), pad=None, key=None): - self.BackgroundColor = background_color if background_color is not None else DEFAULT_BACKGROUND_COLOR - self.TKFrame = frame + def __init__(self, title, layout, text_color=None, background_color=None, relief=DEFAULT_FRAME_RELIEF, size=(None, None), font=None, pad=None, key=None): - super().__init__(ELEM_TYPE_FRAME, background_color=background_color, scale=scale, size=size, pad=pad, key=key) + self.UseDictionary = False + self.ReturnValues = None + self.ReturnValuesList = [] + self.ReturnValuesDictionary = {} + self.DictionaryKeyCounter = 0 + self.ParentWindow = None + self.Rows = [] + self.ParentForm = None + self.TKFrame = None + self.Title = title + self.Relief = relief + self.BackgroundColor = background_color if background_color is not None else DEFAULT_BACKGROUND_COLOR + + self.Layout(layout) + + super().__init__(ELEM_TYPE_FRAME, background_color=background_color, text_color=text_color, size=size, font=font, pad=pad, key=key) return + def AddRow(self, *args): + ''' Parms are a variable number of Elements ''' + NumRows = len(self.Rows) # number of existing rows is our row number + CurrentRowNumber = NumRows # this row's number + CurrentRow = [] # start with a blank row and build up + # ------------------------- Add the elements to a row ------------------------- # + for i, element in enumerate(args): # Loop through list of elements and add them to the row + element.Position = (CurrentRowNumber, i) + CurrentRow.append(element) + if element.Key is not None: + self.UseDictionary = True + # ------------------------- Append the row to list of Rows ------------------------- # + self.Rows.append(CurrentRow) + + def Layout(self, rows): + for row in rows: + self.AddRow(*row) + + def __del__(self): + for row in self.Rows: + for element in row: + element.__del__() + + def __del__(self): super().__del__() @@ -1264,7 +1323,7 @@ class Slider(Element): # ---------------------------------------------------------------------- # -# TkScrollableFrame (Used by Column (SOON) # +# TkScrollableFrame (Used by Column) # # ---------------------------------------------------------------------- # class TkScrollableFrame(tk.Frame): def __init__(self, master, **kwargs): @@ -2132,9 +2191,18 @@ def BuildResultsForSubform(form, initialize_only, top_level_form): BuildResultsForSubform(element, initialize_only, top_level_form) for item in element.ReturnValuesList: AddToReturnList(top_level_form, item) - # for key in element.ReturnValuesDictionary: - # top_level_form.ReturnValuesDictionary[key] = element.ReturnValuesDictionary[key] - # top_level_form.DictionaryKeyCounter += element.DictionaryKeyCounter + if element.UseDictionary: + top_level_form.UseDictionary = True + if element.ReturnValues[0] is not None: # if a button was clicked + button_pressed_text = element.ReturnValues[0] + + if element.Type == ELEM_TYPE_FRAME: + element.DictionaryKeyCounter = top_level_form.DictionaryKeyCounter + element.ReturnValuesList = [] + element.ReturnValuesDictionary = {} + BuildResultsForSubform(element, initialize_only, top_level_form) + for item in element.ReturnValuesList: + AddToReturnList(top_level_form, item) if element.UseDictionary: top_level_form.UseDictionary = True if element.ReturnValues[0] is not None: # if a button was clicked @@ -2200,7 +2268,7 @@ def BuildResultsForSubform(form, initialize_only, top_level_form): # if an input type element, update the results if element.Type != ELEM_TYPE_BUTTON and element.Type != ELEM_TYPE_TEXT and element.Type != ELEM_TYPE_IMAGE and\ element.Type != ELEM_TYPE_OUTPUT and element.Type != ELEM_TYPE_PROGRESS_BAR and \ - element.Type!= ELEM_TYPE_COLUMN: + element.Type!= ELEM_TYPE_COLUMN and element.Type != ELEM_TYPE_FRAME: AddToReturnList(form, value) AddToReturnDictionary(top_level_form, element, value) elif (element.Type == ELEM_TYPE_BUTTON and element.BType == BUTTON_TYPE_CALENDAR_CHOOSER and element.Target == (None,None)) or \ @@ -2240,6 +2308,13 @@ def FillSubformWithValues(form, values_dict): value = values_dict[element.Key] except: continue + if element.Type == ELEM_TYPE_FRAME: + FillSubformWithValues(element, values_dict) + try: + value = values_dict[element.Key] + except: + continue + if element.Type == ELEM_TYPE_INPUT_TEXT: element.Update(value) elif element.Type == ELEM_TYPE_INPUT_CHECKBOX: @@ -2268,6 +2343,10 @@ def _FindElementFromKeyInSubForm(form, key): matching_elem = _FindElementFromKeyInSubForm(element, key) if matching_elem is not None: return matching_elem + if element.Type == ELEM_TYPE_FRAME: + matching_elem = _FindElementFromKeyInSubForm(element, key) + if matching_elem is not None: + return matching_elem if element.Key == key: return element @@ -2366,6 +2445,7 @@ def PackFormIntoFrame(form, containing_frame, toplevel_form): col_frame.pack(side=tk.LEFT, padx=element.Pad[0], pady=element.Pad[1]) if element.BackgroundColor != COLOR_SYSTEM_DEFAULT and element.BackgroundColor is not None: col_frame.configure(background=element.BackgroundColor, highlightbackground=element.BackgroundColor, highlightcolor=element.BackgroundColor) + # ------------------------- TEXT element ------------------------- # elif element_type == ELEM_TYPE_TEXT: # auto_size_text = element.AutoSizeText @@ -2728,12 +2808,16 @@ def PackFormIntoFrame(form, containing_frame, toplevel_form): toplevel_form.TKroot.configure(menu=element.TKMenu) # ------------------------- Frame element ------------------------- # elif element_type == ELEM_TYPE_FRAME: - width, height = element_size - if element.TKFrame is None: - element.TKFrame = tk.Frame(tk_row_frame, width=width, height=height, bd=border_depth) - if element.BackgroundColor is not None and element.BackgroundColor != COLOR_SYSTEM_DEFAULT: - element.TKFrame.configure(background=element.BackgroundColor) - element.TKFrame.pack(side=tk.LEFT, padx=element.Pad[0], pady=element.Pad[1]) + labeled_frame = tk.LabelFrame(tk_row_frame, text=element.Title, relief=element.Relief) + PackFormIntoFrame(element, labeled_frame, toplevel_form) + labeled_frame.pack(side=tk.LEFT, padx=element.Pad[0], pady=element.Pad[1]) + if element.BackgroundColor != COLOR_SYSTEM_DEFAULT and element.BackgroundColor is not None: + labeled_frame.configure(background=element.BackgroundColor, highlightbackground=element.BackgroundColor, highlightcolor=element.BackgroundColor) + if element.TextColor != COLOR_SYSTEM_DEFAULT and element.TextColor is not None: + labeled_frame.configure(foreground=element.TextColor) + if element.Font != None: + labeled_frame.configure(font=element.Font) + # ------------------------- SLIDER Box element ------------------------- # elif element_type == ELEM_TYPE_INPUT_SLIDER: slider_length = element_size[0] * CharWidthInPixels() @@ -2856,7 +2940,9 @@ def ConvertFlexToTK(MyFlexForm): move_string = '+%i+%i'%(int(x),int(y)) master.geometry(move_string) + master.update_idletasks() # don't forget + return @@ -2961,6 +3047,7 @@ def StartupTK(my_flex_form): # root.protocol("WM_DELETE_WINDOW", MyFlexForm.DestroyedCallback()) # root.bind('', MyFlexForm.DestroyedCallback()) ConvertFlexToTK(my_flex_form) + my_flex_form.SetIcon(my_flex_form.WindowIcon) try: