Reacting to a users choice in a combo-box (Event) - python

I have a working form in PySimpleGUI with a combo-box.
I would like to update combo-box "y" (set the default of this combo-box) when the user selects a value in combo-box "x".
I think that I should capture the event and update the "y" element's value, in order to set the "default", but I haven't been able to figure out how to capture this event. I haven't found any good examples of this use case either.
Specifically, after the user chooses a 'Name' from the first combo-box, I would like to update the default value in the 'Status' combo-box:
import gspread
import pandas as pd
import PySimpleGUI as sg
.
.
.
lst = records_df.Label.to_list()
Status = ['A','B','C','D']
layout = [
[sg.Text('Please Choose:',size=(39,1))],
[sg.Combo(lst, key='combo', size=(20,1)),sg.Text('Name:', size=(18,1))],
[sg.Combo(Status, key='comboStatus', size=(20,1)),sg.Text('Status:', size=(18,1))],
[ sg.Button('Exit', key='Exit', size=(18,1)), sg.Button('Submit', key='Submit', size=(20,1))]
]
.
.
.
while True:
event, values = window.read()
if event == sg.WIN_CLOSED or event == 'Exit':
break
elif event == 'Submit':
window.close()

It's easier than you'd think. Just add enable_events=True to the combo-box, and it will pass an event every time an item is chosen.
layout = [
[sg.Text('Please Choose:',size=(39, 1))],
[sg.Combo(lst, key='combo', size=(20, 1), enable_events=True), sg.Text('Name:', size=(18, 1))],
[sg.Combo(Status, key='comboStatus', size=(20, 1)),sg.Text('Status:', size=(18, 1))],
[sg.Button('Exit', key='Exit', size=(18, 1)), sg.Button('Submit', key='Submit', size=(20, 1))]
]
while True:
event, values = window.read()
if event == 'combo': # the event's name is the element's key
print(values)
I couldn't, however, get it to pass an event when you manually enter text into the combobox, even after pressing enter. Hopefully that isn't an issue for your use-case.

Related

Error while getting the index from an empty Listbox .get_indexes()

When I want to get the index of a selected item in a listbox, and the listbox is empty i get a error.
window['Listbox'].get_indexes()[0]
------------------------------------
IndexError: tuple index out of range
The original list that I use in my program is not empty, but it's changing so it may be empty and in that case when I press on the listbox the program crashes.
Code:
import PySimpleGUI as sg
list1 = []
layout = [[sg.Listbox(list1, s=(13, 6), enable_events=True, key='Listbox')]]
window = sg.Window("listbox test 1", layout=layout, size=(100, 100))
while True:
event, values = window.read()
if event == "Exit" or event == sg.WIN_CLOSED:
break
if event == 'Listbox':
print(window['Listbox'].get_indexes()[0])
Is there maybe a simple fix for that?
If no, then I'd have to add a check if the listbox is empty or no.
May this work in your case?
if event == 'Listbox':
try:
print(window['Listbox'].get_indexes()[0])
except:
print("Empty list")
All that's required is an if statement.
if values['Listbox']: # if something was selected
first_entry = values['Listbox'][0]
window['Listbox'].get_indexes()[0] # if you want the index... it'll be safe because values says there are entries

I can't get button name to appear on gui or input to be saved when clicking on button using PySimpleGui

