0
from tkinter import *
window = Tk()
window.title("Registration")
window.configure(background="blue")enter code here

Label (window, text= "Firstname: ", bg="blue", fg="white", font="verdana 12 bold") .grid(row=0, sticky=E)
firstname = Entry(window, width=100, bg="white")
firstname.grid(row=0, column=1, sticky=W)
firstname = firstname.get()
firstname = firstname.strip()
firstname = firstname.lower()

Label (window, bg = "blue") .grid(row=2)

Label (window, text= "Surname: ", bg="blue", fg="white", font="verdana 12 bold") .grid(row=3, sticky=E)
surname = Entry(window, width=100, bg="white")
surname.grid(row=3, column=1, sticky=W)
surname = surname.get()
surname = surname.lower()
surname = surname.strip()

Label (window, bg = "blue") .grid(row=4)

Label (window, text = "Pick a number between 0 and 10: ", bg="blue", fg="white", font = "verdana 12 bold") .grid(row=5, sticky=E)
number = Entry(window, width=100, bg="white")
number.grid(row=5, column=1)
while True:
        try:
            number = number.get()
            if (number > 10) or (number < 0): 1/0
        except:
            print("Sorry, your response must be a number between 0 and 10")
            continue
        break

window.mainloop()

This is my code so far. I am trying to create a registration system for a quiz I'm making, however, now that I am dealing with GUI, I don't know how to use my validation code in the GUI way/environment. for example, just having "print("sorry, your response must be a number between 0 and 10")" won't and isn't working with my program. My question: How do I output a message into a textbox like an error message and how do I implement my validation code? Also, I made my validation code onths ago when I was new to python and used a stack overflow piece of code to help apply it to my program. Anyway, could someone help explain how this code actually works. I don't seem to understand it now and my teacher has struggled to explain it in an understandable way. Specifically the : 1/0 bit. I'm not used to using try and except, I only know how to use for and while loops usually. Many thanks

Hamzah
  • 1
  • 1
  • You can't do division by zero! Your firstname variable should be an Entry object but you overwrite it to with the get() function. It is better to use tkinters StringVar for this purpose, the same is with your surname variable. –  Jan 09 '19 at 12:15
  • And your **if** statement is wrong because you are asking if number greater than 10 and less than 0 but you want catch a number between 0 and 10. –  Jan 09 '19 at 12:23

1 Answers1

1

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

  1. 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.
  2. 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)
  3. 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
user24343
  • 796
  • 6
  • 17