I am trying to get user input data from a tkinter dialog box with several labels. I found a website with an example close to my case here.
I want the user to type 3 data: first name, last name, and identification number. Once the validate button is clicked, I need to check if the identification number is composed only of numbers and if the name is valid, ensuring that it starts with a capital letter. If those conditions are satisfied, I will create a link and store the inputs into a file.
I adapted the code example to my case, but I can't get it to work.
Here is what I tried in file1.py
:
from userDialogBox import UserDialogBox
# ask user to type their "id number", "first name", "last name"
user_dialog = UserDialogBox(None)
# if input data are valid
if user_dialog.validate():
# build link web page
pass
In userDialogBox.py
:
import tkinter as tk
from tkinter import simpledialog
class UserDialogBox(simpledialog.Dialog):
def body(self, master):
self.title("Données utilisateur")
self.iconbitmap("logo_km.ico")
tk.Label(master, text="Matricule", font=('Arial', 15)).grid(row=0)
tk.Label(master, text="Prénom", font=('Arial', 15)).grid(row=1)
tk.Label(master, text="Nom", font=('Arial', 15)).grid(row=2)
self.matricule_entry = tk.Entry(master)
self.first_name_entry = tk.Entry(master)
self.last_name_entry = tk.Entry(master)
self.matricule_entry.grid(row=0, column=1)
self.first_name_entry.grid(row=1, column=1)
self.last_name_entry.grid(row=2, column=1)
def validate(self):
matricule = self.matricule_entry.get()
first_name = self.first_name_entry.get()
last_name = self.last_name_entry.get()
if not matricule.isdigit():
tk.messagebox.showerror("Erreur", "Matricule invalide.")
return False
if not first_name:
tk.messagebox.showerror("Erreur", "Prénom invalide.")
return False
if not last_name:
tk.messagebox.showerror("Erreur", "Nom invalide.")
return False
return True
def apply(self):
self.matricule = self.matricule_entry.get()
self.first_name = self.first_name_entry.get()
self.last_name = self.last_name_entry.get()
Once I tested my code, I received the following error message:
matricule = self.matricule_entry.get()
File "C:\Python310\lib\tkinter\__init__.py", line 3082, in get
return self.tk.call(self._w, 'get')
_tkinter.TclError: invalid command name ".!userdialogbox.!frame.!entry"
I rarely write Python code, so I would appreciate any help you can offer. Thank you!
Validation is done every time you click the OK button. If you inspect the whole traceback (not only the snippet posted) you might realize that your error is triggered from the the validation call you do manually in file1
which is after the dialog has either been accepted or canceled. Either way the widgets you are trying to access are destroyed (see the functions from Dialog
below):
def ok(self, event=None):
if not self.validate():
self.initial_focus.focus_set() # put focus back
return
self.withdraw()
self.update_idletasks()
try:
self.apply()
finally:
self.cancel()
def cancel(self, event=None):
# put focus back to the parent window
if self.parent is not None:
self.parent.focus_set()
self.destroy()
You can implement a new instance variable valid
to your dialog to hold information of whether the input was accepted. This is how it can be done:
import tkinter as tk
from tkinter import simpledialog
class UserDialogBox(simpledialog.Dialog):
def body(self, master):
self.valid = False # implement valid to check if input was provided
self.title("Données utilisateur")
self.iconbitmap("logo_km.ico")
tk.Label(master, text="Matricule", font=('Arial', 15)).grid(row=0)
tk.Label(master, text="Prénom", font=('Arial', 15)).grid(row=1)
tk.Label(master, text="Nom", font=('Arial', 15)).grid(row=2)
self.matricule_entry = tk.Entry(master)
self.first_name_entry = tk.Entry(master)
self.last_name_entry = tk.Entry(master)
self.matricule_entry.grid(row=0, column=1)
self.first_name_entry.grid(row=1, column=1)
self.last_name_entry.grid(row=2, column=1)
def validate(self):
matricule = self.matricule_entry.get()
first_name = self.first_name_entry.get()
last_name = self.last_name_entry.get()
if not matricule.isdigit():
tk.messagebox.showerror("Erreur", "Matricule invalide.")
return False
if not first_name:
tk.messagebox.showerror("Erreur", "Prénom invalide.")
return False
if not last_name:
tk.messagebox.showerror("Erreur", "Nom invalide.")
return False
self.valid = True # set valid to true if the input is correct
return True
def apply(self):
self.matricule = self.matricule_entry.get()
self.first_name = self.first_name_entry.get()
self.last_name = self.last_name_entry.get()
if __name__ == '__main__':
# ask user to type their "id number", "first name", "last name"
user_dialog = UserDialogBox(tk.Tk())
# if input data are valid
if user_dialog.valid: # check for valid instead of calling the validation again
# print data
print(user_dialog.matricule, user_dialog.first_name, user_dialog.last_name)