I am using PySimpleGUI and I want to be able to click on a Button and have that show up on the text under the button as the selection. The options are to split or data populate but I am unable to figure out how to make the event handler update the text or to save that option and then have the code act accordingly based on that option.
The code so far looks a little like this
import PySimpleGUI as sg
layout = [
[sg.Text('Would you like to SPLIT or SPLIT AND DATA POPULATE')],
[sg.Button('Split', key='-SPLIT-'), sg.Button('Split and Populate', key ='-SANDP-')],
[sg.Text('Current Process:'), sg.Text('Process', key='-PROCESS-')]
]
window = sg.Window('Title', layout,size=(1000,500))
while True:
event, values = window.read()
if event is None or event == 'EXIT':
break
if event == '-SPLIT-':
window['-PROCESS-'].update(values("-SPLIT-"))
choice1 = window['-PROCESS-'].update("split")
if event == '-Split and Populate-':
window['-PROCESS-'].update("Split and Populate")
choice2 = window['-PROCESS-'].update("Split and Populate")
window.close()
#psuedo code following
if choice1
bla bla bla
if choice2
bla bla bla
I want to be able to click and have that button name be stored in choice1 or choice 2 and also have that button name appear in the gui, is this posible?
The key will be the button_text of sg.Button if option key or k not specified and not duplicate, so there's no event for '-Split and Populate-'.
Most of time, the value of a sg.Button won't changed, so it won't be data in values from sg.Window().read. To get text on sg.Button, you can call method get_text of sg.Button.
For event generated from the key of element when you click on sg.Button or other element, then decide what to do in if ... elif ... else ... statement.
import PySimpleGUI as sg
layout = [
[sg.Text('Would you like to SPLIT or SPLIT AND DATA POPULATE')],
[sg.Button('Split', key='-SPLIT-'),
sg.Button('Split and Populate', key ='-SANDP-')],
[sg.Text('Current Process:'),
sg.Text('Process', size=(0, 1), key='-PROCESS-')]
]
window = sg.Window('Title', layout, size=(1000,500))
while True:
event, values = window.read()
if event is None or event == 'EXIT':
break
elif event in ('-SPLIT-', '-SANDP-'):
window['-PROCESS-'].update(value=window[event].get_text())
if event == '-SPLIT-':
pass
elif event == '-SANDP-':
pass
window.close()

Code Processing Too Many Values in PySimpleGUI

I have been making an app which lets the users check-boxes. Depending on what boxes they check it will display different information. I decided to use PySimpleGUI for this project. I made 6 check-boxes and one text input which I want the user to be able to choose between the check-boxes and enter a title of a movie in the text input box. Depending on what check-boxes they select it will display different information based on the movie whose title was entered in the text input.
When I try to process the title value entered in the text input it process all values including the boolean values of the check-boxes. The information my code tries to process is: {0: ;'my input', 'Title': True, 'Year': False...}. I only need to process the my input/the movie title input and not the boolean values of the check-boxes.
Here is an example of my code (for reference I am also using the IMDBPY library to search for movies (which I have made work, the problem is that the id = search[0].movieID line is processing too many values.):
def run_code():
global name
while True:
event, value = window.read()
if event == 'SEARCH':
print(values)
name = str(values)[5:-2]
print('Please wait while your results load...')
search = ia.search_movie(name)
id = search[0].movieID
if values['Title'] == True:
print(movie_title)
I am trying to make my code search for the ID of the film title which would be typed by the user in an input field and than (at the bottom) and print the movie title depending if they have the title checkbox selected. At this point I just get an error saying id = search[0].movieID IndexError: list index out of range) To my understanding id = search[0].movieID is taking too many values (which it is, it is taking in all the values, input and check-boxes) I only want it to take in the text input value.
How should I spread out the values to deal with this issue?
Define keys in your sg elements. Then you can pick from values just the item that you need. For example:
def test():
layout = [[sg.Text('Movie title:'), sg.Input(key='input')],
[sg.Checkbox('Title', key='title'), sg.Checkbox('Reverse title', key='reverse')],
[sg.Button('Search', enable_events=True), sg.Cancel()]
]
window = sg.Window('My Window', layout, finalize=True)
while True:
event, values = window.read()
print(f'event = {event}, values = {values}')
if event in (sg.WINDOW_CLOSED, 'Cancel', 'Exit'):
break
if event == 'Search':
print('Searching now...')
if values['title']:
print(f'Title = {values["input"]}')
if values['reverse']:
print(f'Reverse title = {values["input"][::-1]}')
# any other action as needed
For example, when you check both the checkboxes and click on Search, you'll get
event = Search, values = {'input': 'abcde', 'title': True, 'reverse': True}
Searching now...
Title = abcde
Reverse title = edcba
Now you can be sure that you've got the right title as input by the user.
Except of this, you should check the value you get in search = ia.search_movie(name). For a title not found in the database, you'll probably get None and that's where id = search[0].movieID gets you the IndexError: list index out of range because there is no None[0]. So, you may want to add something like
if search is None:
print('Not found!')
continue

how to make a savable ui in python

