pythonpysimplegui

Unable to Pin function in PysimpleGUI


I have a program adding and removing elements on the screen with + and - buttons, the problem is the fact that these buttons don't change position automatically after this change of display like I would expect when using pin function :

1- Initial situation (everything is fine)

Initial situation

2- Adding a frame (everything is fine)

Adding a frame

3- Removing a frame (the buttons 'Add another requirement' and 'Remove a requirement' did not move)

Removing a frame

Code for this layout :

def layout_specification_frame(lvl_1,lvl_2):
    layout = [[sg.Frame(title  = f'Specification N° {lvl_1}',
                        layout = [[sg.Text ('Name of the specification'),      # Layout for one specification 
                                   sg.Input(key    = ('-SPECIFICATION TITLE-', lvl_1)),
                                   sg.Text ('Select IFC Version:'),
                                   sg.Combo(ifc_versions, size=(20, 1),default_value='IFC4', key=('-VERSION-',lvl_1))],
                                  [sg.Frame(title  = 'Applicability',
                                            layout = [[sg.Text  ('All elements of'), 
                                                       sg.Combo (categories, default_value=None, enable_events=True, key=('-FACET-',lvl_1)),
                                                       sg.Text  ('That have a')],
                                                      [sg.Column(layout_parameter(category,lvl_1),key = f'-FACET PARAMETERS {lvl_1}-')]],
                                            key    = f'-APPLICABILITY {lvl_1}-',
                                            relief = 'sunken')],  
                                  [sg.Column(layout_requirement_frame(lvl_1,lvl_2),key = f'-SPEC REQUIREMENT {lvl_1}-')],
                                  [sg.pin(sg.Column([[sg.Button('Add another requirement', key = ('-ADD REQ-',lvl_1)),
                                                      sg.Button('Remove a requirement',key = ('-REMOVE REQ-',lvl_1))]]))]],
                        key    = ('-FRAME LVL 1-',lvl_1),
                        relief = 'groove')]]
    return layout

and in the window.read loop :

        elif event[0] == '-REMOVE REQ-' :
            lvl_2 = lvl_counter[event[1]]
            if lvl_2 >1:
                window[f'-REQUIREMENT {event[1],lvl_2}-'].update(visible = False)
                lvl_counter.update({event[1]:lvl_2-1})
                window.refresh()

Thank you for your time

Update to answer comments : (the code is quite big so I did not want to overload)

The element corresponding to this window[f'-REQUIREMENT {event[1],lvl_2}-'].update(visible = False)

is in the function called sg.Column(layout_requirement_frame(lvl_1,lvl_2),key = f'-SPEC REQUIREMENT {lvl_1}-')

That function is described here : (I also add the other function called inside so you can follow)


def layout_requirement_frame(lvl_1,lvl_2):
    layout = [[sg.Frame(title  = f'Requirement {lvl_2}',
                        layout = [[sg.Text ('Should have a  '),
                                   sg.Combo(categories_req, default_value=None, enable_events=True, key=('-FACET REQ-',lvl_1,lvl_2)),
                                   sg.Text ('With')],
                                  [sg.Column(layout_parameter_req(category_req,lvl_1,lvl_2),key = f'-REQ FACET PARAMETERS {lvl_1, lvl_2}-')]],
                        key    = f'-REQUIREMENT {lvl_1,lvl_2}-',
                        relief = 'sunken')]]
    return layout
    
def layout_parameter_req(category_req,lvl_1,lvl_2):
    cat = category_req[(lvl_1,lvl_2)]
    if cat == None :
        layout = [[]]
    else : 
        items  = Facets[cat]['facet_parameters']
        layout = [[sg.pin(sg.Frame(title  = '',
                                   layout = [[sg.Text  (item['name'], size=(15, 1)), 
                                              sg.Input (key = ('req',cat, item['name'],lvl_1,lvl_2)),
                                              sg.Text  ('Required' if item['required'] else 'Optional',font=('Helvetica', 12, 'bold' if item['required'] else '')),
                                              sg.Push  (), 
                                              sg.Button('+')]for item in items],
                                   key    = f'- FRAME REQ{cat,lvl_1,lvl_2}-',
                                   relief = 'flat'))]]
    return layout 

