I want to create a progress bar using PySimpleGUI but I want the user to put the maximum of the progress bar.
this is my code:
import PySimpleGUI as sg
import random, time
sg.theme("LightBlue")
progress_value=input()
layout = [[sg.Text("Enter a number out of 50", font='Lucida'),
sg.InputText(key='-PROGRESS_VALUE-', font='Lucida, 20', size=(20, 40))],
[sg.ProgressBar(progress_value, orientation='h', size=(100, 20), border_width=4, key='-PROGRESS_BAR-',
bar_color=("Blue", "Yellow"))],
[sg.Button('Change Progress'), sg.Exit(),sg.Button('Stop Progress')]]
window = sg.Window("Progress Bar", layout)
while True:
event, values = window.read()
if event == 'Exit' or event == sg.WIN_CLOSED:
break
progress_value = int(values['-PROGRESS_VALUE-'])
if event == "Change Progress":
for i in range(progress_value):
event, values = window.read(1000)
if event == "Stop Progress":
window['-PROGRESS_BAR-'].update(i-1)
break
window['-PROGRESS_BAR-'].update(max=progress_value)
window['-PROGRESS_BAR-'].update(i+1)
window.close()
as you can see the maximum which is "progress_value" is given by an input (progress_value=input())
but i want it to come from the input text of the user (sg.InputText(key='-PROGRESS_VALUE-', font='Lucida, 20', size=(20, 40))) and that value will be set to progress_value
Here's one way of doing what you're after using a single event loop
When changing the max value of a ProgressBar, you must set a current value too (in the same update call).
import PySimpleGUI as sg
sg.theme("LightBlue")
progress_value = 50
layout = [[sg.Text("Enter a number out of 50", font='Lucida'),
sg.InputText(key='-PROGRESS_VALUE-', font='Lucida, 20', size=(20, 40))],
[sg.ProgressBar(progress_value, orientation='h', size=(100, 20), border_width=4, key='-PROGRESS_BAR-',
bar_color=("Blue", "Yellow"))],
[sg.Button('Change Progress'), sg.Button('Start Progress'), sg.Button('Stop Progress')]]
window = sg.Window("Progress Bar", layout)
progress_started, counter, timeout = False, 0, None
while True:
event, values = window.read(timeout=timeout)
if event == 'Exit' or event == sg.WIN_CLOSED:
break
if event == "Change Progress":
progress_value = int(values['-PROGRESS_VALUE-'])
# NOTE - must set a current count when changing the max value
window['-PROGRESS_BAR-'].update(current_count= 0, max=progress_value)
elif event == 'Start Progress':
progress_started = True
counter = 0
timeout = 1000
elif event == 'Stop Progress':
progress_started = False
timeout = None
if progress_started:
window['-PROGRESS_BAR-'].update(counter)
counter += 1
if counter > progress_value:
progress_started = False
window.close()
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 been trying to integrate a new page into a project i am doing.
import PySimpleGUI as sg
import os
def page2b():
company_list_column = [
[sg.Text('Pick your company name')],
[sg.Listbox(os.listdir("C:\/FYP\/GUI\/Companies"), size=(25, 5), key='-EC-', enable_events=True)]
]
company_column = [
[sg.Text(size=(40,1), key='-Company Selected-')],
[sg.Text(size=(40,1), key='-Folder Selected-')],
]
layout = [
[sg.Text('Select your Company', justification='center',font=("Arial",22))],
[
sg.Column(company_list_column),
sg.VSeparator(),
sg.Column(company_column),
],
[sg.Button('Select Company'), sg.Button('Close')]
]
return sg.Window('Baseline Analyzer', layout, default_element_size=(100, 1), auto_size_buttons=False,
default_button_element_size=(12, 1), size=(600,270))
window= page2b()
while True: # the event loop
event, values = window.read()
if event == sg.WIN_CLOSED or event == "Close":
break
if values['-EC-']: # if something is highlighted in the list
window['-Company Selected-'].update(f"Company selected: {values['-EC-'][0]}")
window['-Folder Selected-'].update(f"Your folder is: C:\FYP\GUI\Companies\{values['-EC-'][0]}")
if event == "Select Company": #The path of the folder to store the things at
word= {values['-EC-'][0]}
word = "".join(word)
foldername = "C:\FYP\\GUI\\Companies\\" + word
break
window.close()
In summary, this would display a list of company folders for me to choose from and when i click on an folder, i would see what is indeed the selected folder, as exampled in the below screenshot:
As a standalone progam, the above page works absolutely fine. However, the moment i try to integrate it into my main program, as evidenced down below:
from tkinter.constants import UNDERLINE
from tkinter.font import BOLD, ITALIC
import PySimpleGUI as sg
from datetime import datetime, date, time
import time
import csv
import pandas as pd
import os
from stat import S_IREAD, S_IRGRP, S_IROTH
sg.ChangeLookAndFeel('DarkTeal9')
# ------ Menu Definition ------ #
menu_def = [
['Company Selection',['New Company','Existing Company']],
['Help',['How to use']]
]
menu_def2 = [
['Scan Management', ['Start Audit Task']],
['Baseline Management', ['View Baselines'] ],
['Help', ['How to Use']]
]
# ------ Functions Defintion ------ #
def clear_input():
for key in values:
if key != 'Import Host':
window[key]('')
return None
def folder_gen():
clientFolder = os.mkdir(values['New Client Name'])
# ------ GUI Defintion ------ #
def page1():
layout = [
[sg.Menu(menu_def)],
[sg.Text('Welcome to the Baseline Analyzer!', justification='center',font=("Arial",25, BOLD))],
[sg.Button('New Company')],
[sg.Button('Existing Company')],
[sg.Button('Exit')],
]
return sg.Window('Baseline Analyzer', layout,element_justification='c', default_element_size=(100, 1), auto_size_text=False, auto_size_buttons=False,
default_button_element_size=(25, 3), size=(600,270), finalize=True)
def page_2a():
layout = [
[sg.Text('New Company Name: ', size=(20,1)), sg.InputText(key='New Client Name')],
[sg.Text('Date of Registration: ', size=(20,1)), sg.InputText(key='Date')],
[sg.Text('Location of Site: ', size=(20,1)), sg.InputText(key='Location')],
[sg.Text('Department: ', size=(20,1)), sg.InputText(key='Department')],
[sg.Text('Company Liaison Name: ', size=(20,1)), sg.InputText(key='Liaison')],
[sg.Text('Company Liaison Email: ', size=(20,1)), sg.InputText(key='Contact')],
[sg.Text('Company Liaison Number: ', size=(20,1)), sg.InputText(key='Number')],
[sg.Button('Create Company'), sg.Button('Clear'), sg.Exit()]
]
return sg.Window('Generate Client Profile', layout,element_justification='c', default_element_size=(100, 1), auto_size_text=False, auto_size_buttons=False,
default_button_element_size=(12, 1), size=(600,270), finalize=True)
def page2b():
company_list_column = [
[sg.Text('Pick your company name')],
[sg.Listbox(os.listdir("C:\/FYP\/GUI\/Companies"), size=(25, 5), key='-EC-', enable_events=True)]
]
company_column = [
[sg.Text(size=(40,1), key='-Company Selected-')],
[sg.Text(size=(40,1), key='-Folder Selected-')],
]
layout = [
[sg.Text('Select your Company', justification='center',font=("Arial",22))],
[
sg.Column(company_list_column),
sg.VSeparator(),
sg.Column(company_column),
],
[sg.Button('Select Company'), sg.Button('Close')]
]
return sg.Window('Baseline Analyzer', layout, default_element_size=(100, 1), auto_size_buttons=False,
default_button_element_size=(12, 1), size=(600,270), finalize=True)
window1, window2= page1(), None
# ------ Loop & Process button menu choices ------ #
# ------ Process menu choices ------ #
while True:
window, event, values = sg.read_all_windows()
if event == sg.WIN_CLOSED or event == 'Exit'or event =='Close':
window.close()
if window == window2:
window2 = None
elif window == window1:
break
# Clear New Scan form inputs
elif event == 'Clear':
clear_input()
#Exisiting Company selection page
if event == 'New Company':
window = page_2a()
elif event == 'Existing Company':
window = page2b()
if values['-EC-']: # if something is highlighted in the list
window['-Company Selected-'].update(f"Company selected: {values['-EC-'][0]}")
window['-Folder Selected-'].update(f"Your folder is: C:\FYP\GUI\Companies\{values['-EC-'][0]}")
if event == "Select Company": #The path of the folder to store the things at
word= {values['-EC-'][0]}
word = "".join(word)
foldername = "C:\FYP\\GUI\\Companies\\" + word
window.close()
I am presented with this "keyError" and have been racking my head on how to solve it
Traceback (most recent call last):
File "c:\Users\******\Documents\******\******\testing.py", line 140, in <module>
if values['-EC-']: # if something is highlighted in the list
KeyError: '-EC-'
Is there a solution to my predicament?
Line window = page2b() creates new window but it doesn't update values in window, event, values - it would need to run again sg.read_all_windows()
So you should run if values['-EC-'] directly in while True. But it will be execute for every window so you would have to check if '-EC-' in values and values['-EC-'] or you would have to check if window == window2 but it needs also use window2 = page2b() instead of window = page2b() or even better window2b = page2b() to recognize if you run page2a or page2b
# ---
window1 = page1()
window2a = None
window2b = None
while True:
window, event, values = sg.read_all_windows()
#print('window:', window)
#print('event:', event)
#print('values:', values)
if event == sg.WIN_CLOSED or event == 'Exit'or event =='Close':
window.close()
if window == window2a:
window2a = None
elif window == window2b:
window2b = None
elif window == window1:
break
elif event == 'Clear':
clear_input()
# - events, values unique for every window -
if window == window1:
if event == 'New Company':
window2a = page_2a()
elif event == 'Existing Company':
window2b = page2b()
elif window == window2a:
# ... code ...
pass
elif window == window2b:
if values['-EC-']:
window['-Company Selected-'].update(f"Company selected: {values['-EC-'][0]}")
window['-Folder Selected-'].update(f"Your folder is: C:\FYP\GUI\Companies\{values['-EC-'][0]}")
if event == "Select Company":
word = {values['-EC-'][0]}
word = "".join(word)
foldername = "C:\FYP\\GUI\\Companies\\" + word
window.close()
Or even
window1 = page1()
window2a = None
window2b = None
while True:
window, event, values = sg.read_all_windows()
#print('window:', window)
#print('event:', event)
#print('values:', values)
if window == window1:
if event == sg.WIN_CLOSED or event == 'Exit'or event =='Close':
window.close()
break
elif event == 'New Company':
window2a = page_2a()
elif event == 'Existing Company':
window2b = page2b()
elif window == window2a:
if event == sg.WIN_CLOSED or event == 'Exit'or event =='Close':
window.close()
window2a = None
elif event == 'Clear':
clear_input()
elif window == window2b:
if event == sg.WIN_CLOSED or event == 'Exit'or event =='Close':
window.close()
window2b = None
elif values['-EC-']:
window['-Company Selected-'].update(f"Company selected: {values['-EC-'][0]}")
window['-Folder Selected-'].update(f"Your folder is: C:\FYP\GUI\Companies\{values['-EC-'][0]}")
elif event == "Select Company":
word = {values['-EC-'][0]}
word = "".join(word)
foldername = "C:\\FYP\\GUI\\Companies\\" + word
EDIT:
Other idea is to create for every window new while-loop but sometimes it may work different then previous version. When window2 is opened then it blocks buttons in window1 so you can't open two windows 2 at the same time. Previous version can open New Company','Existing Company at the same time - it may even open many Existing Company and many 'New Company at the same time. This version can open only one 'New Company or only one Existing Company and it can open New Company','Existing Company at the same time.
And in new version you can't use Exit in window1 when window2 is open.
I changed path in listdir() to run it on my system.
from tkinter.constants import UNDERLINE
from tkinter.font import BOLD, ITALIC
import PySimpleGUI as sg
from datetime import datetime, date, time
import time
import csv
import pandas as pd
import os
from stat import S_IREAD, S_IRGRP, S_IROTH
sg.ChangeLookAndFeel('DarkTeal9')
# ------ Menu Definition ------ #
menu_def = [
['Company Selection',['New Company','Existing Company']],
['Help',['How to use']]
]
menu_def2 = [
['Scan Management', ['Start Audit Task']],
['Baseline Management', ['View Baselines'] ],
['Help', ['How to Use']]
]
# ------ Functions Defintion ------ #
def clear_input():
for key in values:
if key != 'Import Host':
window[key]('')
return None
def folder_gen():
clientFolder = os.mkdir(values['New Client Name'])
# ------ GUI Defintion ------ #
def page1():
layout = [
[sg.Menu(menu_def)],
[sg.Text('Welcome to the Baseline Analyzer!', justification='center',font=("Arial",25, BOLD))],
[sg.Button('New Company')],
[sg.Button('Existing Company')],
[sg.Button('Exit')],
]
window = sg.Window('Baseline Analyzer', layout,element_justification='c', default_element_size=(100, 1), auto_size_text=False, auto_size_buttons=False,
default_button_element_size=(25, 3), size=(600,270), finalize=True)
while True:
event, values = window.read()
#print('window:', window)
#print('event:', event)
#print('values:', values)
if event == sg.WIN_CLOSED or event == 'Exit'or event =='Close':
window.close()
return
elif event == 'New Company':
page_2a()
elif event == 'Existing Company':
page2b()
def page_2a():
layout = [
[sg.Text('New Company Name: ', size=(20,1)), sg.InputText(key='New Client Name')],
[sg.Text('Date of Registration: ', size=(20,1)), sg.InputText(key='Date')],
[sg.Text('Location of Site: ', size=(20,1)), sg.InputText(key='Location')],
[sg.Text('Department: ', size=(20,1)), sg.InputText(key='Department')],
[sg.Text('Company Liaison Name: ', size=(20,1)), sg.InputText(key='Liaison')],
[sg.Text('Company Liaison Email: ', size=(20,1)), sg.InputText(key='Contact')],
[sg.Text('Company Liaison Number: ', size=(20,1)), sg.InputText(key='Number')],
[sg.Button('Create Company'), sg.Button('Clear'), sg.Exit()]
]
window = sg.Window('Generate Client Profile', layout,element_justification='c', default_element_size=(100, 1), auto_size_text=False, auto_size_buttons=False,
default_button_element_size=(12, 1), size=(600,270), finalize=True)
while True:
event, values = window.read()
#print('window:', window)
#print('event:', event)
#print('values:', values)
if event == sg.WIN_CLOSED or event == 'Exit'or event =='Close':
window.close()
return
elif event == 'Clear':
clear_input()
def page2b():
company_list_column = [
[sg.Text('Pick your company name')],
[sg.Listbox(os.listdir(), size=(25, 5), key='-EC-', enable_events=True)]
]
company_column = [
[sg.Text(size=(40,1), key='-Company Selected-')],
[sg.Text(size=(40,1), key='-Folder Selected-')],
]
layout = [
[sg.Text('Select your Company', justification='center',font=("Arial",22))],
[
sg.Column(company_list_column),
sg.VSeparator(),
sg.Column(company_column),
],
[sg.Button('Select Company'), sg.Button('Close')]
]
window = sg.Window('Baseline Analyzer', layout, default_element_size=(100, 1), auto_size_buttons=False,
default_button_element_size=(12, 1), size=(600,270), finalize=True)
while True:
event, values = window.read()
#print('window:', window)
#print('event:', event)
#print('values:', values)
if event == sg.WIN_CLOSED or event == 'Exit'or event =='Close':
window.close()
return
elif values['-EC-']:
window['-Company Selected-'].update(f"Company selected: {values['-EC-'][0]}")
window['-Folder Selected-'].update(f"Your folder is: C:\FYP\GUI\Companies\{values['-EC-'][0]}")
if event == "Select Company":
word = {values['-EC-'][0]}
word = "".join(word)
foldername = "C:\\FYP\\GUI\\Companies\\" + word
# --- start ---
page1()
Good day all,
I have been working on creating a GUI for my Tic Tac Toe game using PySimpleGUI. My code is as follow:
import PySimpleGUI as sg
import random
board_layout1 = {(2,0):" ", (2,1):" ", (2,2): " ", (1,0): " ", (1,1): " ", (1,2): " ", (0,0): " ", (0,1): " ", (0,2): " "}
Board layout is based on:
Diagram
I then created an interface to take in user input (i.e. name and choosing X or O symbol).
layout = [
[sg.Text("Please enter your Name and your opponent's name")],
[sg.Text('Name', size=(15, 1)), sg.InputText('')],
[sg.Text('Name of opponent', size=(15, 1)), sg.InputText('')],
[sg.Frame(layout=[
[sg.Radio('X', "RADIO1", default=True, size=(10,1)), sg.Radio('O', "RADIO1")]], title='Options',title_color='red', relief=sg.RELIEF_SUNKEN, tooltip='Use these to set flags')],
[sg.Submit(), sg.Cancel()]
]
window = sg.Window('Tic Tac Toe Game').Layout(layout)
button, events = window.Read()
print(events)
window.close()
player1, player2, player1_event, player2_event = events[0], events[1], events[2], events[3]
player1 and player2 will return their names. Player1_event and player2_event will return True or False. As I am using a checkbox, events2 will be True if I checked it while events[3] will be False.
I then assign the marker respectively.
if player1_event == True:
player1_marker, player2_marker = ("X", "O")
else:
player1_marker, player2_marker = ("O", "X")
Now, I will create the GUI for the board.
def board_gui():
max_row = max_col = 3
layout = [[sg.Button(' ', size=(8, 4), key=(i,j), pad=(0,0)) for j in range(max_col)] for i in range(max_col)]
window = sg.Window('Tictactoe', layout)
button, events = window.Read()
return button
window.close()
Next (where the problem is), I created the function to update the board accordingly. So let's say if play1 starts first and he decided to choose 'X' as his marker. He picked the first grid and click on it. It marks 'X'. So the next click should belong to play2, whose marker is 'O'. My code seems to have issue updating the marker for the second click.
What I did:
def board_gui_update(marker):
max_row = max_col = 3
layout = [[sg.Button(' ', size=(8, 4), key=(i,j), pad=(0,0)) for j in range(max_col)] for i in range(max_col)]
window = sg.Window('Tictactoe', layout)
while True:
button, events = window.Read()
if button in (None, 'Exit'):
break
window[button].update(marker)
window.close()
What I have tried:
def board_gui_update(marker):
max_row = max_col = 3
layout = [[sg.Button(' ', size=(8, 4), key=(i,j), pad=(0,0)) for j in range(max_col)] for i in range(max_col)]
window = sg.Window('Tictactoe', layout)
while True:
button, events = window.Read()
if button in (None, 'Exit'):
break
if marker == player1_marker:
turn = player1
if turn == player1:
window[button].update(player1_marker)
turn = player2
else:
window[button].update(player2_marker)
else:
if marker == player2_marker:
turn = player2
if turn == player2:
window[button].update(player2_marker)
turn = player1
else:
window[button].update(player1_marker)
window.close()
Doesn't seem to work here as well. I have looked into the documentations and also solutions that involved tkinter but nothing seems to be able to update the marker.
You can view the issue in this snapshot.
See if this does what you're after. Every time you click on a square, it will change to a new marker. I think you're saying you cannot change the value shown on the button. This program shows you how to do it.
import PySimpleGUI as sg
layout = [[sg.B(' ', size=(8,4), key=(i,j)) for i in range(3)] for j in range(3)]
window = sg.Window('Tic Skeleton', layout)
while True: # Event Loop
event, values = window.read()
print(event, values)
if event in (None, 'Exit'):
break
current_marker = window[event].get_text()
window[event].update('X' if current_marker == ' ' else 'O' if current_marker == 'X' else ' ')
window.close()
Based on the samples above, I made this code wich can alternate between the 'O' and 'X'.
I used a variable that alternates between False and True, and two ifs that identifies the values inside window[event].get_text(), analysis it and changes the variable.
import PySimpleGUI as sg
layout = [[sg.Button(' ', size=(8,4)), sg.Button(' ', size=(8,4)),
sg.Button(' ', size=(8,4))],
[sg.Button(' ', size=(8,4)), sg.Button(' ', size=(8,4)),
sg.Button(' ', size=(8,4))],
[sg.Button(' ', size=(8,4)), sg.Button(' ', size=(8,4)),
sg.Button(' ', size=(8,4))]]
turn = True
window = sg.Window('Tic Tac Toe', layout)
while True: # Event Loop
event, values = window.read()
print(event, values) #Just for development purposes.
if event in (None, 'Exit'):
break
current_marker = window[event].get_text()
# I placed all updates conditionals inside this, works better than
# individuals 'ifs' for each of they.
window[event].update('X' if current_marker == ' ' and
turn == True else 'O' if current_marker == ' ' and
turn == False else 'X' if current_marker == 'X'
else 'O' if current_marker == 'O' else ' ')
# The conditionals that change which value should be inserted.
if window[event].get_text() == 'X':
turn = False
elif window[event].get_text() == 'O':
turn = True
window.close()