PySimpleGUI changing visibility breaks columns(?) - python

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()

Related

Switch window in PySimpleGUI with keyboard input (left/right arrow)

I have 3 windows in terms of sg.Frame and would like to switch the windows via keyboard input. However the window does not respones while the buttons work well.
layout = [
[
sg.Column(layout1, key='-COL1-'), # layoutX is a page interms of sg.Frame
sg.Column(layout2, visible=False, key='-COL2-'),
sg.Column(layout3, visible=False, key='-COL3-')
],
[
# sg.Button('Cycle Layout'),
sg.Button('-PREV-'),
sg.Button('1'),
sg.Button('2'),
sg.Button('3'),
sg.Button('-NEXT-'),
# sg.Button('Exit')
]
]
window = sg.Window('Swapping the contents of a window', layout) #, size = (1024, 800)
layout = 1 # The currently visible layout
while True:
event, values = window.read()
print(event, values)
if event in (None, 'Exit'):
break
window.bind('<Right>', '-NEXT-')
window.bind('<Left>', '-PREV-')
window.bind('<Down>', 'Exit')
if event == '-NEXT-' and layout < 3:
window[f'-COL{layout}-'].update(visible=False)
layout = layout + 1
window[f'-COL{layout}-'].update(visible=True)
elif event == '-PREV-' and layout > 1:
window[f'-COL{layout}-'].update(visible=False)
layout -= 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()
How can I modify? Thanks very much!
The statements for binding the keyboards should be placed after window finalized and before your event loop, then it will work before your event loop start.
window = sg.Window('Swapping the contents of a window', layout, finalize=True) #, size = (1024, 800)
window.bind('<Right>', '-NEXT-')
window.bind('<Left>', '-PREV-')
window.bind('<Down>', 'Exit')

How to put the column of checkboxes on the right hand side of the window?

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

python pysimpleGUI changing keep on Top

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

Can I display prints using PySimpleGUI?

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.

How do I respond to window resize in PySimpleGUI

How can I get notified when the window is resized in PySimpleGUI?
I have a window that enables resize events, but I'm not finding a way to move the elements around when that resize occurs, so my window renames top left centered the same size when the window changes size.
Here is the basic code:
import PySimpleGUI as sg
layout = [[sg.Button('Save')]]
window = sg.Window('Window Title',
layout,
default_element_size=(12, 1),
resizable=True) # this is the change
while True:
event, values = window.read()
if event == 'Save':
print('clicked save')
if event == sg.WIN_MAXIMIZED: # I just made this up, and it does not work. :)
window.maximize()
if event == sg.WIN_CLOSED:
break
Adding tkinter events to windows results in callback on change of windows size
import PySimpleGUI as sg
layout = [[sg.Button('Save')]]
window = sg.Window('Window Title',
layout,
default_element_size=(12, 1),
resizable=True,finalize=True) # this is the chang
window.bind('<Configure>',"Event")
while True:
event, values = window.read()
if event == 'Save':
print('clicked save')
if event == "Event":
print(window.size)
if event == sg.WIN_CLOSED:
print("I am done")
break
You need to bind "<Configure>" event to check zoomed event.
import PySimpleGUI as sg
layout = [[sg.Text('Window normal', size=(30, 1), key='Status')]]
window = sg.Window('Title', layout, resizable=True, finalize=True)
window.bind('<Configure>', "Configure")
status = window['Status']
while True:
event, values = window.read()
if event == sg.WINDOW_CLOSED:
break
elif event == 'Configure':
if window.TKroot.state() == 'zoomed':
status.update(value='Window zoomed and maximized !')
else:
status.update(value='Window normal')
window.close()

Categories