Stopping Statement Execution Until true - python

I am trying to handle user input using pysimplegui.
If the user enters any value in the input box I need to make sure it's an integer type.
If successful, I need to replace user input value with default value for it.
I tried to use try except within a while loop. My concern here is if the user enters a string value I need to give a retry option.
However, the if else block below the try block is getting executed.
How can I make sure to give the option for the user to retry entering a value?
import PySimpleGUI as sg
sg.theme('SandyBeach')
layout = [
[sg.Text('Please enter your Phone')],
[sg.Text('Phone', size=(15, 1)), sg.InputText(key="lp1", do_not_clear=False)],
[sg.Button("e"), sg.Quit()]
]
window = sg.Window('Simple data entry window', layout)
while True:
event, values = window.read()
if event in (sg.WINDOW_CLOSED, "Quit"):
break
elif event == "e":
text = values['lp1']
log_timer = 1200
user_input = None
if text == '':
log_timer = 1200
else:
while True:
try:
user_input = int(text)
break
except ValueError:
sg.popup_error("Only Integer Allowed")
break
I need to stop the below block if a string value is entered.
if type(user_input) == int:
log_timer = user_input
print(log_timer)
elif log_timer == 1200:
print("no cha")
window.close()

There is a lot of noise in your code.
When you reduce it to only what you need it becomes a lot clearer.
import PySimpleGUI as sg
sg.theme('SandyBeach')
layout = [
[sg.Text('Please enter your Phone')],
[sg.Text('Phone', size=(15, 1)), sg.InputText(key="lp1", do_not_clear=False)],
[sg.Button("e"), sg.Quit()]
]
window = sg.Window('Simple data entry window', layout)
# Add some defaults for user_input and log_timer
user_input = None
log_timer = 1200
while True:
event, values = window.read()
text = values['lp1']
# break on Quit
if event in (sg.WINDOW_CLOSED, "Quit"):
break
elif event == "e" and text != '':
# Attempt to convert to int
try:
user_input = int(text)
except ValueError:
sg.popup_error("Only Integers Allowed")
# If the attempt was unsuccessful user_input will remain None
if user_input is not None:
# the only place log_timer is changed from the default
log_timer = user_input
break
print(log_timer)
window.close()
The two breaks in your code mean it will only stop running on 2 conditions.
A valid number is entered. Or the quit button was pressed.
Having one place that log_timer is reassigned means the only way it can change from the default is if a valid number is entered.
There are obviously improvements to be made once you learn functions and so on. But this is a good starting point.

Related

Get event to run when Input in empty

I want an event to run when I type in the input, that works.
But only when I type something, not when the field is empty, I want that too
Here's a little template code I wrote that resembles my issue
import PySimpleGUI as sg
list1 = ['a', 'b', 'c']
matches = []
out = []
layout = [
[sg.InputText('', key='-search-', change_submits=True)],
[sg.Listbox(values=out, key='-list-', size=(10,10))]
]
window = sg.Window('Search', layout, size=(300, 300))
while True:
event, values = window.read()
if values['-search-']:
SearchTerm = values['-search-']
SearchTerm.replace("['", "")
SearchTerm.replace("']", "")
print("Search Term = " + SearchTerm)
if SearchTerm == "":
out = list1
window.Element('-list-').Update(values=list1)
if SearchTerm != "":
for i in list1:
if SearchTerm in i:
if i not in matches:
matches.append(i)
outlist = matches
window.Element('-list-').Update(values=outlist)
if event == sg.WIN_CLOSED or event == 'Exit':
break
There's re lot of events in event loop, so you have to decide how to check what the event is. For example, if values['-search-']: will be failed it you close the window and values maybe None, then you will get exception TypeError: 'NoneType' object is not subscriptable.
In your event loop, you didn't check the case values['-search-']=='', but just check SearchTerm == "" under the event values['-search-']!=''.
The pattern for event loop maybe like this
while True:
event, values = window.read()
if event in (sg.WIN_CLOSED, 'Exit'):
break
if event == '-search-':
if values[event]:
""" Code if Input element not empty """
else:
""" Code if Input element is empty """
window.close()

Calculator in PySimpleGUI

