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()
Related
I created a dictionary with two keys, when selecting one of the keys, the dictionary items are updated, the problem is that I am not returning the selected value within the updated list.
for example, when selecting 'male', and then 'Executed', I would like to receive 'Executed' as a value
import PySimpleGUI as sg
genero = {
'male': ['Required','Executed'],
'female': ['Required', 'Performed']
}
layout = [
[sg.Radio('male', "RADIO1", default=False, key="-IN1-")],
[sg.Radio('female', "RADIO1", default=False, key="-IN2-")],
[sg.Listbox(genero.keys(), size=(30, 3), enable_events=True, key='-PART-')],
[sg.Push(),sg.Button('GENERATE'), sg.Exit("Exit")]
]
window = sg.Window("GENERATE PETITION", layout)
while True:
event, values = window.read()
if event == sg.WIN_CLOSED or event == "Exit":
break
elif values["-IN1-"] == True:
window['-PART-'].update(genero['male'])
elif values["-IN2-"] == True:
window['-PART-'].update(genero['female'])
elif event == 'GENERATE':
print('-PART-')
window.close()
print(event,values)
atualmente está retornando assim: Exit {'-IN1-': True, '-IN2-': False, '-PART-': []}
There's programming logic issue in the event loop, it will be better for all the cases starts with the event decision, not the value(s) decision. In your code, the case for the event GENERATE will be never executed after any one of the Radio element clicked.
import PySimpleGUI as sg
genero = {
'male': ['Required','Executed'],
'female': ['Required', 'Performed']
}
layout = [
[sg.Radio('male', "RADIO1", default=False, enable_events=True, key="-IN1-")],
[sg.Radio('female', "RADIO1", default=False, enable_events=True, key="-IN2-")],
[sg.Listbox(genero.keys(), size=(30, 3), enable_events=True, key='-PART-')],
[sg.Push(),sg.Button('GENERATE'), sg.Exit("Exit")]
]
window = sg.Window("GENERATE PETITION", layout)
while True:
event, values = window.read()
if event == sg.WIN_CLOSED or event == "Exit":
break
elif event in ('-IN1-', '-IN2-'):
if values["-IN1-"] == True:
window['-PART-'].update(genero['male'])
else:
window['-PART-'].update(genero['female'])
elif event == 'GENERATE':
selections = values['-PART-']
if selections:
print(selections[0])
else:
print('Nothing selected !')
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 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 am using a GUI to display a countdown timer which will be activated when user click start countdown.
Using another thread to compute the countdown timer , however i only require the latest thread to write on the display, instead of multiple thread writing on the display.
*Button can be clicked multiple time(or used to reset the countdown), just need to show the newest thread data.
import time
import logging
import threading
import PySimpleGUI as sg
cp = sg.cprint
def main():
sg.theme('DarkAmber')
col1 = [[sg.Button('start countdown', button_color='white on green', size=(18, 5), font=('Arial', 30, 'bold'))],
[sg.Button('Buzzer Stop', button_color='red', font=('Arial', 30, 'bold'), size=(18, 5))
]]
col2 = [[sg.Multiline(size=(100, 2), key='-AB-', font=('Arial', 50, 'bold'), reroute_stdout=True, write_only=True,
reroute_cprint=False)],
[sg.Multiline(size=(100, 6), key='-ML-', autoscroll=True, reroute_stdout=True, write_only=True,
reroute_cprint=True)]
]
layout_test = [[sg.Column(col1, element_justification='c'), sg.Column(col2, element_justification='c')]]
window = sg.Window('Counter', layout_test, size=(800, 480))
while True:
event, values = window.read()
cp(event, values)
if event == sg.WIN_CLOSED or event == 'Exit':
break
if event.startswith('start countdown'):
t = 900
t1 = threading.Thread(target=countdown, args=(t, window), daemon=True).start()
if event.startswith('Buzzer Stop'):
threading.Thread(target=Samplingthread, args=(window,), daemon=True).start()
Buzzerflag = 60
window.close()
def countdown(t, window):
while t:
mins, secs = divmod(t, 60)
timer = '{:02d}:{:02d}'.format(mins, secs)
window['-AB-'].print(timer)
time.sleep(1)
t -= 1
if __name__ == '__main__':
main()
Not to update GUI in your thread.
from time import sleep
import threading
import PySimpleGUI as sg
def count_down(window):
count = 100
while count and countdown:
window.write_event_value("COUNT", count)
count -= 1
sleep(1)
def count_up(window):
count = 0
while not countdown:
window.write_event_value("COUNT", count) # CANNOT update GUI in thread
count += 1
sleep(1)
sg.theme('DarkBlue3')
layout = [
[sg.Button('COUNTDOWN'), sg.Button('TIMER')],
[sg.Text('', size=(20, 1), key='LABEL')],
]
window = sg.Window('TITLE', layout, finalize=True)
label = window['LABEL']
countdown = False
while True:
event, values = window.read()
if event == sg.WINDOW_CLOSED:
break
elif event == 'COUNTDOWN':
countdown = True
threading.Thread(target=count_down, args=(window,), daemon=True).start()
elif event == 'TIMER':
countdown = False
threading.Thread(target=count_up, args=(window,), daemon=True).start()
elif event == 'COUNT':
label.update(value=values[event])
countdown = not countdown
sleep(1)
window.close()
how can i comment/uncomment a line of code by checking and unchecking a checkbox in python with PySimpleGUI?
also i don't know if i wrote the code in correct way but i'm just trying to comment a line of code by checking the checkbox
any other way to do it is also fix my problem
This is my code
layout = [[sg.Text('Choose Options'))],
[sg.Checkbox('Save Posts',key="save-ed")],
[sg.Submit('Next')) ,sg.Cancel("Cancel"))] ]
window = sg.Window('my bot', layout, icon="logo.ico")
event, values = window.read()
window.close()
while True:
event, values = window.read()
if event == sg.WIN_CLOSED or event == "Cancel":
break
elif values['save-ed'] == True:
save_input = ['usersave']
elif values['save-ed'] == False:
save_input = ['#usersave']
and this is the code which i want to comment or uncomment with checkbox
try:
save_input = webdriver.find_element_by_xpath('/html/body/div[4]/div[2]/div/article/div[3]/section[1]/span[4]/div/div/button/div')
save_input.click()
sleep(randint(4,5))
except NoSuchElementException:
pass
Following code show how to stop a thread to update time by a checkbox.
from datetime import datetime
from time import sleep
import threading
import PySimpleGUI as sg
def clock(window):
now = None
while timer:
new = datetime.now().strftime("%Y-%m-%d %H:%M:%S")
if new != now:
now = new
if flag:
window.write_event_value('CLOCK', now)
sleep(0.1)
sg.theme("DarkBlue3")
sg.set_options(font=("Courier New", 16))
layout = [
[sg.Text("", size=(0, 1), key='TIME')],
[sg.Checkbox("Time ON", default=True, enable_events=True, key='TIME ON')],
]
window = sg.Window('Title', layout, finalize=True)
timer, flag = True, True
threading.Thread(target=clock, args=(window,), daemon=True).start()
while True:
event, values = window.read()
if event == sg.WINDOW_CLOSED:
timer = False
break
elif event == 'TIME ON':
flag = values[event]
elif event == 'CLOCK':
window['TIME'].update(values[event])
window.close()
according to previous comment and answer by #jason-yang
i got the point and changed the code like this and fixed my problem
layout = [[sg.Text('Choose Options'))],
[sg.Checkbox('Save Posts',key="save-ed")],
[sg.Submit('Next')) ,sg.Cancel("Cancel"))] ]
window = sg.Window('my bot', layout, icon="logo.ico")
event, values = window.read()
window.close()
while True:
event, values = window.read()
if event == sg.WIN_CLOSED or event == "Cancel":
break
if event == "save posts":
if values['save-ed'] == True:
save_input = values['usersave']
elif values['save-ed'] == False:
save_input = values['#usersave']
the rest of the code seems to be correct and i leave it unchanged
try:
save_input = webdriver.find_element_by_xpath('/html/body/div[4]/div[2]/div/article/div[3]/section[1]/span[4]/div/div/button/div')
save_input.click()
sleep(randint(4,5))
except NoSuchElementException:
pass