I have a project that allows the user to make a quiz on their own using some buttons and input
well i even want the user to be able to save their quiz in a file so they can load it in
i don't want something BIG!! a txt file will do..
i am using PySimpleGui and not Tkinter or anything..
i really don't know what i have made till now yet?(sorry i am not great with GUI)
i have a :
Main window
Editor window
And a form window
main window links the editor
editor links the form window
thanks for help in advance
if you need my code too then here
import pysimplegui as sg
layout = [
[sg.Button("Make new Form")],
[sg.Button("Open Form")]
]
window = sg.Window("Python Forms", layout)
def Form_Make():
layout_for_make_form = [
[sg.Button("Add multiple choice question")],
[sg.Button("Save Form")]
# some more items here..
]
make_form_window = sg.Window("Make a Form..", layout_for_make_form)
while True:
events, values = make_form_window.read()
if events == "Add multiple choice question":
pass # this should add a new multi choice question(working on it!)
elif events == "Save Form":
# save a form.. i am stuck on this.. :|
while True:
event,values = windows.read()
if event == "Make new Form":
Form_M()
i really don't know what it is doing yet i will have to make a new file and start from scratch :|
this will work for you :
import PySimpleGUI as sg
import os.path
layout = [
[sg.Button("Make new Form")],
[sg.Button("Open Form")],
[sg.Button("Exit")],
]
windows = sg.Window("Python Forms", layout)
questions = []
def Form_Make():
layout_for_make_form = [
[sg.Button("Add multiple choice question", key='add')],
[sg.Text('file path',size=(10,1)),sg.FileBrowse(key='filepath')],
[sg.Button("Save Form",key='save',visible=False)]
# some more items here..
]
make_form_window = sg.Window("Make a Form..", layout_for_make_form)
while True:
count = False
events, values = make_form_window.read()
if events == "add":
layout_for_question = [
[sg.Text('Must Enter all the filed for save question in file.')],
[sg.Text('Enter Question : ',size=(10,1)),sg.Input(key='question')],
[sg.Text('option1',size=(10,1)),sg.Input(key='option1')],
[sg.Text('option2',size=(10,1)),sg.Input(key='option2')],
[sg.Text('option3',size=(10,1)),sg.Input(key='option3')],
[sg.Text('option4',size=(10,1)),sg.Input(key='option4')],
[sg.Button('add')]
]
make_question_window = sg.Window('question ', layout_for_question)
while True:
events, values = make_question_window.read()
if events == None:
break
elif events == 'add' :
if values['question'] != '' and values['option1'] != '' and values['option2'] != '' and values['option3'] != '' and values['option4'] != '':
questions.append([values['question'],values['option1'],values['option2'],values['option3'],values['option4']])
print('value addded ')
count = True
if count == True:
make_form_window['save'].update(visible=True)
elif events == "save":
print(values['filepath'])
file = values['filepath']
if file != None:
f=open(file,'w+')
for x in questions:
for y in x:
f.write(y + '\n')
f.close()
print('save a form.. i am stuck on this.. :')
elif events == None:
break
while True:
event,values = windows.read()
if event == "Make new Form":
Form_Make()
elif event == 'Exit' or event == None :
break

Updating Values in PySimpleGUI

I have a bot that fetches data from a website through selenium and I want to plot that data on a GUI. Bot sends Email and Notifications as well, I need someway to change value of real_email and real_noti Live, anytime.
Whole BOT Code is in a while True: loop.
Issue that I am having right now is, I was thinking of adding my BOT CODE and pysimplegui in the same while loop but the program stops at event, values = window.read() for input and will not go further input is passed.
Here is the Demo Code.
import PySimpleGUI as sg
sg.theme('DarkAmber') # Keep things interesting for your users
elem = sg.Text('Email and Notfication ON', key='-TEXT-')
layout = [[elem],
[sg.Input(key='-IN-')],
[sg.Input(key='-IN')],
[sg.Button('Ok'), sg.Exit()]]
window = sg.Window('Window that stays open', layout)
real_email = "On"
real_noti = "On"
while True: # The Event Loop
event, values = window.read()
email = values['-IN-']
notification = values['-IN']
if email == "On":
real_email = "On"
elif email == "Off":
real_email = "Off"
if notification == "On":
real_noti = "On"
elif notification =="Off":
real_noti = "Off"
if event in (None, 'Exit'):
break
print("Testing Print Value After .read()")
window.close()
I just want to change these 2 values in this loop. Maybe a way to use Checkbox or Only Buttons?
You have to set enable_event=True in the sg.Input(key='-IN-') will be sg.Input(key='-IN-', enable_event=True)

Categories

Resources