Search code examples
pythonwindowsubmenupersistentpysimplegui

How to display different layouts based on button clicks in PySimple GUI? (Persistent window loop)


I am wondering if there is a way that I can manage different layouts based on button clicks in PySimple GUI. I am just starting off using this framework and I want to find the best way of navigating menus. Doesn't have to be using different layouts but this just struck me of the most intuitive way of doing it.

I was thinking like maybe having a list of layouts that get pushed to the top when a certain submenu button is selected.

layouts = [layout1, layout2, layout3, layout4]

Or maybe start the program with:

layout = layout1

And when a submenu is selected just change the state to:

layout = layout2

So for example having a 'Main Menu' layout, and upon a button click, bringing a different layout, or 'submenu', to the 'front' so that the entire program runs in one single window. Maybe looking something like this:

Main Menu

Button 1

Button 2

Button 3

When Button 1 is clicked, the window stays open, but the display changes to Submenu 1.

From the PySimpleGui Docs, I am using the persistent window loop that it is recommended for structuring some programs:

import PySimpleGUI as sg

sg.theme('BluePurple')

layout = [[sg.Text('Your typed chars appear here:'), sg.Text(size=(15,1), key='-OUTPUT-')],
      [sg.Input(key='-IN-')],
      [sg.Button('Show'), sg.Button('Exit')]]

window = sg.Window('Pattern 2B', layout)

while True:  # Event Loop
    event, values = window.read()
    print(event, values)
    if event in  (None, 'Exit'):
        break
    if event == 'Show':
        # Update the "output" text element to be the value of "input" element
        window['-OUTPUT-'].update(values['-IN-'])

window.close()

I am open to changing the structure entirely but I wanted to get the menu navigation down before I start building the functionality.

  • Using PySimpleGUI==4.14.1

Solution

  • You're actually very close.

    Here is what I think you're looking for. What you need to do is add your layouts to Column elements. Then make all columns invisible except for the one you want visible.

    This is a great idea.

    import PySimpleGUI as sg
    
    # ----------- Create the 3 layouts this Window will display -----------
    layout1 = [[sg.Text('This is layout 1 - It is all Checkboxes')],
               *[[sg.CB(f'Checkbox {i}')] for i in range(5)]]
    
    layout2 = [[sg.Text('This is layout 2')],
               [sg.Input(key='-IN-')],
               [sg.Input(key='-IN2-')]]
    
    layout3 = [[sg.Text('This is layout 3 - It is all Radio Buttons')],
               *[[sg.R(f'Radio {i}', 1)] for i in range(8)]]
    
    # ----------- Create actual layout using Columns and a row of Buttons
    layout = [[sg.Column(layout1, key='-COL1-'), sg.Column(layout2, visible=False, key='-COL2-'), sg.Column(layout3, visible=False, key='-COL3-')],
              [sg.Button('Cycle Layout'), sg.Button('1'), sg.Button('2'), sg.Button('3'), sg.Button('Exit')]]
    
    window = sg.Window('Swapping the contents of a window', layout)
    
    layout = 1  # The currently visible layout
    while True:
        event, values = window.read()
        print(event, values)
        if event in (None, 'Exit'):
            break
        if event == 'Cycle Layout':
            window[f'-COL{layout}-'].update(visible=False)
            layout = layout + 1 if layout < 3 else 1
            window[f'-COL{layout}-'].update(visible=True)
        elif event in '123':
            window[f'-COL{layout}-'].update(visible=False)
            layout = int(event)
            window[f'-COL{layout}-'].update(visible=True)
    window.close()
    

    [EDIT] A new Demo Program was added to the PySimpleGUI GitHub named "Demo_Column_Elem_Swap_Entire_Window.py". You can see the code and run it in your browser by visiting Trinket.