Search code examples
pythonpython-3.xlistboxlistboxitempysimplegui

Unselect item from listbox from pysimplegui


The question pretty straight forward. When I click on an item from the listbox it opens another window with information and buttons. However after closing that Window and hitting the search button (with or without values in names) it will open that window again due to still being selected I think. Below is a shortened version and runable program I'm using.

Update: using python version 3.8.2 pysimplegui version 4.55.1

import PySimpleGUI as sg
import pandas as pd
import numpy as np

name = ''
info_string = '' #created in create_string() to update text in secondary_gui()
list_index = 0 #created in user() to update user information in add_point()
choices = [] #created in search() to update listbox in main_gui()
index = [] #created in main_gui() to get that users information from dataframe by cross refrencing name
list_info = [] #created in user() to get list of that users information
df = pd.DataFrame(columns=['name', 'points'],
             data=np.array([['James', 2],
                            ['josh', 12],
                            ['charles', 5]
                            ]))

def maingui():
    global name
    global choices
    global index

    layout = [[sg.Text('name', size=(6, 1)), sg.Input(key='-Name-')],
              [sg.Button('Search'), sg.Button('Add user'), sg.Button('Close')],
              [sg.Listbox(choices, size=(51, len(choices)), key='-CName-', enable_events=True, bind_return_key=True)]
              ]

    window = sg.Window('users', layout)

    while True:
        event, values = window.read()

        name = values['-Name-']

        if event == 'Close' or event == sg.WIN_CLOSED:
            break
        if event == 'Search':
            #find match using name
            search()
            #update listbox choices
            window['-CName-'].update(choices)
        #if event == '-CName-' and len(values['-CName-']):
        if values['-CName-']:
            #check information of user clicked from listbox
            index = values['-CName-']
            user()
            #window['-CName-'].enable_click_events = False
            #values['-CName-'] = False
            secondary_gui()
            #sg.popup('selected', values['-CName-'])



    window.close()

def secondary_gui():
    global info_string
    create_string()
    layout = [[sg.Text(info_string, key='-CInfo-')],
              [sg.Button('Add Point')]]

    window = sg.Window('user Information', layout)
    while True:
        event, values = window.read()

        if event == 'Close' or event == sg.WIN_CLOSED:
            break

    window.close()

def search():
    print('search')
    global name
    global choices
    global df

    df1 = df
    # find name in gsheet
    if name:
        df1 = df1.loc[df1['name'].str.contains(name, case=False)]
        print(name)
        print(df1)
    # create list that GUI can read properly
    cdf = df1.values.tolist()
    choices = cdf

def user():
    print('user')
    global index
    global info_string
    global list_index
    global list_info
    global df
    global name

    # index is nested list, get correct values corresponding to list
    name = index[0][0]

    df1 = df
    # create list based on matching name
    df1 = df1.loc[df1['name'].str.contains(name, case=False)]

    # get user index used for when updating user information(add_point())
    list_index = df1.index  #used in function not shown
    # create list of user to update user values(add_point())
    list_info = df1.stack().to_list()
    print(list_info)

def create_string():
    global info_string
    global list_info
    print('creating string')
    print(list_info)

    # create string for usergui window text
    info_string = ' '.join([str(elem) for elem in list_info])
    print(info_string)

maingui()

I've tried setting values['-CName-'] = False, using sg.popup instead of a window. Updated the enable_click_events to False on line 47. No luck.

I checked the listbox demo program on github which doesnt have this issue. The difference that stood out to me was

if event == '-LIST-' and len(values['-LIST-']): instead of if values['-CName-']: but that didn't seem to work in my case when I swapped out -LIST- for -CName-.

My other idea is to somehow use tkinter and use its functions in here


Solution

  • It is caused by the programming logic,

            if values['-CName-']:
    

    This statement in event loop will be executed no matter when event is, besides events sg.WIN_CLOSED and 'Close', that's why it will popup secondary gui after you click search.

    When you click search button first time, this if will be false, so no popup window.

    If it is specified for event '-CName-' to popup secondary window, you may need to specify it to

            elif event == '-CName-' and values['-CName-']:
    

    It means listbox clicked and with some item(s) selected.

    If you need to unselect item from listbox,

    window[listbox_key].update(set_to_index=[])