diff --git a/Demo_Columns.py b/Demo_Columns.py new file mode 100644 index 00000000..ededa3f6 --- /dev/null +++ b/Demo_Columns.py @@ -0,0 +1,24 @@ +import PySimpleGUI as sg + +# Demo of how columns work +# Form has on row 1 a vertical slider followed by a COLUMN with 7 rows +# Prior to the Column element, this layout was not possible +# Columns layouts look identical to form layouts, they are a list of lists of elements. + +# sg.ChangeLookAndFeel('BlueMono') + +# Column layout +col = [[sg.Text('col Row 1', text_color='white', background_color='blue')], + [sg.Text('col Row 2', text_color='white', background_color='blue'), sg.Input('col input 1')], + [sg.Text('col Row 3', text_color='white', background_color='blue'), sg.Input('col input 2')]] + +layout = [[sg.Listbox(values=('Listbox Item 1', 'Listbox Item 2', 'Listbox Item 3'), select_mode=sg.LISTBOX_SELECT_MODE_MULTIPLE, size=(20,3)), sg.Column(col, background_color='blue')], + [sg.Input('Last input')], + [sg.OK()]] + +# Display the form and get values +# If you're willing to not use the "context manager" design pattern, then it's possible +# to collapse the form display and read down to a single line of code. +button, values = sg.FlexForm('Compact 1-line form with column').LayoutAndRead(layout) + +sg.MsgBox(button, values, line_width=200) diff --git a/PySimpleGUI.py b/PySimpleGUI.py index 8cbed783..4dae3cb9 100644 --- a/PySimpleGUI.py +++ b/PySimpleGUI.py @@ -867,6 +867,7 @@ class FlexForm: ''' Display a user defined for and return the filled in data ''' + def __init__(self, title, default_element_size=(DEFAULT_ELEMENT_SIZE[0], DEFAULT_ELEMENT_SIZE[1]), auto_size_text=None, auto_size_buttons=None, scale=(None, None), location=(None, None), button_color=None, font=None, progress_bar_color=(None, None), background_color=None, is_tabbed_form=False, border_depth=None, auto_close=False, auto_close_duration=DEFAULT_AUTOCLOSE_TIME, icon=DEFAULT_WINDOW_ICON, return_keyboard_events=False, use_default_focus=True, text_justification=None): self.AutoSizeText = auto_size_text if auto_size_text is not None else DEFAULT_AUTOSIZE_TEXT self.AutoSizeButtons = auto_size_buttons if auto_size_buttons is not None else DEFAULT_AUTOSIZE_BUTTONS @@ -1034,6 +1035,7 @@ class FlexForm: return BuildResults(self, False, self) def KeyboardCallback(self, event ): + self.LastButtonClicked = None self.FormRemainedOpen = True if event.char != '': @@ -1053,6 +1055,7 @@ class FlexForm: self.TKroot.quit() + def _Close(self): try: self.TKroot.update() @@ -1814,6 +1817,7 @@ def StartupTK(my_flex_form): # root.bind('', MyFlexForm.DestroyedCallback()) ConvertFlexToTK(my_flex_form) my_flex_form.SetIcon(my_flex_form.WindowIcon) + if my_flex_form.ReturnKeyboardEvents and not my_flex_form.NonBlocking: root.bind("", my_flex_form.KeyboardCallback) root.bind("", my_flex_form.MouseWheelCallback) diff --git a/docs/cookbook.md b/docs/cookbook.md index 15cb14a3..61e581c0 100644 --- a/docs/cookbook.md +++ b/docs/cookbook.md @@ -535,4 +535,61 @@ Perhaps you don't want all the statistics that the EasyProgressMeter provides an ---- +## The One-Line GUI +For those of you into super-compact code, a complete customized GUI can be specified, shown, and received the results using a single line of Python code. The way this is done is to combine the call to `FlexForm` and the call to `LayoutAndRead`. `FlexForm` returns a `FlexForm` object which has the `LayoutAndRead` method. + + +![simple](https://user-images.githubusercontent.com/13696193/44227935-ecb53b80-a161-11e8-968b-b3f963404dec.jpg) + + +Instead of + + import PySimpleGUI as sg + + layout = [[sg.Text('Filename')], + [sg.Input(), sg.FileBrowse()], + [sg.OK(), sg.Cancel()] ] + + button, (number,) = sg.FlexForm('Get filename example').LayoutAndRead(layout) + +you can write this line of code for the exact same result (OK, two lines with the import): + + import PySimpleGUI as sg + + button, (filename,) = sg.FlexForm('Get filename example'). LayoutAndRead([[sg.Text('Filename')], [sg.Input(), sg.FileBrowse()], [sg.OK(), sg.Cancel()] ]) +-------------------- +## Multiple Columns +Starting in version 2.9 (not yet released but you can get from current GitHub) you can use the Column Element. A Column is required when you have a tall element to the left of smaller elements. + +This example uses a Column. There is a Listbox on the left that is 3 rows high. To the right of it are 3 single rows of text and input. These 3 rows are in a Column Element. + +To make it easier to see the Column in the window, the Column background has been shaded blue. The code is wordier than normal due to the blue shading. Each element in the column needs to have the color set to match blue background. + +![snap0202](https://user-images.githubusercontent.com/13696193/44234671-27749f00-a175-11e8-9e66-a3fccf6c077e.jpg) + + + import PySimpleGUI as sg + + # Demo of how columns work + # Form has on row 1 a vertical slider followed by a COLUMN with 7 rows + # Prior to the Column element, this layout was not possible + # Columns layouts look identical to form layouts, they are a list of lists of elements. + + # sg.ChangeLookAndFeel('BlueMono') + + # Column layout + col = [[sg.Text('col Row 1', text_color='white', background_color='blue')], + [sg.Text('col Row 2', text_color='white', background_color='blue'), sg.Input('col input 1')], + [sg.Text('col Row 3', text_color='white', background_color='blue'), sg.Input('col input 2')]] + + layout = [[sg.Listbox(values=('Listbox Item 1', 'Listbox Item 2', 'Listbox Item 3'), select_mode=sg.LISTBOX_SELECT_MODE_MULTIPLE, size=(20,3)), sg.Column(col, background_color='blue')], + [sg.Input('Last input')], + [sg.OK()]] + + # Display the form and get values + # If you're willing to not use the "context manager" design pattern, then it's possible + # to collapse the form display and read down to a single line of code. + button, values = sg.FlexForm('Compact 1-line form with column').LayoutAndRead(layout) + + sg.MsgBox(button, values, line_width=200) diff --git a/docs/tutorial.md b/docs/tutorial.md index edc6b619..ab1e798b 100644 --- a/docs/tutorial.md +++ b/docs/tutorial.md @@ -59,13 +59,31 @@ Let's look at the first recipe from the book print(button, values[0], values[1], values[2]) -It's a reasonable sized form. +It's a reasonably sized form. ![super simple 2](https://user-images.githubusercontent.com/13696193/43934091-8100e29a-9c1b-11e8-8d0a-9bd2d13e6d8e.jpg) If you only need to collect a few values and they're all basically strings, then you would copy this recipe and modify it to suit your needs. +## The 5-line GUI + +Not all GUIs take 5 minutes. Some take 5 lines of code. This is a GUI with a custom layout contained in 5 lines of code. + + import PySimpleGUI as sg + + form = sg.FlexForm('My first GUI') + + layout = [ [sg.Text('Enter your name'), sg.InputText()], + [sg.OK()] ] + + button, (name,) = form.LayoutAndRead(layout) + + +![myfirstgui](https://user-images.githubusercontent.com/13696193/44315412-d2918c80-a3f1-11e8-9eda-0d5d9bfefb0f.jpg) + + + ## Making Your Custom GUI That 5-minute estimate wasn't the time it takes to copy and paste the code from the Cookbook. You should be able to modify the code within 5 minutes in order to get to your layout, assuming you've got a straightforward layout.