I'm working on a GUI app to add clients to a database. Now, I'm stuck with the tkinter library. I would like to import models only once, and only in the app.py file because I will add more functions to this file. I would like to add tkinter elements in file adduser.py. Here is the error:
Traceback (most recent call last):
File "app.py", line 8, in <module>
from adduser import adduser
File "C:\*************adduser.py", line 10, in <module>
name_label = tk.Label(root, text="Name:")
NameError: name 'tk' is not defined
# app.py
import os
import re
import sys
import time
import requests
from adduser import adduser
import tkinter as tk
import ttkbootstrap as ttk
from ttkbootstrap.scrolled import ScrolledFrame
from ttkbootstrap.toast import ToastNotification
from ttkbootstrap.tooltip import ToolTip
from ttkbootstrap.widgets import DateEntry, Floodgauge, Meter
root = ttk.Window(themename = "vapor")
root.geometry('800x600')
root.title('Users')
adduser()
root.mainloop()
I would like to add tkinter elements in file adduser.py
# adduser.py
import sqlite3
conn = sqlite3.connect('users.db')
def adduser(name, email):
conn.execute('INSERT INTO users (name, email) VALUES (?, ?)', (name, email))
conn.commit()
print(f"User {name} added successfully!")
name_label = tk.Label(root, text="Name:")
name_label.pack()
name_entry = tk.Entry(root)
name_entry.pack()
email_label = tk.Label(root, text="Email:")
email_label.pack()
email_entry = tk.Entry(root)
email_entry.pack()
submit_button = tk.Button(root, text="Submit", command=get_input)
submit_button.pack()
adduser(name, email)
conn.close()
I appreciate your help and effort.
I've tried to import tkinter in both files, but that's not what I would like to achieve.
Hopefully this points you in the right direction. As the comments have mentioned, to be able to access tkinter in another file you need to either import it or pass it along so that it is accessible. Passing it along can be in the form of function arguments like this:
# in adduser.py
def adduser(name, email, tk, root):
pass
# here you now have tk available to use
# in app.py
import tkinter as tk
import ttkbootstrap as ttk
from adduser import adduser
root = ttk.Window(themename = "vapor")
root.geometry('800x600')
root.title('Users')
adduser("John Doe", "john@doe.com", tk, root)
However, I would recommend using the import over passing modules across like this in function calls. One thing to keep in mind is that when you make an import
statement, all the top-level code runs in that file. Importing adduser.py
in the question above, would run the name_label
, email_label
and submit_button
sections at import time. A better structure would be like this:
# app.py
import os
import re
import sys
import time
import requests
from adduser import adduser, initialize_user_tk
import tkinter as tk
import ttkbootstrap as ttk
from ttkbootstrap.scrolled import ScrolledFrame
from ttkbootstrap.toast import ToastNotification
from ttkbootstrap.tooltip import ToolTip
from ttkbootstrap.widgets import DateEntry, Floodgauge, Meter
root = ttk.Window(themename = "vapor")
root.geometry('800x600')
root.title('Users')
initialize_user_tk(root)
adduser("John Doe", "john@doe.com")
root.mainloop()
# adduser.py
import sqlite3
import tkinter as tk
def adduser(name, email):
conn = sqlite3.connect('users.db')
conn.execute('INSERT INTO users (name, email) VALUES (?, ?)', (name, email))
conn.commit()
print(f"User {name} added successfully!")
conn.close()
def initialize_user_tk(root):
name_label = tk.Label(root, text="Name:")
name_label.pack()
name_entry = tk.Entry(root)
name_entry.pack()
email_label = tk.Label(root, text="Email:")
email_label.pack()
email_entry = tk.Entry(root)
email_entry.pack()
def invoke_callback():
name = name_entry.get()
email = email_entry.get()
adduser(name, email)
submit_button = tk.Button(root, text="Submit", command=invoke_callback)
submit_button.pack()
In this way, the name_label
, email_label
and submit_button
sections run when you are ready to call them