I am using PySimpleGUI to build a GUI for my application. I am trying to print out on screen some messages for the user through a Listbox but when I call the window[].update() lines the print out is not showing by line but putting each character on a new line. I am not sure if Listbox is the function that I should be using or if there is another function better suited for what I want to do.
import PySimpleGUI as sg
import os, sys
file_list_column = [
[sg.Text('File Name: '), sg.In(size = (25, 1), enable_events = True, key = '-ID-')],
[sg.Text('File Location: '), sg.In(size = (25, 1), enable_events = True, key = '-FOLDER-'),sg.FolderBrowse()],
[sg.Button('Create Location')],
[sg.Listbox(values = [], enable_events = True, size = (40, 20), key = '-UPDATES-')],]
layout = [[sg.Column(file_list_column)],
[sg.Button('Close')]]
window = sg.Window('Test', layout)
while True:
event, values = window.read()
if event == 'Close' or event == sg.WIN_CLOSED or event == 'Exit':
break
if event == 'Create Location':
try:
os.makedirs(os.path.join(values['-FOLDER-'], values['-ID-']))
window['-UPDATES-'].update(str('Folder location created.'))
except:
window['-UPDATES-'].update(str('Folder location NOT created.'))
window.close()
The string I want to display to the user is placing each character on its own line.
Related
I have developed another GUI using PySimpleGUI that helps the user change the passenger's life state by checking and unchecking the boxes on the left side of the GUI. However, I was asked if I could put the column of the checkboxes on the most right-hand side of the GUI instead. I have tried both methods of using the Tree Element and the Column Element
Is it possible to insert a checkbox in a PysimpleGui table?
Is it possible to put two columns of checkboxes on PySimpleGUI to manipulate the values in a dataframe?
Here is my code.
from io import BytesIO
from PIL import Image, ImageDraw
import pandas as pd
import PySimpleGUI as sg
import copy
def icon(check):
box = (32, 32)
background = (255, 255, 255, 0)
rectangle = (3, 3, 29, 29)
line = ((9, 17), (15, 23), (23, 9))
im = Image.new('RGBA', box, background)
draw = ImageDraw.Draw(im, 'RGBA')
draw.rectangle(rectangle, outline='black', width=3)
if check == 1:
draw.line(line, fill='black', width=3, joint='curve')
elif check == 2:
draw.line(line, fill='grey', width=3, joint='curve')
with BytesIO() as output:
im.save(output, format="PNG")
png = output.getvalue()
return png
check = [icon(0), icon(1), icon(2)]
titanic_df = pd.read_csv('titanic.csv').head(30)
names = titanic_df['name'].to_list()
states = titanic_df['survived'].to_list()
data = titanic_df.values.tolist()
passenger_dict = {name : state for name, state in zip(names, states)}
print(f'passenger_dict: {passenger_dict}')
treedata = sg.TreeData()
for index, (name, state) in enumerate(passenger_dict.items()):
if state is True:
treedata.Insert('', name, index, values=[name, state], icon=check[1])
else:
treedata.Insert('', name, index,values=[name,state], icon=check[0])
#print(f"treedata: {treedata}")
sg.set_options(font=('Helvetica', 16))
layout = [
[sg.Tree(data=treedata,key='-TREE-',
headings=['NAME','SURVIVED'],
row_height=48,
enable_events=True,
select_mode=sg.TABLE_SELECT_MODE_BROWSE)],
[sg.Button('Submit', key='-SUBMIT-'),sg.Button('Quit')]
]
window = sg.Window('Tree as Table', layout, finalize=True)
tree = window['-TREE-']
tree.Widget.heading("#0", text='Index') # Set heading for column #0
survivors = {}
dead_people = {}
for passenger, state in passenger_dict.items():
if state is True:
survivors[passenger] = state
else:
dead_people[passenger] = state
print(f'Original survivers: {survivors}')
print(f'Original dead_people: {dead_people}')
while True:
event, values = window.read()
print(f'event: {event}')
print(f'values: {values}')
if event == sg.WIN_CLOSED or event == 'Quit':
break
elif event == '-TREE-':
passenger_name = values['-TREE-'][0]
print(f'passenger_name: {passenger_name}')
if passenger_dict[passenger_name] is True:
if passenger_name in survivors.keys():
print('1')
tree.update(key=passenger_name, icon=check[0])
passenger_dict[passenger_name] = False
dead_people[passenger_name] = copy.deepcopy(passenger_dict[passenger_name])
del survivors[passenger_name]
else:
if passenger_name in dead_people.keys():
print('2')
tree.update(key=passenger_name, icon=check[1])
passenger_dict[passenger_name] = True
survivors[passenger_name] = copy.deepcopy(passenger_dict[passenger_name])
del dead_people[passenger_name]
elif event == "-SUBMIT-":
survivors_df = pd.DataFrame(survivors.items())
survivors_df.to_csv('survivors.csv')
dead_people_df = pd.DataFrame(dead_people.items())
dead_people_df.to_csv('dead_people.csv')
break
print(f'Updated survivors: {survivors}')
print(f'Updated dead_people: {dead_people}')
window.close()
Once the user presses the "Submit" button, "survivors" and "dead_people" dictionaries with the passenger's name and life state key-value pairs in them will be outputted as two separate CSV files.
Here is the CSV file I tested with the program.
https://drive.google.com/file/d/1WMv44p6GnTdFBxGQufd9Uc1beubXYgrL/view?usp=sharing
The idea is from the dataset here.
https://www.kaggle.com/code/alexisbcook/titanic-tutorial/data
Here is what I wanted to achieve:
My Ultimate Goal
Here is what I have got so far
Result of Tree Element
I have a couple programs I am trying this on here is a smaller one. I have a right click set up I want to change keep_on_top=True to keep_on_top=False
as you can see I am able to change the Alpha level but not able to figure out how to make this change here is the code of a simple local and Zulu time clock
import PySimpleGUI as sg
import pytz
from datetime import datetime
Cur_Time_Date=''
Cur_Time_DateUTC=''
ALPHA = 0.9 # Initial alpha until user changes
def update_window():
current_datetime = datetime.now()
Cur_Time_Date = current_datetime.strftime("%H:%M:%S (L) %m/%d/%y")
utc_time = datetime.now(pytz.utc)
Cur_Time_DateUTC = utc_time.strftime("%H:%M:%S (Z) %m/%d/%y")
window['-LCL-'].update(Cur_Time_Date + '(L)')
window['-UTC-'].update(Cur_Time_DateUTC + '(Z)')
def create_window():
right_click_menu = [[''],['keep_on_top', 'Alpha', [str(x) for x in range(1, 11)], 'Exit', ]]
layout = [
[sg.Text(Cur_Time_Date, key = '-LCL-')],
[sg.Text(Cur_Time_DateUTC, key = '-UTC-')]
]
return sg.Window('Local/UTC time', layout, alpha_channel=ALPHA, no_titlebar=True, grab_anywhere=True, right_click_menu=right_click_menu, keep_on_top=True)
window = create_window()
while True:
event, values = window.read(timeout=1000)
if event in (sg.WIN_CLOSED, '-CLOSE-'):
break
elif event in (sg.WIN_CLOSE_ATTEMPTED_EVENT, 'Exit'):
break
elif event == 'keep_on_top':
sg.popup( title = 'Keep On Top', keep_on_top=True)
elif event in [str(x) for x in range(1, 11)]:
window.set_alpha(int(event) / 10)
#window.close
update_window()
I figured it out if anyone else is looking
First, I set the variable and setup my own popup box:
keepOnTop = True
def My_popup():
layout = [[sg.Text('Keep On Top')],
[sg.Push(), sg.Yes(),sg.No(), sg.Push()]]
window = sg.Window('', layout, keep_on_top=True)
event, values = window.read()
window.close()
return (event)
I set the variable to start and used it to set at the beginning.
Then I used this when selecting option from right clicking
elif event == 'keep_on_top':
ans=My_popup()
print(ans)
if ans == 'Yes':
keepOnTop=True
else:
keepOnTop=False
print(keepOnTop)
window.close()
window = create_window()
I also needed to add, finalize=True to the window
I have 2 columns and I want to reveal them on a button press by using the visibility parameter. However, it seems that columns that go from invisible to visible stop being next to each other and are instead arranged like rows.
Here is the code without the reveal, and the columns work fine:
import PySimpleGUI as sg
left_col = sg.Column([[sg.Frame('',[],background_color = '#FF0000',size = (60,40))]])
right_col = sg.Column([[sg.Frame('',[],background_color = '#00FF00',size = (60,40))]])
layout = [
[sg.Button('reveal')],
[left_col,right_col]]
window = sg.Window('Converter', layout)
while True:
event, values = window.read()
if event == sg.WIN_CLOSED:
break
window.close()
And here is the same code with the columns being revealed:
import PySimpleGUI as sg
left_col = sg.Column([[sg.Frame('',[],background_color = '#FF0000',size = (60,40))]],visible = False, key = 'left')
right_col = sg.Column([[sg.Frame('',[],background_color = '#00FF00',size = (60,40))]],visible = False, key = 'right')
layout = [
[sg.Button('reveal')],
[left_col,right_col]]
window = sg.Window('Converter', layout)
while True:
event, values = window.read()
if event == sg.WIN_CLOSED:
break
if event == 'reveal':
window['left'].update(visible = True)
window['right'].update(visible = True)
window.close()
I guess my question is whether there is a workaround for this (or whether I did something wrong).
Elements after visible=False will miss it's location in the window, so use function pin to keep the location for element if you want to set it to be invisible.
layout = [
[sg.Button('reveal')],
[sg.pin(left_col), sg.pin(right_col)]]
By default, the background is the background color of theme. Of course, you can built one by yourself which with one more option bg as background_color.
Don't forget to set the background color of the Column in your layout at the same time.
def pin(elem, vertical_alignment=None, shrink=True, expand_x=None, expand_y=None, bg=None):
if shrink:
return sg.Column([[elem, sg.Column([[]], pad=(0,0), background_color=bg)]], background_color=bg, pad=(0, 0), vertical_alignment=vertical_alignment, expand_x=expand_x, expand_y=expand_y)
else:
return sg.Column([[elem]], pad=(0, 0), vertical_alignment=vertical_alignment, expand_x=expand_x, expand_y=expand_y, background_color=bg)
Then you code maybe something like this
import PySimpleGUI as sg
def pin(elem, vertical_alignment=None, shrink=True, expand_x=None, expand_y=None, bg=None):
if shrink:
return sg.Column([[elem, sg.Column([[]], pad=(0,0), background_color=bg)]], background_color=bg, pad=(0, 0), vertical_alignment=vertical_alignment, expand_x=expand_x, expand_y=expand_y)
else:
return sg.Column([[elem]], pad=(0, 0), vertical_alignment=vertical_alignment, expand_x=expand_x, expand_y=expand_y, background_color=bg)
left_col = sg.Column([[sg.Frame('', [], background_color = '#FF0000', size = (60,40))]], background_color='blue')
right_col = sg.Column([[sg.Frame('', [], background_color = '#00FF00', size = (60,40))]], background_color='blue')
layout = [
[sg.Button('reveal')],
[pin(left_col, bg='blue'), pin(right_col, bg='blue')]]
window = sg.Window('Converter', layout, background_color='blue')
while True:
event, values = window.read()
if event == sg.WIN_CLOSED:
break
window.close()
I have a window that has multiple inputs and combo selectbox like this
main_layout = [[sg.Text('First Name', size=(15, 1)),
sg.InputText(key='gname', size=(25, 1))],
[sg.Text('V Type', size=(15, 1)),
sg.Combo(['option 1','option 2','option 3'],key="vtype",size=(25, 1)],
[sg.Text('Last Name', size=(15, 1)),
sg.InputText(key='glastname', size=(25, 1)],
[sg.Submit('Submit'),sg.Cancel('Cancel')]]
layout = [[sg.Column(main_layout,scrollable=True,vertical_scroll_only=True, size=(755,500))]]
window = sg.Window('Form', layout, font='arial',resizable=True, element_justification='l',size=(755,500))
event, values = window.read()
if event == 'Cancel' or event == sg.WIN_CLOSED:
sys.exit()
name_check = window['gname'].get().strip()
if name_check == '':
sg.popup(f"Field is Required")
window.close()
I'm already using name_check = window['gname'].get().strip() for the name event that checks it isn't blank what I want to do is on clicking submit check all inputs to have a value and not to be blank because the code above is a form and the form is long I only wrote few of them for example
The form data will be written into a text file with a regular expression and if the value would be blank the app crashes, so I want something that I can check multiple event keys at once
How can I do that?
Using window.key_dict to get a dictionary with all key:element pairs for all elements, then iterate each item to confirm if it is sg.Input element, and all inputs are not null string.
import PySimpleGUI as sg
sg.theme("DarkBlue3")
sg.set_options(font=("Courier New", 12))
layout = [
[sg.Text(f"Line {i: >2d}:"), sg.Input("")] for i in range(10)] + [
[sg.Button("Submit")],
[sg.StatusBar("", size=(20, 1), key='Status')]
]
window = sg.Window('Title', layout, finalize=True)
prompt = window['Status'].update
input_key_list = [key for key, value in window.key_dict.items()
if isinstance(value, sg.Input)]
while True:
event, values = window.read()
if event == sg.WINDOW_CLOSED:
break
elif event == "Submit":
if all(map(str.strip, [values[key] for key in input_key_list])):
prompt("All inputs are OK !")
else:
prompt("Some inputs missed !")
window.close()
below is my script:
import wolframalpha
client = wolframalpha.Client("LXP5A5-62XJKEY85U")
import PySimpleGUI as sg
sg.theme('DarkPurple') # Add a touch of color
# All the stuff inside your window.
layout = [ [sg.Text('Enter a command'), sg.InputText()],
[sg.Button('Ok'), sg.Button('Cancel')] ]
# Create the Window
window = sg.Window('Sunia', layout)
# Event Loop to process "events" and get the "values" of the inputs
while True:
event, values = window.read()
if event == sg.WIN_CLOSED or event == 'Cancel': # if user closes window or clicks cancel
break
res = client.query(values[0])
try:
print (next(res.results).text)
except:
print ("No results")
window.close()
and here is my error:
res = client.query(values[0])
File "C:\Users\jonathan b\AppData\Local\Programs\Python\Python38-32\lib\site-packages\wolframalpha\__init__.py", line 68, in query
assert resp.headers.gettype() == 'text/xml'
AttributeError: 'HTTPMessage' object has no attribute 'gettype'
I think i understand the error which you are getting its very simple you just have to put the
client = wolframalpha.Client("LXP5A5-62XJKEY85U") before sg.theme('DarkPurple')
import wolframalpha
import PySimpleGUI as sg
client = wolframalpha.Client("LXP5A5-62XJKEY85U")
sg.theme('DarkPurple') # Add a touch of color
# All the stuff inside your window.
layout = [ [sg.Text('Enter a command'), sg.InputText()],
[sg.Button('Ok'), sg.Button('Cancel')] ]
# Create the Window
window = sg.Window('Sunia', layout)
# Event Loop to process "events" and get the "values" of the inputs
while True:
event, values = window.read()
if event == sg.WIN_CLOSED or event == 'Cancel': # if user closes window or clicks cancel
break
res = client.query(values[0])
try:
print (next(res.results).text)
except:
print ("No results")
window.close()