I have a simple calculator with a fixed constant and another entry to be added to the constant. I am struggling to deal with these entries(VARIABLE) being negative ie -1234 since i cast an int() on the input so clearly this leads to problems when trying to calculate the sum.
import PySimpleGUI as sg
columns = ["FIXED","VARIABLE","RESULT"]
param = (20,3) # size of the main window
def CALCULATOR():
sg.theme('Dark Brown 1')
listing = [sg.Text(u, size = param) for u in columns]
core = [
sg.Input(f"{10}", size = param),
sg.Input(size = param,enable_events=True,key='NUMBER'),
sg.Input(size = param)]
mesh = [[x,y] for (x,y) in list(zip(listing, core))]
window = sg.Window('CALCULATOR', mesh, font='Courier 12').Finalize()
while True:
event, values = window.read()
if event == sg.WINDOW_CLOSED:
break
elif event == "SEND":
break
elif event == "NUMBER":
variable = int(values['NUMBER'])
fixed= int(values[0])
for element, value in zip(core[2:], [variable+fixed]):
element.update(value=value)
else:
print("OVER")
window.close()
CALCULATOR()
You can wrap your if-statements in a try-except statement, and then handle the updates for when there is a ValueError:
while True:
event, values = window.read()
try:
if event == sg.WINDOW_CLOSED:
break
elif event == "SEND":
break
elif event == "NUMBER":
variable = int(values['NUMBER'])
fixed = int(values[0])
core[2].update(variable+fixed)
else:
print("OVER")
except ValueError:
core[2].update("ValueError!")
The above code "catches" the ValueError that is triggered once you input something that doesn't translate well into an integer, after that you can then update the field to inform the user why the results didn't output.

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

Loop Input until Parameter is met or User Input

I want my program to either wait 10 seconds before moving on, or break the loop by user input
try:
while True:
afkseconds = 0
time.sleep(1)
afkseconds +=1
if afkseconds == 10:
Timer()
except KeyboardInterrupt:
pass
newTaskIO = input('Y/N: ')
newTaskIO = newTaskIO.lower()
if newTaskIO == 'y':
taskName = input('Enter the name of the task: ')
taskDescription = input('Enter a brief description, or press enter to continue: ')
The program enters the while Loop, adding a second to the "afksecond" variable. The idea is once the afksecond variable = 10, the loop breaks and performs the specified function.
Either that or the user enters "y" or "n" to break the loop and continue with the next phase of the program. I cannot figure out the logic to get this to work. Please advicse

Python not reading string a second time

I'm writing a text adventure (does anyone remember Zork?), and I'm having troubles with this code:
from random import randint
def prompt():
action = input(">>> ").lower()
if action == "exit":
quit()
elif action == "save":
save()
else:
return action
def action_error(custom=False):
if custom != False:
print(custom)
else:
phrases = ["A bunch", "of funny", "error phrases"]
print(phrases[randint(1, len(phrases)-1)])
return prompt()
action = prompt()
while True:
print(action) #Debugging purposes
if action.find("switch") != -1:
if action.find("light") != -1:
second_room() #Story continues
else:
action = action_error("What do you want to switch?")
action = action_error()
The matter is that if I enter a string that contains "switch", the next input is not picked up.
Also, anyone has better ways to parse verb-noun strings like "switch the light", "open the door" or "look around"/"look at OBJECT"?
First of all I noticed that if you enter switch twice the second time it's caught as an error by your program.
I think the problem lies at the end of the action_error function where you assign the return value to prompt(), so the input get consumed too early.
A possible fix would be:
def action_error(custom=False):
if custom != False:
print(custom)
else:
phrases = ["A bunch", "of funny", "error phrases"]
print(phrases[randint(1, len(phrases)-1)])
while True:
action = prompt()
print(action) #Debugging purposes
if action.find("switch") != -1:
if action.find("light") != -1:
second_room() #Story continues
else:
action_error("What do you want to switch?")
else:
action_error()
So no return value for action_error() and direct assignment at the beginning of the while loop.
How about, in the case of a partially entered compound action, you concatenate the new input to the old one? Then "switch" becomes "switch light", and both of your conditionals will pass.
action = prompt()
while True:
print(action) #Debugging purposes
if action.find("switch") != -1:
if action.find("light") != -1:
second_room() #Story continues
else:
action = action + " " + action_error("What do you want to switch?")
continue
action = action_error()
Bonus style suggestions:
replace a.find("b") != -1 with "b" in a
use random.choice(phrases) instead of phrases[randint(1, len(phrases)-1)]

Categories

Resources