I’m coding a database management app with python tkinter packages. This API is on a NAS (network attached storage). So the users can open it from a connection and make modifications in real time.
I want to give some privilege for admin users. That means if a users log in the app, they can tick and fill entry box which is disabled for normal users.
How to do it?
Here is my try:
from tkinter import *
import tkinter as tk
from tkinter import ttk
#Initialisation
root=Tk()
root.title("Test")
#Tab creation
my_tab=ttk.Notebook(root)
my_tab.pack(expand=True, fill=tk.BOTH)
#Tab name and their creation
frames=[]
nom_des_onglets=["Main", "First tab", "Second tab"]
def admin():
global longentrie
win=Toplevel()
longentrie = StringVar()
password_msg = tk.Label(win,text="Enter password for administrator privileges")
password_msg.pack()
password_entries = tk.Entry(win,textvariable=longentrie)
password_entries.pack()
tk.Button(win,text='Enter', command=admin_privilege).pack()
def admin_privilege():
global login_value
password_admin = longentrie.get()
if password_admin == 'good':
login_value=1
else:
login_value=0
for i in range(3):
frame=ttk.Frame(my_tab) # add tab
frame.pack(fill="both")
frames.append(frame)
my_tab.add(frames[i], text=nom_des_onglets[i])
#Login button
login=tk.Button(frames[0],text="login", command=admin)
login.pack()
#special priviledge
var1 = tk.IntVar()
ts = [tk.StringVar() for _ in range(17)]
lbl7 = tk.Checkbutton(frames[1], text='Text',variable=var1, onvalue=1,offvalue=0, bg='#ececec', state='disabled')
lbl7.grid(row=0, column=0, padx=5, pady=3)
lbl1=tk.Label(frames[1], text="Name")
lbl1.grid(row=2, column=0, padx=5, pady=3)
ent7=Entry(frames[1], textvariable=ts[6])
ent7.grid(row=2, column=1, padx=5, pady=3,sticky="nsew")
lbl8=tk.Label(frames[1], text="Age")
lbl8.grid(row=3, column=0, padx=5, pady=3)
ent8=Entry(frames[1], textvariable=ts[7],state='disabled')
ent8.grid(row=3, column=1, padx=5, pady=3,sticky="nsew")
if login_value == 1:
lbl7.configure(state='normal')
ent8.configure(state='normal')
root.mainloop()
Here's an example where entering the right password does correctly change the disabled state of those two fields.
This could be refactored to be a lot less messy (better variable naming for one), but it's a start:
import tkinter as tk
from tkinter import ttk
is_admin = False
def setup_ui():
lbl7.configure(state=("normal" if is_admin else "disabled"))
ent8.configure(state=("normal" if is_admin else "disabled"))
def do_login_window():
def admin_privilege():
global is_admin
if password_var.get() == "good":
is_admin = True
setup_ui()
login_win.destroy() # Close the login box
login_win = tk.Toplevel()
password_var = tk.StringVar()
password_msg = tk.Label(login_win, text="Enter password for administrator privileges")
password_msg.pack()
password_entries = tk.Entry(login_win, textvariable=password_var)
password_entries.pack()
tk.Button(login_win, text="Enter", command=admin_privilege).pack()
# Initialisation
root = tk.Tk()
root.title("Test")
# Tab creation
my_tab = ttk.Notebook(root)
my_tab.pack(expand=True, fill=tk.BOTH)
frames = []
for name in ["Main", "First tab"]:
frame = ttk.Frame(my_tab)
frame.pack(fill="both")
frames.append(frame)
my_tab.add(frame, text=name)
# Login button
login_frame = frames[0]
login = tk.Button(login_frame, text="login", command=do_login_window)
login.pack()
# special priviledge
data_frame = frames[1]
var1 = tk.IntVar()
ts = [tk.StringVar() for _ in range(17)]
lbl7 = tk.Checkbutton(
data_frame, text="Text", variable=var1, onvalue=1, offvalue=0, bg="#ececec"
)
lbl7.grid(row=0, column=0, padx=5, pady=3)
lbl1 = tk.Label(data_frame, text="Name")
lbl1.grid(row=2, column=0, padx=5, pady=3)
ent7 = tk.Entry(data_frame, textvariable=ts[6])
ent7.grid(row=2, column=1, padx=5, pady=3, sticky="nsew")
lbl8 = tk.Label(data_frame, text="Age")
lbl8.grid(row=3, column=0, padx=5, pady=3)
ent8 = tk.Entry(data_frame, textvariable=ts[7])
ent8.grid(row=3, column=1, padx=5, pady=3, sticky="nsew")
setup_ui() # Will be called after logging in too
root.mainloop()
Related
I'm beginner...
When the code below is executed, how do I make the widgets inside increase when the screen size is increased to width? but, it couldn't resized..
Does it matter if I use either pack or grid?
i can't solve it....
from tkinter import *
from tkinter import ttk
class program:
def __init__(self):
self.root = Tk()
self.root.title("Python")
self.root.resizable(True, True)
self.create_project()
def create_project(self):
Topic_Label = ttk.Label(self.root, text="program")
Topic_Label.pack(side="top")
Record_LabelFrame = LabelFrame(self.root, text="Record information")
Record_LabelFrame.pack(side="top", anchor=W, padx=10)
date = ttk.Label(Record_LabelFrame, text="date")
date.grid(column=0, row=0, sticky=W)
Topic_Label_Entry1 = ttk.Entry(Record_LabelFrame)
Topic_Label_Entry1.grid(column=0, row=1)
time = ttk.Label(Record_LabelFrame, text="time")
time.grid(column=1, row=0, sticky=W)
Topic_Label_Combo1 = ttk.Combobox(Record_LabelFrame)
Topic_Label_Combo1.grid(column=1, row=1)
recorder = ttk.Label(Record_LabelFrame, text="record")
recorder.grid(column=2, row=0, sticky=W)
Topic_Label_Entry2 = ttk.Entry(Record_LabelFrame)
Topic_Label_Entry2.grid(column=2, row=1)
loc = ttk.Label(Record_LabelFrame, text="location")
loc.grid(column=0, row=2, sticky="W")
RadioVar = IntVar()
Radio_Frame = Frame(Record_LabelFrame)
Radio_Frame.grid(column=0, row=3, sticky=W)
Topic_Label_Radio1 = ttk.Radiobutton(Radio_Frame, text="A", variable=RadioVar, value=1)
Topic_Label_Radio1.grid(column=0, row=0)
Topic_Label_Radio2 = ttk.Radiobutton(Radio_Frame, text="B", variable=RadioVar, value=2)
Topic_Label_Radio2.grid(column=1, row=0)
Topic_Label_Radio3 = ttk.Radiobutton(Radio_Frame, text="C", variable=RadioVar, value=3)
Topic_Label_Radio3.grid(column=2, row=0)
count = ttk.Label(Record_LabelFrame, text="count")
count.grid(column=1, row=2, sticky="W")
Topic_Label_Combo2 = ttk.Combobox(Record_LabelFrame)
Topic_Label_Combo2.grid(column=1, row=3)
seed_name = ttk.Label(Record_LabelFrame, text="seed")
seed_name.grid(column=2, row=2, sticky="W")
Topic_Label_Entry4 = ttk.Entry(Record_LabelFrame)
Topic_Label_Entry4.grid(column=2, row=3)
mt = program()
mt.root.mainloop()
I want to print like this that widget resize automatically when i resize the screen
https://i.stack.imgur.com/iSbaJ.png
https://i.stack.imgur.com/mzv9R.png
I have a simple label and entry field that would:
1) Create a static label and clear the entry field after confirmation button click
2) Clear static label after reset button click
Is there any way to overwrite the entry field with a static label of the user input on the confirmation click instead of creating a new static label? And overwriting the static label with an empty entry field on the reset click?
Thank you for the help in advance.
from tkinter import *
root = Tk()
frame1 = Frame(root)
frame1.pack()
def reset():
set_cname.destroy()
cbtn['state'] = NORMAL
def confirm():
global set_cname
text1="Customer Name: " + entry1.get()
set_cname = Label(frame1, text=text1)
set_cname.grid(row=3, column=0, columnspan=1)
entry1.delete(0, 'end')
cbtn['state'] = DISABLED
cname = Label(frame1, text="Customer Name: ").grid(padx=5, pady=5, columnspan=2, sticky=W)
entry1 = Entry(frame1)
entry1.grid(row=0, column=2, padx=5)
cbtn = Button(frame1, text="Confirm", command=confirm, width=20)
cbtn.grid(row=1, column=4, padx=5, pady=5)
rbtn = Button(frame1, text="Reset Names", command=reset, width=20)
rbtn.grid(row=2, column=4, padx=5, pady=5)
root.mainloop()
You can replace the Entry with a Label by first creating both and then using pack() to switch between them. The trick is to not let their different sizes affect the application layout, which can be accomplished by disabling size propagation.
In my example I create a new frame (entry_frame) with a fixed size and then disable size propagation (.pack_propagate(False)). Then I use this new frame to contain the Entry/Label. Im giving the entry_frame the bg color khaki to let you see exactly where it is.
I fiddled a bit with the column numbers also.
from tkinter import *
root = Tk()
frame1 = Frame(root)
frame1.pack()
def reset():
text_label.pack_forget()
entry1.pack()
cbtn['state'] = NORMAL
def confirm():
global set_cname
entry1.pack_forget()
text_label.config(text=entry1.get())
text_label.pack(side='left')
entry1.delete(0, 'end')
cbtn['state'] = DISABLED
cname = Label(frame1, text="Customer Name: ")
cname.grid(row=0, column=0, padx=5, pady=5, sticky=W)
entry_frame = Frame(frame1, width=130, height=20, bg='khaki')
entry_frame.grid(row=0, column=1, padx=5, pady=5, sticky='nsew')
entry_frame.pack_propagate(False) # Disable size propagation
entry1 = Entry(entry_frame) # Customer name entry
entry1.pack()
text_label = Label(entry_frame) # Label to hold customer name
cbtn = Button(frame1, text="Confirm", command=confirm, width=20)
cbtn.grid(row=1, column=2, padx=5, pady=5)
rbtn = Button(frame1, text="Reset Names", command=reset, width=20)
rbtn.grid(row=2, column=2, padx=5, pady=5)
root.mainloop()
Be aware that this solution will be sensitive to font size changes.
I'm just about ready to pull my hair out - have tried just about everything I can imagine to do something that on the face of it seems fairly simple...
I need to have an Entry box, which takes in a variable, which is returned to the code and can be used as a variable throughout the script. I actually need to import this script and use it in the code of another script.
At the moment, I know the Submit button is calling the get_data() function, because using 'print' displays the password entered. But using return, to return it to the parent function, and then returning that value and printing the output of the main function returns nothing.
Thanks
from tkinter import *
def get_params():
def get_data():
pw = pwentry_enter.get()
return pw
window = Tk()
headFrame = Frame(window)
headFrame.grid(row=0, pady=6)
header = Label(headFrame, text="Input Password", font=(f1, 20))
header.grid(column=0, row=0, columnspan=2, sticky="w")
mainFrame = Frame(window, bg="#1B2230")
mainFrame.grid(row=1, pady=6)
raw_password = StringVar()
pwentry_enter=Entry(mainFrame, width=30, font=(f2,10), show="*", textvariable=raw_password)
pwentry_enter.pack()
btnFrame = Frame(window)
btnFrame.grid(row=2, pady=6)
submit_btn = Button(btnFrame, text='Submit', command=get_data, width=10, bg="#DB4158", fg="black", font=(f2, 20))
submit_btn.grid(column=1, row=0)
quit_btn = Button(btnFrame, text='Quit', command=window.destroy, width=10, bg="#DB4158", fg="black", font=(f2, 20))
quit_btn.grid(column=0, row=0)
window.mainloop()
a = get_data()
return a
Don't add return in get_data() and use a global variable to store the password when submit button is clicked and return when quit button is pressed.
You are trying to read data of the Entry after destroying the window.
from tkinter import *
pw = ''
def get_params():
global pw
def get_data():
global pw
pw = pwentry_enter.get()
window = Tk()
headFrame = Frame(window)
headFrame.grid(row=0, pady=6)
header = Label(headFrame, text="Input Password", font=(f1, 20))
header.grid(column=0, row=0, columnspan=2, sticky="w")
mainFrame = Frame(window, bg="#1B2230")
mainFrame.grid(row=1, pady=6)
raw_password = StringVar()
pwentry_enter=Entry(mainFrame, width=30, font=(f2,10), show="*", textvariable=raw_password)
pwentry_enter.pack()
btnFrame = Frame(window)
btnFrame.grid(row=2, pady=6)
submit_btn = Button(btnFrame, text='Submit', command=get_data, width=10, bg="#DB4158", fg="black", font=(f2, 20))
submit_btn.grid(column=1, row=0)
quit_btn = Button(btnFrame, text='Quit', command=window.destroy, width=10, bg="#DB4158", fg="black", font=(f2, 20))
quit_btn.grid(column=0, row=0)
window.mainloop()
return pw
I have a Tkinter GUI and I would like to update the status of the script in a Label, writing which function is being called, but I am having problems with that.
I have already seen many answers on here, but still I cant come to a solution. This is the part of the code that I am working on:
run_script(username, password):
text = StringVar()
text.set('')
l=Label(master, text=text, fg='blue')
l.grid(row=6) #I would like the Label in the row 6
l.pack()
text.set('calling my function1')
my_file.my_function1(username, password)
text.set('calling my function2')
my_file.my_function2()
master = Tk()
username = Entry(master, name='username', width=30)
password = Entry(master, name='password', show='*', width=30)
username.grid(row=0, column=1, padx=10, pady=(10,2))
password.grid(row=1, column=1, padx=10, pady=2)
def call_report(username, password):
run_script(username, password)
Button(master, text='start script',
command= lambda:call_report(username.get(), password.get(),)).grid(row=6, column=1, sticky=W, pady=10)
mainloop()
The program run perfectly, just the label is not updated. Thanks
here is one way to do it, using the keyword argument textvariable:
import tkinter as tk
def run_script(username, password):
text = tk.StringVar()
text.set('')
lab = tk.Label(master, textvariable=text, fg='blue')
lab.grid(row=6)
text.set('calling my function1')
# call functions here
def call_report(username, password):
run_script(username, password)
if __name__ == '__main__':
master = tk.Tk()
username = tk.Entry(master, name='username', width=30)
password = tk.Entry(master, name='password', show='*', width=30)
username.grid(row=0, column=1, padx=10, pady=(10,2))
password.grid(row=1, column=1, padx=10, pady=2)
button = tk.Button(master, text='start script', command=lambda: call_report(username.get(), password.get(),))
button.grid(row=6, column=1, sticky=tk.W, pady=10)
master.mainloop()
Note:
The use of pack and grid geometry managers in the same widget is not encouraged.
Please import tkinter as tk: adding tk. is a small price to keep the namespace clean.
This is my solution that can be used as example:
from Tkinter import *
from time import sleep
def run_script():
text = StringVar()
l = Label(master, textvariable=text, fg='blue').grid(row=6)
text.set('calling my function1')
master.update()
sleep(2)
text.set('end of function1')
def call_report():
run_script()
if __name__ == '__main__':
master = Tk()
username = Entry(master, name='username', width=30)
password = Entry(master, name='password', show='*', width=30)
username.grid(row=0, column=1, padx=10, pady=(10,2))
password.grid(row=1, column=1, padx=10, pady=2)
button = Button(master, text='start script', command=lambda: call_report())
button.grid(row=6, column=1, sticky=W, pady=10)
master.mainloop()
I've changed text to textvariable in Label, and I added master.update(). In this way it force the GUI to redraw. Just to test if the GUI was changing, I tested with sleep. It is possible to update more time (for example before calling a function).
How do you check if the user has selected "Other" from the hopOptions selection, and then enable otherEntry if they did? And then disable it again if they select one of the other options.
class Interface():
def __init__(self, window):
frame = Frame(window)
frame.pack()
self.hopLabel = Label(frame, text="Hop:", anchor=E)
self.hopLabel.grid(row=0, column=0, sticky=EW)
hops = range(0,6)
hops.append("Other")
self.selectedHop = StringVar(frame)
self.selectedHop.set(hops[0])
self.hopOptions = OptionMenu(frame, self.selectedHop, *hops)
self.hopOptions.grid(row=0, column=2, sticky=EW)
self.otherEntry = Entry(frame, state=DISABLED)
self.otherEntry.grid(row=0, column=1, sticky=EW)
root = Tk()
app = Interface(root)
root.mainloop()
Bind the option menu to a command and add another method to your class. The command will run the class method with the value as an argument anytime an option is changed in the menu. There you can do validation to update the otherEntry widget. Also I would advise not doing from Tkinter import * as it appears that's what you've done. Generally importing an entire package could have conflicts with your namespace. This should suit your needs:
from Tkinter import *
class Interface():
def __init__(self, window):
frame = Frame(window)
frame.pack()
self.hopLabel = Label(frame, text="Hop:", anchor=E)
self.hopLabel.grid(row=0, column=0, sticky=EW)
hops = range(0,6)
hops.append("Other")
self.selectedHop = StringVar(frame)
self.selectedHop.set(hops[0])
self.hopOptions = OptionMenu(frame, self.selectedHop, *hops, command=self.optupdate)
self.hopOptions.grid(row=0, column=2, sticky=EW)
self.otherEntry = Entry(frame, state=DISABLED)
self.otherEntry.grid(row=0, column=1, sticky=EW)
def optupdate(self, value):
if value == "Other":
self.otherEntry.config(state=NORMAL)
else:
self.otherEntry.config(state=DISABLED)
if __name__ == "__main__":
root = Tk()
app = Interface(root)
root.mainloop()
As an alternative to iChar's command approach, Use selectedHop.trace to register a function that will be called whenever the selected item changes.
from Tkinter import *
class Interface():
def __init__(self, window):
frame = Frame(window)
frame.pack()
self.hopLabel = Label(frame, text="Hop:", anchor=E)
self.hopLabel.grid(row=0, column=0, sticky=EW)
hops = range(0,6)
hops.append("Other")
self.selectedHop = StringVar(frame)
self.selectedHop.set(hops[0])
self.selectedHop.trace("w", self.selected_hop_changed)
self.hopOptions = OptionMenu(frame, self.selectedHop, *hops)
self.hopOptions.grid(row=0, column=2, sticky=EW)
self.otherEntry = Entry(frame, state=DISABLED)
self.otherEntry.grid(row=0, column=1, sticky=EW)
def selected_hop_changed(self, *args):
value = self.selectedHop.get()
if value == "Other":
self.otherEntry.config(state=NORMAL)
else:
self.otherEntry.config(state=DISABLED)
root = Tk()
app = Interface(root)
root.mainloop()