Showing messages in tkinter (1st question)
To show the user basic massages and get basic options (show an error, ask OK/Cancel or yes/no...) you can use tkinter.messagebox
. It provides show*()
and ask*()
functions. In your case, showerror()
or showwarning()
is probably best.
To get basic input, tkinter.simpledialog
can be used. It provides the functions askinteger
, askfloat
and askstring
that will ask the user for the respective data type.
To get file (path) input, use tkinter.filadialog
.
For more complex situations, it is best you use the tkinter.Toplevel
widget.
2nd question
Your code
I am going to play interpreter and go through your code. If you just want the solutions (not recommended), jump below.
firstname = Entry(...) => create an Entry widget and assign it to firstname
firstname.grid(...) => put the widget in/on the window
firstname = firstname.get() => get the text currently in the widget and assign it to firstname.
OK, you want to get the text. Just, the window isn't even visible yet. These instructions will work in the IDLE shell, because of special reasons and you wait to call .get()
until you typed your name. In "real" execution, the interpreter won't wait and your user can't type (because there isn't a window) before you call .mainloop()
. One solution, if you read above, is to use simpledialog
. But also this should run after the GUI started, i.e. after .mainloop()
is called. I'll get to that part later.
-- same for surname --
Your validation
Interpreter:
number = Entry(...) => create a new Entry widget and assign it to number
number.grid(...) => show it
# while True here
# try here
number = number.get() => call number.get() and assign the value (a str) to number -- keep that in mind
# if condidtion below
number > 10 => check if a str is larger/greater than an int; can't do that, raise a TypeError
# error -> go to the except
print("I asked how to do this on SO") => show this (in the console); in future hopefully via messagebox
continue => go to the beginning of the loop
# in try
number = number.get() => call the .get() method of the str number; can't find it, raise an AttributeError
# error -> go to the except
print(...) => as before
continue => as before
You get caught in an infinite loop of exception that won't stop even if the user enters a correct number (which can't happen anyway, we don't have a window yet). This is a very good reason for avoiding a bare except
- you will also catch lots of stuff you don't want.
Why the method you are trying to use wooooould work (you said you found it here -- do you still have a link or remember the title?):
Code (this example in the console for simplicity):
while True:
try:
value = int(input())
if not 0<value<10:
1/0
except ZeroDivisionError: # let ValueError through (you willl want to catch it separately)
print('by executing 1/0, I raised a ZeroDivisionError. This code therefore will execute.')
else:
print('Everything did fine. I will exit the loop to continue.')
break
Interpreter:
# loop
# in try
value = int(input()) => read input and try to convert to an int; we assume this doesn't fail.
# if condition
not 0<value<10 => is value not between 0 and 10? (we assume it isn't)
# if block
1/0 => what?!? I can't do that, I'll raise a ZeroDivisionError
# except block
print(...) => show the text
# loop again
# in try
value = int(input()) => as above
# if condition
not 0<value<10 => we assume value is between 0 and 10 (evaluetes to False)
# else part of the try...except...else
print(...) => show text
break => exit the loop
You intentionally perform 1/0
, which will raise a ZeroDivisionError
and act on that in the except
. Since you said you don't usually do it, I recommend you try to understand what it does.
How to do it better
- Make the window appear before expecting user input: Put all code that should execute at application start in a function and either delay it with
tkinter.Tk.after
(window.after
) or add a nice "Start!"
Button.
- Don't (ab)use exceptions when a simple
if
will do (if you really want to (show off), define your own class MyFancyException(Exception): pass
)
- Look up on concepts you don't understand before using them and insert comments to remind you if something is so complicated you're afraid you won't remember later.
.
import tkinter as tk
from tkinter.simpledialog import askstring, askinteger
from tkinter.messagebox import showwarning
def do_stuff(first_name, surname, number):
...
def start():
# if you want to use Entry, add a "Submit" Button
first_name = askstring('Title', 'first name:')
surname = askstring('Title', 'last name:')
while True: # ask* return None when cancel is pressed
number = askinteger('Title', 'insert a number between 0 and 10:')
if number is not None and 0<number<10: # what we want
break
do_stuff(first_name, surname, number)
# GUI preparation code
window = tk.Tk()
button_start = tk.Button(window, text='Start!', command=start)
button_start.pack() # for use with other widgets (that use grid), you must .grid() here
window.mainloop() # the GUI appears at this moment