And the frame is added with an extend layout just there :

 elif event[0] == '-ADD REQ-' :
            
            categories_req  = categories.copy()
            if values[('-FACET-',event[1])]: 
                categories_req.remove(values[('-FACET-',event[1])])
            lvl_2 = lvl_counter[event[1]]+1 #retrieve the previous value (with the dict)
            category_req.update({(event[1],lvl_2):None})
            if f'-REQUIREMENT {event[1],lvl_2}-' in window.AllKeysDict:
                window[f'-REQUIREMENT {event[1],lvl_2}-'].update(visible = True)
                lvl_counter.update({event[1]:lvl_2})
            
            else : 
                lvl_counter.update({event[1]:lvl_2})
                window.extend_layout(window[f'-SPEC REQUIREMENT {event[1]}-'],layout_requirement_frame(event[1],lvl_2))
            window[('-FACET REQ-',event[1],lvl_2)].update(values=categories_req)

Solution

  • I cannot run your script to find what's wrong, but reduce and revise your code to following script and it work.

    import PySimpleGUI as sg
    
    def layout_specification_frame(lvl_1,lvl_2):
        sub_frame = [
            [sg.Text('All elements of'),
             sg.Text  ('That have a')],
            [sg.Column([],key = f'-FACET PARAMETERS {lvl_1}-')],
        ]
        column_layout = [
            [sg.Button('Add another requirement', key = ('-ADD REQ-',lvl_1)),
             sg.Button('Remove a requirement',key = ('-REMOVE REQ-',lvl_1))],
        ]
        frame_layout = [
            [sg.Text ('Name of the specification'),
             sg.Input(key=('-SPECIFICATION TITLE-', lvl_1)),
             sg.Text ('Select IFC Version:')],
            [sg.Frame('Applicability', sub_frame, key=f'-APPLICABILITY {lvl_1}-', relief = 'sunken')],
            [sg.Column(layout_requirement_frame(lvl_1,lvl_2),key = f'-SPEC REQUIREMENT {lvl_1}-')],
            [sg.pin(sg.Column(column_layout))]],
        layout = [[sg.Frame(f'Specification N° {lvl_1}', frame_layout, key=('-FRAME LVL 1-',lvl_1), relief='groove')]]
        return layout
    
    def layout_requirement_frame(lvl_1,lvl_2):
        frame_layout = [
            [sg.Text ('Should have a  '),
             sg.Text ('With')],
            [sg.Column(layout_parameter_req(lvl_1,lvl_2),key=f'-REQ FACET PARAMETERS {lvl_1, lvl_2}-')],
        ]
        layout = [[sg.pin(sg.Frame(f'Requirement {lvl_2}', frame_layout, key=f'-REQUIREMENT {lvl_1,lvl_2}-', relief = 'sunken'))]]
        return layout
    
    def layout_parameter_req(lvl_1,lvl_2):
        items  = []
        frame_layout = [
            [sg.Text(item, size=(15, 1)),
             sg.Input(key=('req', item, lvl_1, lvl_2)),
             sg.Text('Required'), sg.Push(), sg.Button('+')]
                for item in items
        ]
        layout = [[sg.pin(sg.Frame('', frame_layout, key=f'- FRAME REQ{lvl_1,lvl_2}-', relief='flat'))]]
        return layout
    
    lvl_1, lvl_2 = 1, 1
    layout = layout_specification_frame(lvl_1,lvl_2)
    window = sg.Window("Window Title", layout)
    
    while True:
    
        event, values = window.read()
    
        if event == sg.WIN_CLOSED:
            break
    
        elif event[0] == '-ADD REQ-' :
            lvl_2 += 1
            if f'-REQUIREMENT {lvl_1,lvl_2}-' in window.AllKeysDict:
                window[f'-REQUIREMENT {lvl_1,lvl_2}-'].update(visible=True)
            else :
                window.extend_layout(window[f'-SPEC REQUIREMENT {lvl_1}-'],layout_requirement_frame(lvl_1,lvl_2))
    
        elif event[0] == '-REMOVE REQ-' :
            if lvl_2 > 1:
                window[f'-REQUIREMENT {lvl_1,lvl_2}-'].update(visible=False)
                lvl_2 -= 1
    
    window.close()
    

    enter image description here enter image description here