diff --git a/PySimpleGUI.py b/PySimpleGUI.py index 7f4af47b..ccddbd8c 100644 --- a/PySimpleGUI.py +++ b/PySimpleGUI.py @@ -6170,7 +6170,7 @@ class QuickMeter(object): layout = [] if self.orientation.lower().startswith('h'): col = [] - col += [[T(arg)] for arg in args] + col += [[T(''.join(map(lambda x: str(x)+'\n',args)),key='_OPTMSG_')]] ### convert all *args into one string that can be updated col += [[T('', size=(30,10), key='_STATS_')], [ProgressBar(max_value=self.max_value, orientation='h', key='_PROG_', size=self.size, bar_color=self.bar_color)], [Cancel(button_color=self.button_color), Stretch()]] @@ -6178,7 +6178,7 @@ class QuickMeter(object): else: col = [[ProgressBar(max_value=self.max_value, orientation='v', key='_PROG_', size=self.size, bar_color=self.bar_color)]] col2 = [] - col2 += [[T(arg)] for arg in args] + col2 += [[T(''.join(map(lambda x: str(x)+'\n',args)),key='_OPTMSG_')]] ### convert all *args into one string that can be updated col2 += [[T('', size=(30,10), key='_STATS_')], [Cancel(button_color=self.button_color), Stretch()]] layout = [Column(col), Column(col2)] @@ -6187,11 +6187,12 @@ class QuickMeter(object): return self.window - def UpdateMeter(self, current_value, max_value): + def UpdateMeter(self, current_value, max_value,*args): ### support for *args when updating self.current_value = current_value self.max_value = max_value self.window.Element('_PROG_').UpdateBar(self.current_value, self.max_value) self.window.Element('_STATS_').Update('\n'.join(self.ComputeProgressStats())) + self.window.Element('_OPTMSG_').Update(value=''.join(map(lambda x: str(x)+'\n',args))) ### update the string with the args event, values = self.window.Read(timeout=0) if event in('Cancel', None) or current_value >= max_value: self.window.Close() @@ -6239,10 +6240,11 @@ def OneLineProgressMeter(title, current_value, max_value, key, *args, orientatio else: meter = QuickMeter.active_meters[key] - rc = meter.UpdateMeter(current_value, max_value) + rc = meter.UpdateMeter(current_value, max_value,*args) ### pass the *args to to UpdateMeter function OneLineProgressMeter.exit_reasons = getattr(OneLineProgressMeter,'exit_reasons', QuickMeter.exit_reasons) return rc == METER_OK + def OneLineProgressMeterCancel(key): try: meter = QuickMeter.active_meters[key] diff --git a/PySimpleGUIQt/PySimpleGUIQt.py b/PySimpleGUIQt/PySimpleGUIQt.py index 08e3ae7c..4e10a424 100644 --- a/PySimpleGUIQt/PySimpleGUIQt.py +++ b/PySimpleGUIQt/PySimpleGUIQt.py @@ -8,6 +8,16 @@ import base64 import calendar from random import randint + + +###### ##### ##### # # ### ##### +# # # # # # # # # ##### # ###### # # # # # # # ##### +# # # # # # ## ## # # # # # # # # # # # +###### # ##### # # ## # # # # ##### # #### # # # # # # +# # # # # # ##### # # # # # # # # # # # +# # # # # # # # # # # # # # # # # # +# # ##### # # # # ###### ###### ##### ##### ### #### # # + FORCE_PYQT5 = False if not FORCE_PYQT5: @@ -4404,9 +4414,48 @@ def AddMenuItem(top_menu, sub_menu_info, element, is_sub_menu=False, skip=False) AddMenuItem(top_menu, item, element) i += 1 + +""" + QQQQQQQQQ tttt + QQ:::::::::QQ ttt:::t + QQ:::::::::::::QQ t:::::t +Q:::::::QQQ:::::::Q t:::::t +Q::::::O Q::::::Qttttttt:::::ttttttt +Q:::::O Q:::::Qt:::::::::::::::::t +Q:::::O Q:::::Qt:::::::::::::::::t +Q:::::O Q:::::Qtttttt:::::::tttttt +Q:::::O Q:::::Q t:::::t +Q:::::O Q:::::Q t:::::t +Q:::::O QQQQ:::::Q t:::::t +Q::::::O Q::::::::Q t:::::t tttttt +Q:::::::QQ::::::::Q t::::::tttt:::::t + QQ::::::::::::::Q tt::::::::::::::t + QQ:::::::::::Q tt:::::::::::tt + QQQQQQQQ::::QQ ttttttttttt + Q:::::Q + QQQQQQ +""" + +# My crappy Qt code starts here + +# ░░░░░░░░░░░█▀▀░░█░░░░░░ +# ░░░░░░▄▀▀▀▀░░░░░█▄▄░░░░ +# ░░░░░░█░█░░░░░░░░░░▐░░░ +# ░░░░░░▐▐░░░░░░░░░▄░▐░░░ +# ░░░░░░█░░░░░░░░▄▀▀░▐░░░ +# ░░░░▄▀░░░░░░░░▐░▄▄▀░░░░ +# ░░▄▀░░░▐░░░░░█▄▀░▐░░░░░ +# ░░█░░░▐░░░░░░░░▄░█░░░░░ +# ░░░█▄░░▀▄░░░░▄▀▐░█░░░░░ +# ░░░█▐▀▀▀░▀▀▀▀░░▐░█░░░░░ +# ░░▐█▐▄░░▀░░░░░░▐░█▄▄░░░ +# ░░░▀▀▄░░░░░░░░▄▐▄▄▄▀░░░ +# ░░░░░░░░░░░░░░░░░░░░░░░ + + # ------------------------------------------------------------------------------------------------------------------ # # ------------------------------------------------------------------------------------------------------------------ # -# ===================================== TK CODE STARTS HERE ====================================================== # +# ===================================== Qt CODE STARTS HERE ====================================================== # # ------------------------------------------------------------------------------------------------------------------ # # ------------------------------------------------------------------------------------------------------------------ # def style_entry(**kwargs): @@ -5735,27 +5784,28 @@ class QuickMeter(object): def BuildWindow(self, *args): layout = [] if self.orientation.lower().startswith('h'): - col = [*[[T(arg)] for arg in args], - [T('', size=(25,8), key='_STATS_')], + col = [[T(''.join(map(lambda x: str(x)+'\n',args)),key='_OPTMSG_')]] ### convert all *args into one string that can be updated + col += [[T('', size=(25,5), key='_STATS_')], [ProgressBar(max_value=self.max_value, orientation='h', key='_PROG_', size=self.size, bar_color=self.bar_color)], - [Cancel(button_color=self.button_color), Stretch()] ] + [Cancel(button_color=self.button_color), Stretch()]] layout += [Column(col)] else: col = [[ProgressBar(max_value=self.max_value, orientation='v', key='_PROG_', size=self.size, bar_color=self.bar_color)]] - col2 = [*[[T(arg)] for arg in args], - [T('', size=(25, 8), key='_STATS_')],[Cancel(button_color=self.button_color), Stretch()] ] + col2 = [[T(''.join(map(lambda x: str(x)+'\n',args)),key='_OPTMSG_')]] ### convert all *args into one string that can be updated + col2 += [[T('', size=(25,5), key='_STATS_')],[Cancel(button_color=self.button_color), Stretch()]] layout += [Column(col), Column(col2)] self.window = Window(self.title, grab_anywhere=self.grab_anywhere, border_depth=self.border_width) self.window.Layout([layout]).Finalize() return self.window - def UpdateMeter(self, current_value, max_value): + def UpdateMeter(self, current_value, max_value, *args): self.current_value = current_value self.max_value = max_value self.window.Element('_PROG_').UpdateBar(self.current_value, self.max_value) self.window.Element('_STATS_').Update('\n'.join(self.ComputeProgressStats())) + self.window.Element('_OPTMSG_').Update(value=''.join(map(lambda x: str(x)+'\n',args))) ### update the string with the args event, values = self.window.Read(timeout=0) if event in('Cancel', None) or current_value >= max_value: self.window.Close() @@ -5803,7 +5853,7 @@ def OneLineProgressMeter(title, current_value, max_value, key, *args, orientatio else: meter = QuickMeter.active_meters[key] - rc = meter.UpdateMeter(current_value, max_value) + rc = meter.UpdateMeter(current_value, max_value, *args) OneLineProgressMeter.exit_reasons = getattr(OneLineProgressMeter,'exit_reasons', QuickMeter.exit_reasons) return rc == METER_OK diff --git a/PySimpleGUIWeb/PySimpleGUIWeb.py b/PySimpleGUIWeb/PySimpleGUIWeb.py index 586dec62..2c0770c8 100644 --- a/PySimpleGUIWeb/PySimpleGUIWeb.py +++ b/PySimpleGUIWeb/PySimpleGUIWeb.py @@ -11,7 +11,7 @@ from queue import Queue import remi import logging import traceback - +import os g_time_start = 0 g_time_end = 0 @@ -143,7 +143,7 @@ DEFAULT_PROGRESS_BAR_BORDER_WIDTH = 1 DEFAULT_PROGRESS_BAR_RELIEF = RELIEF_GROOVE PROGRESS_BAR_STYLES = ('default', 'winnative', 'clam', 'alt', 'classic', 'vista', 'xpnative') DEFAULT_PROGRESS_BAR_STYLE = 'default' -DEFAULT_METER_ORIENTATION = 'Horizontal' +DEFAULT_METER_ORIENTATION = 'horizontal' DEFAULT_SLIDER_ORIENTATION = 'vertical' DEFAULT_SLIDER_BORDER_WIDTH = 1 DEFAULT_SLIDER_RELIEF = 00000 @@ -439,6 +439,28 @@ class Element(): def Update(self, widget, background_color=None, text_color=None, font=None, visible=None, disabled=None, tooltip=None): + if font is not None: + font_info = font_parse_string(font) # family, point size, other + widget.style['font-family'] = font_info[0] + widget.style['font-size'] = '{}px'.format(font_info[1]) + + if background_color not in (None, COLOR_SYSTEM_DEFAULT): + widget.style['background-color'] = background_color + if text_color not in (None, COLOR_SYSTEM_DEFAULT): + widget.style['color'] = text_color + + if disabled: + widget.set_enabled(False) + elif disabled is False: + widget.set_enabled(True) + if visible is False: + widget.attributes['hidden'] = 'true' + elif visible is True: + del(widget.attributes['hidden']) + if tooltip is not None: + widget.attributes['title'] = tooltip + + # if font: # widget.SetFont(font_to_wx_font(font)) # if text_color not in (None, COLOR_SYSTEM_DEFAULT): @@ -912,22 +934,9 @@ class Spin(Element): def Update(self, value=None, values=None, disabled=None, background_color=None, text_color=None, font=None, visible=None): - if values != None: - self.Values = values - self.QT_Spinner.setStrings(values) - # self.QT_Spinner.setRange(self.Values[0], self.Values[1]) if value is not None: - # self.QT_Spinner.setValue(value) - try: - self.QT_Spinner.setValue(self.QT_Spinner.valueFromText(value)) - self.DefaultValue = value - except: - pass - if disabled == True: - self.QT_Spinner.setDisabled(True) - elif disabled == False: - self.QT_Spinner.setDisabled(False) - super().Update(self.QT_Spinner, background_color=background_color, text_color=text_color, font=font, visible=visible) + self.Widget.set_value(value) + super().Update(self.Widget, background_color=background_color, text_color=text_color, font=font,visible=visible) def Get(self): return self.Widget.get_value() @@ -1076,7 +1085,7 @@ class MultilineOutput(Element): self.CurrentValue = self.CurrentValue + '\n' + str(value) self.Widget.set_value(self.CurrentValue) app = self.ParentForm.App - app.execute_javascript("document.getElementById('%s').scrollTop=%s;" % (self.Widget.identifier, 9999)) # 9999 number of pixel to scroll + # app.execute_javascript("document.getElementById('%s').scrollTop=%s;" % (self.Widget.identifier, 9999)) # 9999 number of pixel to scroll super().Update(self.Widget, background_color=background_color, text_color=text_color, font=font, visible=visible) @@ -1134,6 +1143,7 @@ class Text(Element): pixelsize = size[0]*10, size[1]*20 self.BorderWidth = border_width if border_width is not None else DEFAULT_BORDER_WIDTH self.Disabled = False + self.Widget = None #type: remi.gui.Label super().__init__(ELEM_TYPE_TEXT, pixelsize, auto_size_text, background_color=bg, font=font if font else DEFAULT_FONT, text_color=self.TextColor, pad=pad, key=key, tooltip=tooltip, size_px=size_px, visible=visible) @@ -1142,12 +1152,7 @@ class Text(Element): def Update(self, value=None, background_color=None, text_color=None, font=None, visible=None): if value is not None: self.Widget.set_text(str(value)) - # if background_color is not None: - # self.TKText.configure(background=background_color) - # if text_color is not None: - # self.TKText.configure(fg=text_color) - # if font is not None: - # self.TKText.configure(font=font) + super().Update(self.Widget, background_color=background_color, text_color=text_color, font=font, visible=visible) def __del__(self): super().__del__() @@ -1517,28 +1522,8 @@ class Button(Element): def Update(self, text=None, button_color=(None, None), disabled=None, image_data=None, image_filename=None, font=None, visible=None): if text is not None: self.Widget.set_text(text) - if self.ParentForm.Font and (self.Font == DEFAULT_FONT or not self.Font): - font = self.ParentForm.Font - elif self.Font is not None: - font = self.Font - else: - font = DEFAULT_FONT - - fg = bg = None - if button_color != (None, None): - self.ButtonColor = button_color - fg, bg = button_color - if self.Disabled != disabled and disabled is not None: - if not disabled: # if enabling buttons, set the color - fg, bg = self.ButtonColor - self.Disabled = disabled - if disabled: - self.QT_QPushButton.setDisabled(True) - else: - self.QT_QPushButton.setDisabled(False) - # fg, bg = self.ButtonColor - # print(f'Button update fg, bg {fg}, {bg}') - super().Update(self.Widget, background_color=bg, text_color=fg, font=font, visible=visible) + fg, bg = button_color + super().Update(self.Widget, background_color=bg, text_color=fg, disabled=disabled, font=font, visible=visible) def GetText(self): @@ -1615,7 +1600,7 @@ class ProgressBar(Element): # ---------------------------------------------------------------------- # class Image(Element): def __init__(self, filename=None, data=None, background_color=None, size=(None, None), pad=None, key=None, - tooltip=None): + tooltip=None, right_click_menu=None, visible=True, enable_events=False): ''' Image Element :param filename: @@ -1626,32 +1611,27 @@ class Image(Element): :param key: :param tooltip: ''' - self.Filename = filename + self.Filename = '/'+filename if filename else None # note that Remi expects a / at the front of resource files self.Data = data self.tktext_label = None self.BackgroundColor = background_color + self.Disabled = False + self.EnableEvents = enable_events + sz = (0,0) if size == (None, None) else size + self.Widget = None #type: remi.gui.Image if data is None and filename is None: print('* Warning... no image specified in Image Element! *') - super().__init__(ELEM_TYPE_IMAGE, size=size, background_color=background_color, pad=pad, key=key, - tooltip=tooltip) + super().__init__(ELEM_TYPE_IMAGE, size=sz, background_color=background_color, pad=pad, key=key, + tooltip=tooltip, visible=visible) return - def Update(self, filename=None, data=None, size=(None, None)): + def Update(self, filename=None, data=None, size=(None,None), visible=None): if filename is not None: - image = tk.PhotoImage(file=filename) - elif data is not None: - # if type(data) is bytes: - try: - image = tk.PhotoImage(data=data) - except: - return # an error likely means the window has closed so exit - # else: - # image = data - else: - return - width, height = size[0] or image.width(), size[1] or image.height() - self.tktext_label.configure(image=image, width=width, height=height) - self.tktext_label.image = image + 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): super().__del__() @@ -2205,19 +2185,14 @@ class Slider(Element): text_color=text_color, key=key, pad=pad, tooltip=tooltip, visible=visible, size_px=size_px) return - def Update(self, value=None, range=(None, None), disabled=None): + def Update(self, value=None, range=(None, None), disabled=None, visible=None): if value is not None: - try: - self.TKIntVar.set(value) - if range != (None, None): - self.TKScale.config(from_=range[0], to_=range[1]) - except: - pass + self.Widget.set_value(value) self.DefaultValue = value - if disabled == True: - self.TKScale['state'] = 'disabled' - elif disabled == False: - self.TKScale['state'] = 'normal' + if range != (None, None): + self.Widget.style['min'] = '{}'.format(range[0]) + self.Widget.style['max'] = '{}'.format(range[1]) + super().Update(self.Widget, disabled=disabled, visible=visible) def SliderCallback(self, widget:remi.Widget, value): self.ParentForm.LastButtonClicked = self.Key if self.Key is not None else '' @@ -3207,11 +3182,13 @@ class Window: userdata = args[-1].userdata self.window = userdata[0] # type: Window else: - self.window = userdata2 + self.window = userdata2 # type: Window self.window.App = self self.master_widget = None if userdata2 is None: - super(Window.MyApp, self).__init__(*args) + res_path = os.path.dirname(os.path.abspath(__file__)) + # 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 main(self, name='world'): # margin 0px auto allows to center the app to the screen @@ -3226,6 +3203,10 @@ class Window: print('* ERROR PACKING FORM *') print(traceback.format_exc()) + if self.window.BackgroundImage: + self.master_widget.attributes['background-image'] = "url('{}')".format(self.window.BackgroundImage) + # print(f'background info',self.master_widget.attributes['background-image'] ) + # 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?";};""" % ( @@ -3982,10 +3963,10 @@ def PackFormIntoFrame(form, containing_frame, toplevel_form): if element.TextColor not in (None, COLOR_SYSTEM_DEFAULT): widget.style['color'] = element.TextColor widget.style['font-size'] = '{}px'.format(font_info[1]) - size = convert_tkinter_size_to_Wx(element_size) - # if not auto_size_text: - widget.style['height'] = '{}px'.format(size[1]) - widget.style['width'] = '{}px'.format(size[0]) + if element_size[0]: # if size is zero, don't set any sizes + size = convert_tkinter_size_to_Wx(element_size) + widget.style['height'] = '{}px'.format(size[1]) + widget.style['width'] = '{}px'.format(size[0]) widget.style['margin'] = '{}px {}px {}px {}px'.format(*full_element_pad) if element.Disabled: widget.set_enabled(False) @@ -4428,10 +4409,10 @@ def PackFormIntoFrame(form, containing_frame, toplevel_form): # ------------------------- IMAGE element ------------------------- # elif element_type == ELEM_TYPE_IMAGE: element = element # type: Image - element.Widget = remi.gui.Image(filename=element.Filename) + element.Widget = remi.gui.Image(element.Filename) do_font_and_color(element.Widget) - if element.ChangeSubmits: - element.Widget.onchange.connect(element.ChangedCallback) + if element.EnableEvents: + element.Widget.onclick.connect(element.ChangedCallback) tk_row_frame.append(element.Widget) # if element.Filename is not None: # photo = tk.PhotoImage(file=element.Filename) @@ -4616,7 +4597,8 @@ def PackFormIntoFrame(form, containing_frame, toplevel_form): # ------------------------- SLIDER element ------------------------- # elif element_type == ELEM_TYPE_INPUT_SLIDER: element = element # type: Slider - element.Widget = remi.gui.Slider(layout_orientation = remi.gui.Widget.LAYOUT_HORIZONTAL, default_value=element.DefaultValue, min=element.Range[0], max=element.Range[1],step=element.Resolution) + orient = remi.gui.Widget.LAYOUT_HORIZONTAL if element.Orientation.lower().startswith('h') else remi.gui.Widget.LAYOUT_VERTICAL + element.Widget = remi.gui.Slider(layout_orientation = orient, 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'): @@ -6453,7 +6435,7 @@ def main(): [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)], + [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')] ] diff --git a/PySimpleGUIWeb/readme.md b/PySimpleGUIWeb/readme.md index 9df59c18..fbc2b6ed 100644 --- a/PySimpleGUIWeb/readme.md +++ b/PySimpleGUIWeb/readme.md @@ -8,7 +8,7 @@ ![Python Version](https://img.shields.io/badge/Python-3.x-yellow.svg) -![Python Version](https://img.shields.io/badge/PySimpleGUIWeb_-0.9.0-orange.svg?longCache=true&style=for-the-badge) +![Python Version](https://img.shields.io/badge/PySimpleGUIWeb_-0.10.0-orange.svg?longCache=true&style=for-the-badge) @@ -31,7 +31,7 @@ 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. -## Engineering Pre-Release Version 0.9.0 +## Engineering Pre-Release Version 0.10.0 [Announcements of Latest Developments](https://github.com/MikeTheWatchGuy/PySimpleGUI/issues/142) @@ -79,13 +79,14 @@ PySimpleGUIWeb runs only on Python 3. Legacy Python (2.7) is not supported. * Listbox Element * Spinner Element (sorta... numbers 0 to 100 only now) * Column Element +* Image Element * Window background color * Element padding * Read with timeout * Read with timeout = 0 * Popup Windows * Multiple windows - +* Update methods for many of the elements (Text is 100% complete), others have some of their parameters working. # Running online using repl.it @@ -186,6 +187,26 @@ New features * Support for Window.Hide, Window.UnHide (better multi-window support) +## 0.9.1 PySimpleGUIWeb + +* Emergency release due to some code to do scrolling of multiline not being right and sometimes crashed programs + +## 0.10.0 PySimpleGUIWeb 16-Feb-2019 + +* Completed Text.Update method. Can now change: + * Text + * Font family & size + * Background color + * Text Color + * Visibility +* Completed Button.Update with exception of images +* Completed Spin.Update with except of range. This element still pretty crippled +* Completed Slider.Update - Can update value, visibility, disabled, but not the range +* Image Element! +* Events for Image Element +* Image.Update to change image + + # Design # Author @@ -197,6 +218,6 @@ New features # Acknowledgments \ No newline at end of file diff --git a/PySimpleGUIWx/PySimpleGUIWx.py b/PySimpleGUIWx/PySimpleGUIWx.py index 7e1117af..e7912339 100644 --- a/PySimpleGUIWx/PySimpleGUIWx.py +++ b/PySimpleGUIWx/PySimpleGUIWx.py @@ -1,6 +1,4 @@ #!/usr/bin/python3 -#!/usr/bin/python3 -#!/usr/bin/python3 import sys import wx @@ -15,12 +13,30 @@ import pickle import os import time +###### ##### ##### # # ### # # +# # # # # # # # # ##### # ###### # # # # # # # # # # +# # # # # # ## ## # # # # # # # # # # # # # +###### # ##### # # ## # # # # ##### # #### # # # # # # ## +# # # # # # ##### # # # # # # # # # # ## +# # # # # # # # # # # # # # # # # # # # +# # ##### # # # # ###### ###### ##### ##### ### ## ## # # + """ + 21-Dec-2018 Welcome to the "core" PySimpleGUIWx port! + +'##:::::'##:'##::::'##:'########::'##:::'##:'########:'##::::'##::'#######::'##::: ##: + ##:'##: ##:. ##::'##:: ##.... ##:. ##:'##::... ##..:: ##:::: ##:'##.... ##: ###:: ##: + ##: ##: ##::. ##'##::: ##:::: ##::. ####:::::: ##:::: ##:::: ##: ##:::: ##: ####: ##: + ##: ##: ##:::. ###:::: ########::::. ##::::::: ##:::: #########: ##:::: ##: ## ## ##: + ##: ##: ##::: ## ##::: ##.....:::::: ##::::::: ##:::: ##.... ##: ##:::: ##: ##. ####: + ##: ##: ##:: ##:. ##:: ##::::::::::: ##::::::: ##:::: ##:::: ##: ##:::: ##: ##:. ###: +. ###. ###:: ##:::. ##: ##::::::::::: ##::::::: ##:::: ##:::: ##:. #######:: ##::. ##: +:...::...:::..:::::..::..::::::::::::..::::::::..:::::..:::::..:::.......:::..::::..:: This marks the 3rd port of the PySimpleGUI GUI SDK. Each port gets a little better than - the previous. + the previous, in theory. It will take a while for this Wx port to be completed, but should be running with a fully selection of widgets fairly quickly. The Qt port required 1 week to get to "Alpha" condition @@ -1186,8 +1202,8 @@ class Text(Element): if self.ParentForm.TKrootDestroyed: return if value is not None: - self.WxStaticText.SetLabel(value) - self.DisplayText = value + self.WxStaticText.SetLabel(str(value)) + self.DisplayText = str(value) if background_color is not None: self.WxStaticText.SetBackgroundColour(background_color) if text_color is not None: @@ -4254,9 +4270,18 @@ else: i += 1 + + # # ###### + # # # # # # # # # ##### # # #### # # + # # # # # # # # # # # # # # ## # + # # # ## ###### # # ###### # # # # # + # # # ## # # # # # # # # # # + # # # # # # # # # # # # # ## + ## ## # # # # # # # #### # # + # ------------------------------------------------------------------------------------------------------------------ # # ------------------------------------------------------------------------------------------------------------------ # -# ===================================== TK CODE STARTS HERE ====================================================== # +# ===================================== WxPython CODE STARTS HERE ================================================ # # ------------------------------------------------------------------------------------------------------------------ # # ------------------------------------------------------------------------------------------------------------------ # @@ -5479,7 +5504,7 @@ class QuickMeter(object): layout = [] if self.orientation.lower().startswith('h'): col = [] - col += [[T(arg)] for arg in args] + col += [[T(''.join(map(lambda x: str(x)+'\n',args)),key='_OPTMSG_')]] ### convert all *args into one string that can be updated col += [[T('', size=(25,8), key='_STATS_')], [ProgressBar(max_value=self.max_value, orientation='h', key='_PROG_', size=self.size)], [Cancel(button_color=self.button_color), Stretch()]] @@ -5487,7 +5512,7 @@ class QuickMeter(object): else: col = [[ProgressBar(max_value=self.max_value, orientation='v', key='_PROG_', size=self.size)]] col2 = [] - col2 += [[T(arg)] for arg in args] + col2 += [[T(''.join(map(lambda x: str(x)+'\n',args)),key='_OPTMSG_')]] ### convert all *args into one string that can be updated col2 += [[T('', size=(25,8), key='_STATS_')], [Cancel(button_color=self.button_color), Stretch()]] layout = [Column(col), Column(col2)] @@ -5496,11 +5521,12 @@ class QuickMeter(object): return self.window - def UpdateMeter(self, current_value, max_value): + def UpdateMeter(self, current_value, max_value, *args): self.current_value = current_value self.max_value = max_value self.window.Element('_PROG_').UpdateBar(self.current_value, self.max_value) self.window.Element('_STATS_').Update('\n'.join(self.ComputeProgressStats())) + self.window.Element('_OPTMSG_').Update(value=''.join(map(lambda x: str(x)+'\n',args))) ### update the string with the args event, values = self.window.Read(timeout=0) if event in('Cancel', None) or current_value >= max_value: self.window.Close() @@ -5548,7 +5574,7 @@ def OneLineProgressMeter(title, current_value, max_value, key, *args, orientatio else: meter = QuickMeter.active_meters[key] - rc = meter.UpdateMeter(current_value, max_value) + rc = meter.UpdateMeter(current_value, max_value, *args) OneLineProgressMeter.exit_reasons = getattr(OneLineProgressMeter,'exit_reasons', QuickMeter.exit_reasons) return rc == METER_OK @@ -6219,6 +6245,16 @@ def ObjToString(obj, extra=' '): # Pre-built dialog boxes for all your needs These are the "high level API calls # # ------------------------------------------------------------------------------------------------------------------ # +###### +# # #### ##### # # ##### #### +# # # # # # # # # # # +###### # # # # # # # # #### +# # # ##### # # ##### # +# # # # # # # # # +# #### # #### # #### + + + # ----------------------------------- The mighty Popup! ------------------------------------------------------------ # @@ -6827,6 +6863,19 @@ def PopupGetText(message, title=None, default_text='', password_char='', size=(N return input_values[0] +""" + d8b + Y8P + +88888b.d88b. 8888b. 888 88888b. +888 "888 "88b "88b 888 888 "88b +888 888 888 .d888888 888 888 888 +888 888 888 888 888 888 888 888 +888 888 888 "Y888888 888 888 888 + +""" + + def main(): ChangeLookAndFeel('GreenTan') layout = [ diff --git a/readme.md b/readme.md index 701cbc82..706d1981 100644 --- a/readme.md +++ b/readme.md @@ -8,11 +8,11 @@ ![pysimplegui_logo](https://user-images.githubusercontent.com/13696193/43165867-fe02e3b2-8f62-11e8-9fd0-cc7c86b11772.png) -[![Downloads](http://pepy.tech/badge/pysimplegui)](http://pepy.tech/project/pysimplegui) -[![Downloads ](https://pepy.tech/badge/pysimplegui27)](https://pepy.tech/project/pysimplegui27) -[![Downloads](https://pepy.tech/badge/pysimpleguiqt)](https://pepy.tech/project/pysimpleguiqt) -[![Downloads](https://pepy.tech/badge/pysimpleguiwx)](https://pepy.tech/project/pysimpleguiWx) -[![Downloads](https://pepy.tech/badge/pysimpleguiweb)](https://pepy.tech/project/pysimpleguiWeb) +[![Downloads](http://pepy.tech/badge/pysimplegui)](http://pepy.tech/project/pysimplegui) tkinter +[![Downloads ](https://pepy.tech/badge/pysimplegui27)](https://pepy.tech/project/pysimplegui27) tkinter 2.7 +[![Downloads](https://pepy.tech/badge/pysimpleguiqt)](https://pepy.tech/project/pysimpleguiqt) Qt +[![Downloads](https://pepy.tech/badge/pysimpleguiwx)](https://pepy.tech/project/pysimpleguiWx) WxPython +[![Downloads](https://pepy.tech/badge/pysimpleguiweb)](https://pepy.tech/project/pysimpleguiWeb) Web (Remi) ![Documentation Status](https://readthedocs.org/projects/pysimplegui/badge/?version=latest) ![Awesome Meter](https://img.shields.io/badge/Awesome_meter-100-yellow.svg) ![Python Version](https://img.shields.io/badge/Python-2.7_3.x-yellow.svg) @@ -24,9 +24,12 @@ ## Supports both Python 2.7 & 3 when using tkinter -## Supports both PySide2 and PyQt5 (limited support) -## PySimpleGUI source code can run either on Qt, tkinter, WxPython, Web (Remi) by changing only the import statement +## Supports both PySide2 and PyQt5 (limited support) + +## Effortlessly move across tkinter, Qt, WxPython, and the Web (Remi) by changing only the import statement + +## The *only* way to write both desktop and web based GUIs at the same time @@ -38,7 +41,7 @@ ![Python Version](https://img.shields.io/badge/PySimpleGUIWx_version-0.3.0-orange.svg?longCache=true&style=for-the-badge) -![Python Version](https://img.shields.io/badge/PySimpleGUIWeb_Version-0.2.2-orange.svg?longCache=true&style=for-the-badge) +![Python Version](https://img.shields.io/badge/PySimpleGUIWeb_Version-0.10.0-orange.svg?longCache=true&style=for-the-badge) [Announcements of Latest Developments](https://github.com/MikeTheWatchGuy/PySimpleGUI/issues/142) @@ -52,7 +55,7 @@ [Docs in PDF Format](https://github.com/MikeTheWatchGuy/PySimpleGUI/tree/master/docs) -[Run live in a web browser using repl.it!](https://repl.it/@PySimpleGUI/PySimpleGUIWeb-Demos) +[Repl.it Home for PySimpleGUI](https://repl.it/@PySimpleGUI) Super-simple GUI to use... Powerfully customizable @@ -4973,9 +4976,9 @@ GNU Lesser General Public License (LGPL 3) + * [GRADESK](https://github.com/sidbmw/ICS4U) - Created by a couple of young talented programmers, this classroom management software combines SQL and a GUI to provide a much improved interface for Ottawa teachers. \ No newline at end of file