I need to fill entry boxes with values selected from dictionary.
List of dictionaries is compiled from a csv file. Here is the code:
import os
import csv
from tkinter import *
import tkinter as tk
from tkinter.filedialog import *
def show():
record =[]
details = open('c.record.csv','r')
reader = csv.DictReader(details)
for line in reader:
record.append(line)
return record
def recordDetails():
name = ent_user.get()
password = ent_pw.get()
city = ent_city.get()
code = ent_code.get()
if len(name) != 0 and len(password) != 0 and len(city) != 0 and len(code) != 0:
with open('c.record.csv', 'a') as add:
w = csv.writer(add)
w.writerow([name,password,city,code])
add.close
lbl_result["text"] = "record saved"
else:
lbl_result["text"] = "values cannot be empty"
return True
def SaveToFile():
name = ent_user.get()
data = show()
for elem in data:
if name in elem.values():
lbl_result["text"] = "record exist already"
return False
recordDetails()
return True
def display() :
lbl_result["text"] = show()
record = show()
for n, dicts in enumerate(record):
for v, k in dicts.items():
position = n
user = dicts['name']
lbl_record = tk.Label(master=frm_details, height=1, width=40, bg = 'white', relief=tk.GROOVE, text=user,justify="right")
lbl_record.grid(row=1+position, column=0, padx=5)
def select():
Clear()
ent_user.insert(tk.END,dicts['name'])
ent_pw.insert(tk.END,dicts['password'])
ent_city.insert(tk.END,dicts['city'])
ent_code.insert(tk.END,dicts['code'])
btn_recSelect = tk.Button(master=frm_details ,width=5, bg = 'white', text='select',command=select)
btn_recSelect.grid(row=1+position, column=1, padx=2,sticky=tk.W)
return True
def Connect():
if len(ent_user.get()) != 0:
lbl_result["text"] = "connecting to "+ent_user.get()
def Clear() :
user = ent_user.delete(0,END)
pw = ent_pw.delete(0,END)
city = ent_city.delete(0,END)
code = ent_code.delete(0,END)
#def update(window):
#window.update()
screen = tk.Tk()
screen.title ("tk files interaction")
screen.minsize(width=400, height=300)
screen.maxsize(width=900, height=700)
screen.rowconfigure(0, minsize=50, weight=1)
screen.columnconfigure(0, minsize=60, weight=1)
screen.update()
#FORM to collect connectivity details
frm_connEntryArea = tk.Frame(master=screen,height=10, borderwidth=1, highlightbackground="orange", highlightthickness=1)
frm_connEntryArea.grid(column=0, row=0, sticky=tk.N, padx=10, pady=5)
lbl_user = tk.Label(master=frm_connEntryArea, text="name:")
lbl_user.grid(column=0, row=0, sticky=tk.NW, padx=5, pady=3)
ent_user = tk.Entry(master=frm_connEntryArea,width=30)
ent_user.grid(column=1, row=0, sticky=tk.NW, padx=5, pady=3)
lbl_pw = tk.Label(master=frm_connEntryArea, text="password:")
lbl_pw.grid(column=0, row=1, sticky=tk.NW, padx=5, pady=3)
ent_pw = tk.Entry(master=frm_connEntryArea,width=30)
ent_pw.grid(column=1, row=1, sticky=tk.NW, padx=5, pady=3)
lbl_city = tk.Label(master=frm_connEntryArea, text="city")
lbl_city.grid(column=0, row=2, sticky=tk.NW, padx=5, pady=3)
ent_city = tk.Entry(master=frm_connEntryArea,width=30)
ent_city.grid(column=1, row=2, sticky=tk.NW, padx=5, pady=3)
lbl_code = tk.Label(master=frm_connEntryArea, text="code:")
lbl_code.grid(column=0, row=3, sticky=tk.NW, padx=5, pady=3)
ent_code = tk.Entry(master=frm_connEntryArea,width=30)
ent_code.grid(column=1, row=3, sticky=tk.NW, padx=5, pady=3)
ent_code.insert(tk.END,"20")
ent_code.bind("<Button-1>", lambda event: clear_entry(ent_code))
#connect,save and clear details
btn_save = tk.Button(master=frm_connEntryArea,text="Save",width=10,fg="black",command=SaveToFile)
btn_save.grid(column=0, row=4, sticky=tk.NW, padx=5, pady=3)
btn_clear = tk.Button(master=frm_connEntryArea,text="Clear",width=10,fg="black",command=Clear)
btn_clear.grid(column=1, row=4, sticky=tk.NW, padx=5, pady=3)
btn_conn = tk.Button(master=frm_connEntryArea,text="Connect",width=10,fg="black",command=Connect)
btn_conn.grid(column=2, row=4, sticky=tk.NW, padx=5, pady=3)
#FORM to shows connectivity results and errors
frm_logs = tk.Frame(master=screen,height=10,bg="gray",relief=tk.GROOVE,highlightbackground="orange")
frm_logs.grid(column=0, row=1, sticky=tk.NW, padx=5, pady=3)
lbl_result = tk.Label(master=frm_logs, height=8, width=50,relief=tk.GROOVE, bg = 'white', text="Logs",wraplength=300,justify="left")
lbl_result.grid(row=0, column=0)
#FORM to shows Existing Record
frm_record = tk.Frame(master=screen,height=10,bg="gray")
frm_record.grid(column=1, row=1, sticky=tk.N, padx=5, pady=3)
lbl_record = tk.Label(master=frm_record, height=1, width=40, bg = 'white', relief=tk.GROOVE, text='Record',wraplength=200,justify="left")
lbl_record.grid(row=0, column=0, padx=5)
btn_recDisplay = tk.Button(master=frm_record ,width=5, bg = 'white', text='Display',command =display)
btn_recDisplay.grid(row=0, column=1, padx=2,sticky=tk.W)
frm_details = tk.Frame(master=frm_record,height=10,bg="gray")
frm_details.grid(row=1, column=0, sticky=tk.NW, padx=5, pady=3)
lbl_record = tk.Label(master=frm_details , height=1, width=30, bg = 'white', relief=tk.GROOVE, text='user',justify="right")
lbl_record.grid(row=0, column=0, padx=5)
#FORM to exit
frm_exit = tk.Frame(master=screen,height=50,width= 300, bg="orange")
frm_exit.grid(column=1, row=0, sticky=NE, padx=5, pady=3)
frm_exit.grid_propagate(0)
btn_refresh = tk.Button(master=frm_exit, text="Refresh")
btn_refresh.grid(row=2, column=3,sticky=E, padx=10,pady=10)
btn_exit = tk.Button(master=frm_exit, text="Exit", command=screen.destroy)
btn_exit.grid(row=2, column=4, sticky=E, padx=10,pady=10)
# added at the end
screen.mainloop()
csv structure:
name,password,city,code
apple,1234,rome,20
banana,2345,paris,20
cherry,3456,london,21
I am concerned with the def display() : and def select(): functions. These works in displaying and selecting. The problem is when ‘select’ is pressed the latest dictionary value form the list is used to fill the entries boxes, I would like the entries to be filled with the values that correspond to the user display in the line.
I have found the solution.
I have adjust the code with the guidance found here:
https://www.geeksforgeeks.org/looping-through-buttons-in-tkinter/
def select(u,pwd,cy,co):
Clear()
ent_user.insert(tk.END,u)
ent_pw.insert(tk.END,pwd)
ent_city.insert(tk.END,cy)
ent_code.insert(tk.END,co)
def display() :
lbl_result["text"] = show()
record = show()
for n, line in enumerate(record):
position = n
user = line['name']
for k,v in line.items():
def action(x = line['name'], p = line['password'], c = line['city'], d = line['code']):
return select(x,p,c,d)
lbl_record = tk.Label(master=frm_details, height=1, width=40, bg = 'white', relief=tk.GROOVE, text=user,justify="right")
lbl_record.grid(row=1+position, column=0, padx=5)
btn_recSelect = tk.Button(master=frm_details ,width=5, bg = 'white', text='select',command= action)
btn_recSelect.grid(row=1+position, column=1, padx=2,sticky=tk.W)
return True
I had to create an aditional function to point to action the entry update and add an addidional for looop, the first loop through the list, the second through the dictionary items.
Related
This is my code:
mycanvas = Canvas(self.search_result_frame)
mycanvas.pack(side=LEFT)
yscrollbar = ttk.Scrollbar(self.search_result_frame, orient="vertical", command=mycanvas.yview)
yscrollbar.pack(side=RIGHT, fill=Y)
mycanvas.configure(yscrollcommand=yscrollbar.set)
mycanvas.bind('<Configure>', lambda e: mycanvas.configure(scrollregion = mycanvas.bbox('all')))
self.sample_frame = Frame(mycanvas)
mycanvas.create_window((0,0), window=self.sample_frame, anchor=E)
for widget in self.search_result_frame.winfo_children():
widget.destroy()
if len(matching_bills) > 0:
for bill in matching_bills:
with open(f'{self.bill_folder}//{bill}//data//bill_details.json', 'r') as bill_json_file:
bill_details = json.loads(bill_json_file.read())
customer_name = bill_details["customer_details"][0]
payment_method = bill_details["payment_method"]
date_of_issue = bill_details["date_of_issue"]
date_of_issue = datetime.strptime(date_of_issue, "%d/%m/%Y")
date_of_issue = date_of_issue.strftime("%d %b %Y")
# # -------------------- Search Result Frame Contents
result_frame = Frame(self.sample_frame, bg=self.bg3, bd=5, relief=GROOVE)
result_frame.pack(fill=BOTH, pady=2)
result_billno_lbl = Label(result_frame, text=bill, bg=self.bg1, fg="#FFF", font=self.search_results_font1, padx=22, pady=3)
result_billno_lbl.grid(row=0, column=0, padx=50, pady=8, sticky=W)
billed_to_lbl = Label(result_frame, text=f"Billed To - {customer_name}", bg=self.bg1, fg="#FFF", font=self.search_results_font2, bd=2, relief=RAISED, padx=12, pady=3)
billed_to_lbl.grid(row=0, column=1, padx=80, sticky=W)
billed_type_lbl = Label(result_frame, text=f"Bill Type - {payment_method}", bg=self.bg1, fg="#FFF", font=self.search_results_font2, bd=2, relief=RAISED, padx=12, pady=3)
billed_type_lbl.grid(row=0, column=2, sticky=W)
issued_on_lbl = Label(result_frame, text=f"Issued On - {date_of_issue}", bg=self.bg1, fg="#FFF",
font=self.search_results_font2, bd=2, relief=RAISED, padx=12, pady=3)
issued_on_lbl.grid(row=0, column=3, padx=80, sticky=W)
view_btn = Button(result_frame, text="View", font="Comicsan 14", bd=2, relief=GROOVE, bg="#000", fg="#FFF", padx=1, command=lambda bill=bill: self.view_bill(bill))
view_btn.grid(row=0, column=4, padx=3, columnspan=2, sticky=W)
elif len(matching_bills) == 0:
for widgets in self.search_result_frame.winfo_children():
widgets.destroy()
no_result_lbl = Label(self.search_result_frame, text=f"No search result found for {bill_cat}", font=self.search_results_font1, bg=self.bg3, fg="#FFF")
no_result_lbl.pack(fill=X)
When I run it, it shows me the bad window path name ".!labelframe.!canvas.!frame error and when I try to do the same thing without object-oriented in tkinter then it works well !
So I am trying to create this function to make a plot of a mass spring damper system and we should be able to basically change whatever we like, the values for the function and the sliders should affect the plot as well, i'm having trouble trying to get my function plotted. The error is coming within the function where I am trying to use my solveMBK function inside my PlotWindow function, I am not sure how to include the values from my sliders as well as the other values that are inputted in the start up window. Here is a look at my code:
import tkinter as tk
from matplotlib.backends.backend_tkagg import (FigureCanvasTkAgg, NavigationToolbar2Tk)
from matplotlib.figure import Figure
import numpy as np
def solveMBK(inlist):
x0 = inlist[0]
dx0 = inlist[1]
dt = inlist[2]
m = inlist[3]
b = inlist[4]
k = inlist[5]
tf = inlist[6]
Z = inlist[7]
t = np.arange(0,tf,dt)
z0 = np.zeros_like(t)
z1 = np.zeros_like(t)
z0[0] = x0
z1[0] = dx0
for c in range(len(t)-1):
z0[c+1] = z0[c] + z1[c]*dt
z1[c+1] = z1[c] + ((ABradiobutton(Z,t[c]) - k*z0[c] - b*z1[c]) / m)
x = z0
return t,x
def ABradiobutton(Z, t):
if Z == 1:
A = float(A_entry.get())
return A
elif Z == 2:
B = float(B_entry.get())
return np.sin(B*t)
def PlotWindow():
root1 = tk.Tk()
root1.title("Plot")
Mmin = float(Mmin_entry.get())
Mmax = float(Mmax_entry.get())
bmin = float(bmin_entry.get())
bmax = float(bmax_entry.get())
kmin = float(kmin_entry.get())
kmax = float(kmax_entry.get())
mscale = tk.Scale(root1, from_=Mmin, to=Mmax, label="m", bd=2, length=200, orient=tk.HORIZONTAL, command = funcPlot)
mscale.set((Mmin+Mmax)/2)
mscale.grid(row=1, column=0)
bscale = tk.Scale(root1, from_=bmin, to=bmax, label="b", bd=2, length=200, orient=tk.HORIZONTAL, command = funcPlot)
bscale.set((bmin+bmax)/2)
bscale.grid(row=3, column=0)
kscale = tk.Scale(root1, from_=kmin, to=kmax, label="k", bd=2, length=200, orient=tk.HORIZONTAL, command = funcPlot)
kscale.set((kmin+kmax)/2)
kscale.grid(row=5, column=0)
tk.Label(root1, text = " ").grid(row=6, column=0)
tk.Button(root1, text="Back", command=root1.destroy).grid(row=7, column=0)
Graph_Frame = tk.Frame(root1)
Graph_Frame.grid(row=2, column=2, columnspan=10, rowspan=10)
Fig = Figure(figsize=(5.5,4))
a = Fig.add_subplot(111)
if Radio_Var == 1:
t,x = solveMBK(str(mscale.get()), str(bscale.get()), str(kscale.get()), str(A_entry.get()), str(x0_Entry.get()), str(dxdt_Entry.get()), str(tfinal_entry.get()), str(dt_entry.get()))
a.plot(t,x)
# elif Radio_Var == 2:
# t,x = solveMBK()
# a.plot(t,x)
tk.Label(Graph_Frame, text = "Mass-Spring-Damper Plot").pack()
canvas = FigureCanvasTkAgg(Fig, Graph_Frame)
canvas.draw()
canvas.get_tk_widget().pack()
toolbar = NavigationToolbar2Tk(canvas, Graph_Frame)
toolbar.update()
canvas.get_tk_widget().pack()
def CloseWindow():
root.quit()
root.destroy()
exit()
def funcPlot(input_list, mscale, bscale, kscale, a, canvas, event=None):
input_list[0]=float(x0_Entry.get())
input_list[1]=float(dxdt_Entry.get())
input_list[2]=float(dt_entry.get())
input_list[3]=float(mscale.get())
input_list[4]=float(bscale.get())
input_list[5]=float(kscale.get())
input_list[6]=float(tfinal_entry.get())
input_list[7]=float(Radio_Var.get())
data = solveMBK(input_list)
a.plot(data[0], data[1])
canvas.draw()
return
root = tk.Tk()
root.title("Numerical solution of a second order differential equation")
tk.Label(root, text = "Differential Equation:").grid(row=0, column=0, sticky=tk.E)
tk.Label(root, text = "m d2x/dt2 + b dx/dt + kx = f(x)").grid(row=0, column=1)
x0_Start = tk.IntVar()
x0_Start.set("0")
x0_Entry = tk.Entry(root, width=7, textvariable = x0_Start)
tk.Label(root, text = "x(0) = ").grid(row=1, column=0, stick=tk.E), x0_Entry.grid(row=1, column=1, sticky=tk.W)
dxdt_Start = tk.IntVar()
dxdt_Start.set("0")
dxdt_Entry = tk.Entry(root, width=7, textvariable = dxdt_Start)
tk.Label(root, text = "dx(0)/dt= ").grid(row=2, column=0, sticky=tk.E), dxdt_Entry.grid(row=2, column=1, sticky=tk.W)
A_start = tk.IntVar()
A_start.set("1")
A_entry = tk.Entry(root, width=7, textvariable = A_start)
tk.Label(root, text = "A = ").grid(row=6, column=1, sticky=tk.E), A_entry.grid(row=6, column=2, sticky=tk.W)
B_start = tk.IntVar()
B_start.set("0")
B_entry = tk.Entry(root, width=7, textvariable=B_start)
tk.Label(root, text= "B =").grid(row=7,column=1, sticky=tk.E), B_entry.grid(row=7, column=2, sticky=tk.W)
tk.Label(root, text = " ").grid(row=5, column=0, sticky=tk.E)
Radio_Var = tk.IntVar()
tk.Radiobutton(root, text="A", value = 1, variable=Radio_Var).grid(row=6, column=1, sticky = tk.W)
tk.Radiobutton(root, text="sin(Bt)", value = 2, variable=Radio_Var).grid(row=7, column=1, sticky = tk.W)
Radio_Var.set(1)
tk.Label(root, text = "f(x) = ").grid(row=6, column=0, sticky=tk.E)
tk.Label(root, text = " ").grid(row=8, column=0, sticky=tk.E)
tfinal_start = tk.IntVar()
tfinal_start.set("10")
tfinal_entry = tk.Entry(root, width = 7, textvariable=tfinal_start)
tk.Label(root, text = "tfinal = ").grid(row=9, column=0, sticky=tk.E), tfinal_entry.grid(row=9, column=1, sticky=tk.W)
dt_start = tk.IntVar()
dt_start.set("0.001")
dt_entry = tk.Entry(root, width = 7, textvariable=dt_start)
tk.Label(root, text = "dt = ").grid(row=9, column=1, sticky=tk.E), dt_entry.grid(row=9, column=2, sticky=tk.W)
tk.Label(root, text = " ").grid(row=10, column=0, sticky=tk.E)
Mmin_start = tk.IntVar()
Mmin_start.set("1")
Mmin_entry = tk.Entry(root, width=7, textvariable=Mmin_start)
tk.Label(root, text = "Mmin = ").grid(row=11, column=0, sticky=tk.E), Mmin_entry.grid(row=11, column=1, sticky=tk.W)
Mmax_start = tk.IntVar()
Mmax_start.set("100")
Mmax_entry = tk.Entry(root, width=7, textvariable=Mmax_start)
tk.Label(root, text = "Mmax = ").grid(row=11,column=1, sticky=tk.E), Mmax_entry.grid(row=11, column=2, sticky=tk.W)
bmin_start = tk.IntVar()
bmin_start.set("1")
bmin_entry = tk.Entry(root, width=7, textvariable=bmin_start)
tk.Label(root, text = "bmin = ").grid(row=12, column=0, sticky=tk.E), bmin_entry.grid(row=12, column=1, sticky=tk.W)
bmax_start = tk.IntVar()
bmax_start.set("250")
bmax_entry = tk.Entry(root, width=7, textvariable=bmax_start)
tk.Label(root, text= "bmax = ").grid(row=12, column=1, sticky=tk.E), bmax_entry.grid(row=12,column=2,sticky=tk.W)
kmin_start = tk.IntVar()
kmin_start.set("1")
kmin_entry = tk.Entry(root, width=7, textvariable=kmin_start)
tk.Label(root, text= "kmin = ").grid(row=13, column=0, sticky=tk.E), kmin_entry.grid(row=13, column=1, sticky=tk.W)
kmax_start = tk.IntVar()
kmax_start.set("500")
kmax_entry = tk.Entry(root, width=7, textvariable=kmax_start)
tk.Label(root, text="kmax = ").grid(row=13, column=1, sticky=tk.E), kmax_entry.grid(row=13, column=2, sticky=tk.W)
tk.Button(root, text = "Quit", command=CloseWindow, width=10).grid(row=14, column=0)
tk.Button(root, text= "Plot", command=PlotWindow, width=10).grid(row=14, column=3)
root.mainloop()
Any help would be appreciated, thank you!
You're passing funcPlot as the command for Scale to call:
mscale = tk.Scale(root1, ..., command=funcPlot)
According to the documentation, command is:
A procedure to be called every time the slider is moved. This
procedure will be passed one argument, the new scale value.
But instead of taking one argument, your funcPlot() function requires six arguments:
def funcPlot(input_list, mscale, bscale, kscale, a, canvas, event=None):
Which leads to the error:
TypeError: funcPlot() missing 5 required positional arguments: 'mscale', 'bscale', 'kscale', 'a', and 'canvas'
You need to rethink how this is supposed to work. Below is my rework of your code. I got around the problem above by using global variables -- I'm not proud of that. I also had to rework the way your plot gets embedded in Tk as what you had wasn't working:
import tkinter as tk
import numpy as np
from matplotlib.backends.backend_tkagg import (FigureCanvasTkAgg, NavigationToolbar2Tk)
from matplotlib.figure import Figure
def solveMBK(inlist):
x0, dx0, dt, m, b, k, tf, Z = inlist
t = np.arange(0, tf, dt)
z0 = np.zeros_like(t)
z1 = np.zeros_like(t)
z0[0] = x0
z1[0] = dx0
for c in range(len(t) - 1):
z0[c + 1] = z0[c] + z1[c] * dt
z1[c + 1] = z1[c] + ((ABradiobutton(Z, t[c]) - k * z0[c] - b * z1[c]) / m)
return t, z0
def ABradiobutton(Z, t):
if Z == 1:
A = float(A_entry.get())
return A
if Z == 2:
B = float(B_entry.get())
return np.sin(B * t)
def PlotWindow():
global mscale, bscale, kscale, subplot, figure_canvas
plot_window = tk.Toplevel(root)
plot_window.title("Plot")
Mmin = float(Mmin_entry.get())
Mmax = float(Mmax_entry.get())
bmin = float(bmin_entry.get())
bmax = float(bmax_entry.get())
kmin = float(kmin_entry.get())
kmax = float(kmax_entry.get())
mscale = tk.Scale(plot_window, from_=Mmin, to=Mmax, label="m", bd=2, length=200, orient=tk.HORIZONTAL, command=funcPlot)
mscale.set((Mmin + Mmax) / 2)
mscale.grid(row=1, column=0)
bscale = tk.Scale(plot_window, from_=bmin, to=bmax, label="b", bd=2, length=200, orient=tk.HORIZONTAL, command=funcPlot)
bscale.set((bmin + bmax) / 2)
bscale.grid(row=3, column=0)
kscale = tk.Scale(plot_window, from_=kmin, to=kmax, label="k", bd=2, length=200, orient=tk.HORIZONTAL, command=funcPlot)
kscale.set((kmin + kmax) / 2)
kscale.grid(row=5, column=0)
tk.Label(plot_window, text=" ").grid(row=6, column=0)
tk.Button(plot_window, text="Back", command=plot_window.destroy).grid(row=7, column=0)
graph_frame = tk.Frame(plot_window)
graph_frame.grid(row=2, column=2, columnspan=10, rowspan=10)
figure = Figure(figsize=(5.5, 4))
subplot = figure.add_subplot(111)
if Radio_Var.get() == 1:
t, x = solveMBK([float(mscale.get()), float(bscale.get()), float(kscale.get()), float(A_entry.get()), float(x0_Entry.get()), float(dxdt_Entry.get()), float(tfinal_entry.get()), float(dt_entry.get())])
subplot.plot(t, x)
# elif Radio_Var.get() == 2:
# t, x = solveMBK()
# subplot.plot(t, x)
figure_canvas = FigureCanvasTkAgg(figure, master=graph_frame)
figure_canvas.draw()
figure_canvas.get_tk_widget().pack(side=tk.TOP, fill=tk.BOTH, expand=1)
toolbar = NavigationToolbar2Tk(figure_canvas, graph_frame)
toolbar.update()
figure_canvas.get_tk_widget().pack(side=tk.TOP, fill=tk.BOTH, expand=1)
tk.Label(graph_frame, text="Mass-Spring-Damper Plot").pack()
def CloseWindow():
root.quit()
root.destroy()
exit()
def funcPlot(event):
input_list = []
input_list.append(float(x0_Entry.get()))
input_list.append(float(dxdt_Entry.get()))
input_list.append(float(dt_entry.get()))
input_list.append(float(mscale.get()))
input_list.append(float(bscale.get()))
input_list.append(float(kscale.get()))
input_list.append(float(tfinal_entry.get()))
input_list.append(float(Radio_Var.get()))
t, x = solveMBK(input_list)
subplot.plot(t, x)
figure_canvas.draw()
figure_canvas = subplot = mscale = bscale = kscale = None
root = tk.Tk()
root.title("Numerical solution of a second order differential equation")
tk.Label(root, text="Differential Equation:").grid(row=0, column=0, sticky=tk.E)
tk.Label(root, text="m d2x/dt2 + b dx/dt + kx = f(x)").grid(row=0, column=1)
tk.Label(root, text="x(0) = ").grid(row=1, column=0, stick=tk.E)
x0_Start = tk.IntVar()
x0_Start.set("0")
x0_Entry = tk.Entry(root, width=7, textvariable=x0_Start)
x0_Entry.grid(row=1, column=1, sticky=tk.W)
tk.Label(root, text="dx(0)/dt = ").grid(row=2, column=0, sticky=tk.E)
dxdt_Start = tk.IntVar()
dxdt_Start.set("0")
dxdt_Entry = tk.Entry(root, width=7, textvariable=dxdt_Start)
dxdt_Entry.grid(row=2, column=1, sticky=tk.W)
tk.Label(root, text=" ").grid(row=5, column=0, sticky=tk.E)
Radio_Var = tk.IntVar()
Radio_Var.set(1)
tk.Label(root, text="f(x) = ").grid(row=6, column=0, sticky=tk.E)
tk.Radiobutton(root, text="A", value=1, variable=Radio_Var).grid(row=6, column=1, sticky=tk.W)
tk.Label(root, text="A = ").grid(row=6, column=1, sticky=tk.E)
A_start = tk.IntVar()
A_start.set("1")
A_entry = tk.Entry(root, width=7, textvariable=A_start)
A_entry.grid(row=6, column=2, sticky=tk.W)
tk.Radiobutton(root, text="sin(Bt)", value=2, variable=Radio_Var).grid(row=7, column=1, sticky=tk.W)
tk.Label(root, text="B =").grid(row=7, column=1, sticky=tk.E)
B_start = tk.IntVar()
B_start.set("0")
B_entry = tk.Entry(root, width=7, textvariable=B_start)
B_entry.grid(row=7, column=2, sticky=tk.W)
tk.Label(root, text=" ").grid(row=8, column=0, sticky=tk.E)
tk.Label(root, text="tfinal = ").grid(row=9, column=0, sticky=tk.E)
tfinal_start = tk.IntVar()
tfinal_start.set("10")
tfinal_entry = tk.Entry(root, width=7, textvariable=tfinal_start)
tfinal_entry.grid(row=9, column=1, sticky=tk.W)
tk.Label(root, text="dt = ").grid(row=9, column=1, sticky=tk.E)
dt_start = tk.IntVar()
dt_start.set("0.001")
dt_entry = tk.Entry(root, width=7, textvariable=dt_start)
dt_entry.grid(row=9, column=2, sticky=tk.W)
tk.Label(root, text=" ").grid(row=10, column=0, sticky=tk.E)
tk.Label(root, text="Mmin = ").grid(row=11, column=0, sticky=tk.E)
Mmin_start = tk.IntVar()
Mmin_start.set("1")
Mmin_entry = tk.Entry(root, width=7, textvariable=Mmin_start)
Mmin_entry.grid(row=11, column=1, sticky=tk.W)
tk.Label(root, text="Mmax = ").grid(row=11, column=1, sticky=tk.E)
Mmax_start = tk.IntVar()
Mmax_start.set("100")
Mmax_entry = tk.Entry(root, width=7, textvariable=Mmax_start)
Mmax_entry.grid(row=11, column=2, sticky=tk.W)
tk.Label(root, text="bmin = ").grid(row=12, column=0, sticky=tk.E)
bmin_start = tk.IntVar()
bmin_start.set("1")
bmin_entry = tk.Entry(root, width=7, textvariable=bmin_start)
bmin_entry.grid(row=12, column=1, sticky=tk.W)
tk.Label(root, text="bmax = ").grid(row=12, column=1, sticky=tk.E)
bmax_start = tk.IntVar()
bmax_start.set("250")
bmax_entry = tk.Entry(root, width=7, textvariable=bmax_start)
bmax_entry.grid(row=12, column=2, sticky=tk.W)
tk.Label(root, text="kmin = ").grid(row=13, column=0, sticky=tk.E)
kmin_start = tk.IntVar()
kmin_start.set("1")
kmin_entry = tk.Entry(root, width=7, textvariable=kmin_start)
kmin_entry.grid(row=13, column=1, sticky=tk.W)
tk.Label(root, text="kmax = ").grid(row=13, column=1, sticky=tk.E)
kmax_start = tk.IntVar()
kmax_start.set("500")
kmax_entry = tk.Entry(root, width=7, textvariable=kmax_start)
kmax_entry.grid(row=13, column=2, sticky=tk.W)
tk.Button(root, text="Quit", command=CloseWindow, width=10).grid(row=14, column=0)
tk.Button(root, text="Plot", command=PlotWindow, width=10).grid(row=14, column=3)
root.mainloop()
I've been following this website for a while. It is really helpful. So, thanks for all the useful tips.
I've been searching for this answer for the past two weeks without any success, so now I'm compelled to ask out of total frustration with my current obstacle.
How do you use StringVar as a list?
Basically, I was coding the following program for my wife. The code is pretty messy as it is my first program I've tried to code.
The idea was that I would take 3 variables; password, secret number and website and then do some work on them using if statements and lists to create a unique password.
First problem was that I couldn't restrict the character length of the entry widgets but in the end i solved that but i still want to limit the characters that can be input.
for instance in the website entry box, i want to allow only letters.
If I could convert StringVar to a list, I could do some work with messy if statements to allow only certain characters in each index but everythime i try it says that stringvars cant be used as a list.
I need them as a list to limit the type of characters that can be entered and also so that i can do work on the variables to get the final output.
CODE:
from Tkinter import *
import Tkinter
from PIL import Image, ImageTk
import os
Title= ("Helvetica", 20, "bold", "underline")
Heading= ("Courier", 20, "bold")
Body= ("Courier", 15)
Body1= ("Courier", 15, "bold")
notice= ("Courier", 10)
Body2= ("Courier", 15, "bold", "underline")
root = Tk()
root.title("Koala Series: Encrypter")
root.configure(background="#ffefd5")
root.geometry('{}x{}'.format(510, 600))
root.columnconfigure(0, weight=1)
root.rowconfigure(0, weight=1) # not needed, this is the default behavior
root.rowconfigure(1, weight=1)
root.rowconfigure(2, weight=1)
website = StringVar()
Titlemsg = Label(root, text="Koala Encrypter", font=Title, bg="#00FA9A", relief=RAISED,)
Titlemsg.grid( row=7, pady=25, sticky=N+S+E+W)
img1 = ImageTk.PhotoImage(Image.open("koala.jpeg"))
startpic = Label(root, image = img1, relief=RIDGE )
startpic.grid( row=10,pady=25, )
Head = Label(root,anchor=CENTER,text="Welcome to the Koala Encrypter \n\n A Koala series tool that allows you\n\n to Encrypt your passwords \n\n Click \'Start Encrypting\' to continue \n\n", font=Body, bg="#ffefd5", relief=RAISED,)
Head.grid( row=14, pady=25, columnspan=2, sticky=N+S+E+W)
web = Label(root, text="WEBSITE: ", font=Body, bg="#ffefd5", justify=CENTER,)
#website.set("Enter your website here")
entry = Entry(root,textvariable=website , justify=CENTER,relief=SUNKEN,cursor="pencil", takefocus=True )
Notice1 = Label( text="Please only insert the first 5 letters of the website!!",font=notice, bg="#ffefd5", fg="#0000ff",)
passw = Label(root, text="PASSWORD: ", font=Body, bg="#ffefd5", justify=CENTER)
passwordvar= StringVar()
entry1 = Entry(root, textvariable= passwordvar, justify=CENTER,relief=SUNKEN, cursor="pencil", takefocus=True )
Notice= Label(root, text="Your password must only be 5 characters long!!", font=notice, bg="#ffefd5", fg="#0000ff", justify=CENTER)
def callback(event):
if "<0>":
top = Toplevel(bg="#ffefd5")
top.title("Koala Encrypter")
popuptitle = Label(top, text="Your secret number must be between 1 and 9:", font=Body1, fg="red", bg="#ffefd5")
popuptitle.grid(row = 2,column=0, padx=5, pady = 50,sticky=N+S+E+W)
secret = Label(root, text="SECRET NUMBER: ", font=Body, bg="#ffefd5" , justify=CENTER,)
numbervar = StringVar()
entry2 = Entry(root, textvariable=numbervar , justify=CENTER,relief=SUNKEN,cursor="pencil", takefocus=True)
entry2.bind("<0>", callback)
Notice2 = Label(root, text="your secret number must be between 1 and 9!!!", font=notice, bg="#ffefd5", fg="#0000ff", justify=CENTER)
img = ImageTk.PhotoImage(Image.open("Koalalogo.jpg"))
panel = Label(root, image = img, relief=SUNKEN)
correct= Label(root, text="Check the below details \n\n Click \'yes\' if they are correct \n\n Click \'No\' to go back \n\n", font=Body1, bg="#ffefd5")
yourwebsite = Label(root, text="The Website is :", font=Body, bg="#ffefd5")#
website1 = Label(root, font=Body2, bg="#ffefd5",fg= "#00009C", textvariable = website)#
yourpassword = Label(root, text="Your Password is:", font=Body, bg="#ffefd5")
yournumber1= Label(root, font=Body2, bg="#ffefd5",textvariable = numbervar , fg= "#00009C", )
yourpassword1 = Label(root, font=Body2, bg="#ffefd5",textvariable = passwordvar , fg= "#00009C", )
yournumber= Label(root, text="Your Secret Number is:", font=Body, bg="#ffefd5")
def restart():
Titlemsg.grid_forget()
correct.grid_forget()
yourwebsite.grid_forget()
website1.grid_forget()
yourpassword.grid_forget()
yourpassword1.grid_forget()
yournumber.grid_forget()
yournumber1.grid_forget()
panel.grid_forget()
toolbar.grid_forget()
yes.grid_forget()
no.grid_forget()
entry.delete(0,END)
entry1.delete(0,END)
entry2.delete(0,END)
Titlemsg.grid( row=7, pady=25, sticky=N+S+E+W)
startpic.grid( row=10,pady=25, )
Head.grid( row=14, pady=25, columnspan=2, sticky=N+S+E+W)
toolbar.grid( row=21, )
end.grid(column =3, row=1, sticky=N+S+E+W)
begin.grid(column =2, row=1, sticky=N+S+E+W)
def start():
#entry.destroy()
#entry1.destroy()
#entry2.destroy()
toolbar.grid_forget()
Titlemsg.grid_forget()
begin.grid_forget()
Head.grid_forget()
startpic.grid_forget()
web.grid(row=3, column=0, sticky= W+E)
entry.grid( row=3, column=1, padx=50)
passw.grid(row=10, column=0)
Notice1.grid(row=4, sticky=N+S+E+W, columnspan=2)
entry1.grid(row=10, column=1)
Notice.grid(row=11,column=0, columnspan=2,)
secret.grid(row=13, column=0)
entry2.grid( row=13, column=1)
Notice2.grid( row=14,column=0, columnspan=2,)
panel.grid(row=20,columnspan=2, pady=70)
confirm.grid(column =1, row=1)
reset.grid(column =2, row=1)
end.grid(column =3, row=1)
toolbar.grid(row=21, column=0, columnspan=2)
Titlemsg.grid(row=0, column=0, columnspan=2, sticky=E+W)
def Reset():
entry.delete(0,END)
entry1.delete(0,END)
entry2.delete(0,END)
def clear_text():
#entry.destroy()
#entry1.destroy()
#entry2.destroy()
panel.grid_forget()
entry.grid_forget()
entry1.grid_forget()
entry2.grid_forget()
web.grid_forget()
Notice.grid_forget()
passw.grid_forget()
secret.grid_forget()
Notice1.grid_forget()
Notice2.grid_forget()
confirm.grid_forget()
reset.grid_forget()
toolbar.grid_forget()
Titlemsg.grid_forget()
Titlemsg.grid(row=0, column=0, columnspan=2, sticky=E+W)
correct.grid(row=1, column=0, columnspan=2, sticky=E+W)
yourwebsite.grid(row=2,column=0,sticky=E+W, pady=5)
website1.grid(row=2, column=1, padx=65,sticky=E+W, pady=5)
yourpassword.grid(row=4, column=0,sticky=E+W, pady=5)
yourpassword1.grid(row=4, column=1, padx=65,sticky=E+W, pady=5)
yournumber.grid(row=6, column=0,sticky=E+W, pady=5)
yournumber1.grid(row=6, column=1, padx=65,sticky=E+W, pady=5)
panel.grid(row=8, column=0, columnspan=2, pady=50)
toolbar.grid(row=10, column=0, columnspan=2)
yes.grid(column =1, row=1)
no.grid(column =2, row=1)
def popup():
top = Toplevel(bg="#ffefd5")
top.title("Koala Encrypter")
popuptitle = Label(top, text="Your password is:", font=Body1, fg="red", bg="#ffefd5")
popuptitle.grid(row = 2,column=0, padx=5, pady = 50,sticky=N+S+E+W)
pwd= Label(top, font=Body2, text="password", bg="#ffefd5", fg= "#00009C", ) #textvariable = newpassword ,
pwd.grid(row= 2, column=1,sticky=E+W,padx=15)
button = Button(top, text="OK", command=top.destroy, relief=RAISED )
button.grid(column =0,columnspan=2, row=4, sticky=N+S+E+W)
def helpmsg():
top = Toplevel(bg="#ffefd5")
top.title("Koala Encrypter")
popuptitle = Label(top, text="Koala series 1.0 - Koala Encrypter", font=Title, bg="#00FA9A", relief=RAISED,)
popuptitle.grid(row = 2,column=0, padx=5, pady = 50,sticky=N+S+E+W)
pwd= Label(top, font=Body, text="Free software to help you keep your acounts safe", bg="#ffefd5")
pwd.grid(row= 1,sticky=E+W,)
Titlems = Label(top, text="Koala Encrypter", font=Title, bg="#00FA9A", relief=RAISED,)
Titlems.grid( row=0, pady=25, sticky=N+S+E+W)
button = Button(top, text="OK", command=top.destroy, relief=RAISED )
button.grid(column =0,columnspan=2, row=4, sticky=N+S+E+W)
max_len = 5
def on_write(*args):
s = website.get()
if len(s) > max_len:
website.set(s[:max_len])
website.trace_variable("w", on_write)
max_len1 = 5
def on_write(*args):
s = passwordvar.get()
if len(s) > max_len1:
passwordvar.set(s[:max_len1])
passwordvar.trace_variable("w", on_write)
max_len2 = 1
def on_write(*args):
s = numbervar.get()
if len(s) > max_len2:
numbervar.set(s[:max_len2])
numbervar.trace_variable("w", on_write)
toolbar = Frame(root)
reset = Button(toolbar, text="Reset", width=6, command=Reset, cursor="cross", relief=RAISED, takefocus=True )
end = Button(toolbar, text="Quit" ,command=root.destroy, relief=RAISED, cursor="X_cursor", takefocus=True)
end.grid(column =3, row=1, sticky=N+S+E+W)
begin = Button(toolbar, text="Start Encrypting", command=start, relief=RAISED, cursor="star",takefocus=True )
begin.grid(column =2, row=1, sticky=N+S+E+W)
confirm = Button(toolbar, text="Next", command =clear_text, cursor="star", relief=RAISED,takefocus=True )
yes = Button(toolbar, text="Yes", command =popup, cursor="star", relief=RAISED,takefocus=True )
no = Button(toolbar, text="No", command =restart, cursor="pirate", relief=RAISED, takefocus=True )
toolbar.grid( row=21, )
menu = Menu(root)
root.config(menu=menu)
filemenu = Menu(menu)
menu.add_cascade(label="File", menu=filemenu)
filemenu.add_command(label="Restart", command=restart)
filemenu.add_separator()
filemenu.add_command(label="Exit", command=root.destroy)
helpmenu = Menu(menu)
menu.add_cascade(label="Help", menu=helpmenu, )
helpmenu.add_command(label="About...", command=helpmsg)
app = root
root.mainloop()
# add functionality, fix validation
To restrict the type/number of characters that can be typed into an entry widget, you can use the entry validatecommand. Here is an example to allow only letters and another one to restrict the entry to 4 digits:
from tkinter import Tk, Entry, Label
def only_letters(action, char):
if action == "1":
# a character is inserted (deletion is 0) allow the insertion
# only if the inserted character char is a letter
return char.isalpha()
else:
# allow deletion
return True
def only_numbers_max_4(action, new_text):
if action == "1":
return new_text.isdigit() and len(new_text) <= 4
else:
return True
root = Tk()
# register validate commands
validate_letter = root.register(only_letters)
validate_nb = root.register(only_numbers_max_4)
Label(root, text="Only letters: ").grid(row=0, column=0)
e1 = Entry(root, validate="key", validatecommand=(validate_letter, '%d', '%S'))
# %d is the action code and %S the inserted/deleted character
e1.grid(row=0, column=1)
Label(root, text="Only numbers, at most 4: ").grid(row=1, column=0)
e2 = Entry(root, validate="key", validatecommand=(validate_nb, '%d', '%P'))
# %P is the new content of the entry after the modification
e2.grid(row=1, column=1)
root.mainloop()
For more details on entry validation, see http://infohost.nmt.edu/tcc/help/pubs/tkinter/web/entry-validation.html
I have created a window with a button saying Enter, when clicked I would like it to proceed to an options menu with 3 separate sliders whereby the user can adjust them to get a value then press enter. With this value I would like to have a timed output that is the same as that value in seconds. I am very new to Python and need as much help as possible please :)
This is my code so far; and so far the first enter screen will appear then when the enter button is pressed it will load the next window I have created with the three sliders inside it I am not sure this is the best way to do it? Complete novis!
Please Advise :)
FIRST WINDOW FOR "PRESS ENTER SCREEN"
#! /usr/bin/env python
from Tkinter import *
def callback():
execfile('process screen 2nd draft.py')
exit
window = Tk()
window.title( 'company name ' )
window.configure ( bg = 'purple' )
label = Label( window, text = 'company name with slogan ' )
label.grid(row=0, column=1)
btn_nxt = Button( window , bg = 'purple', text = 'Enter' , command=callback , )
btn_nxt.grid(row=1, column=1, padx=100, pady=100)
window.mainloop()
SECOND WINDOW FOR OPTIONS MENU 3 SEPERATE SLIDERS
#! /usr/bin/env python
from Tkinter import *
window = Tk()
window.title( 'random title' )
window.configure( bg = 'purple' )
def show_values () :
print (w1.get(), w2.get(), w3.get())
btn_ent = Button( window , text = 'Enter' , command=show_values)
btn_ent.grid(row=3, column=3, padx=5, pady=5)
label_chem= Label( window , bg = 'purple', text = 'Please Choose Chemical Levels' )
label_chem.grid(row=0, column=2, padx=5, pady=5)
label_nic= Label( window , bg = 'purple', text = 'Nictonine (mg)' )
label_nic.grid(row=1, column=1, padx=5, pady=5)
label_glyc= Label( window , bg = 'purple', text = 'Glycol (mg)' )
label_glyc.grid(row=1, column=2, padx=5, pady=5)
label_gli= Label( window , bg = 'purple', text = 'Glycerine (mg) ' )
label_gli.grid(row=1, column=3, padx=5, pady=5)
w1 = Scale( window, bg = 'purple', from_=30, to=0, orient=VERTICAL, resolution=0.5 )
w1.grid(row=2, column=1, padx=5, pady=5)
w2 = Scale( window, bg = 'purple', from_=30, to=0, orient=VERTICAL, resolution=0.5 )
w2.grid(row=2, column=2, padx=5, pady=5)
w3 = Scale( window, bg = 'purple', from_=30, to=0, orient=VERTICAL, resolution=0.5 )
w3.grid(row=2, column=3, padx=5, pady=5)
window.mainloop()
First version with Toplevel to create second window and timed window - all in one file.
I use after(time_miliseconds, function_name) to run function after time_miliseconds
Press buton Enter to see timed window. It closes after constant time.
#! /usr/bin/env python
from Tkinter import *
#-----------------------------------------------
# global variable
time = 0
#-----------------------------------------------
# second window
def second_window():
subwindow = Toplevel(window)
subwindow.title('random title')
subwindow.configure(bg='purple')
def show_values():
print w1.get(), w2.get(), w3.get()
btn_ent = Button(subwindow, text='Enter', command=timed_window)
btn_ent.grid(row=3, column=3, padx=5, pady=5)
label_chem = Label(subwindow, bg='purple', text='Please Choose Chemical Levels')
label_chem.grid(row=0, column=2, padx=5, pady=5)
label_nic = Label(subwindow, bg='purple', text='Nictonine (mg)')
label_nic.grid(row=1, column=1, padx=5, pady=5)
label_glyc = Label(subwindow, bg='purple', text='Glycol (mg)')
label_glyc.grid(row=1, column=2, padx=5, pady=5)
label_gli = Label(subwindow , bg='purple', text='Glycerine (mg)')
label_gli.grid(row=1, column=3, padx=5, pady=5)
w1 = Scale(subwindow, bg='purple', from_=30, to=0, orient=VERTICAL, resolution=0.5)
w1.grid(row=2, column=1, padx=5, pady=5)
w2 = Scale(subwindow, bg='purple', from_=30, to=0, orient=VERTICAL, resolution=0.5)
w2.grid(row=2, column=2, padx=5, pady=5)
w3 = Scale(subwindow, bg='purple', from_=30, to=0, orient=VERTICAL, resolution=0.5)
w3.grid(row=2, column=3, padx=5, pady=5)
#-----------------------------------------------
# timed window
def timed_window():
global time
time = 50
def countdown():
global time
if time > 0:
time -= 1
lab.config(text=str(time))
subwindow.after(100, countdown) # 100 miliseconds
else:
subwindow.destroy()
subwindow = Toplevel(window)
subwindow.title('countdown')
subwindow.configure(bg='purple')
lab = Label(subwindow, bg='purple', text=str(time))
lab.pack(padx=20, pady=20)
subwindow.after(100, countdown) # 100 miliseconds
#-----------------------------------------------
# mainwindow
window = Tk()
window.title('company name')
window.configure(bg='purple')
label = Label(window, text='company name with slogan')
label.grid(row=0, column=1)
btn_nxt = Button(window, bg='purple', text='Enter', command=second_window)
btn_nxt.grid(row=1, column=1, padx=100, pady=100)
window.mainloop()
Second version with one window and two frames - all in one file.
I use pack() and pack_forget() to show and hide frames.
I use the same timed window as before.
#! /usr/bin/env python
from Tkinter import *
#-----------------------------------------------
frame_1 = None
frame_2 = None
time = 0
#-----------------------------------------------
def create_frame_1():
global frame_1
frame_1 = Frame(window)
frame_1.configure(bg='purple')
label = Label(frame_1, text='company name with slogan')
label.grid(row=0, column=1)
btn_nxt = Button(frame_1, bg='purple', text='Enter', command=show_frame_2)
btn_nxt.grid(row=1, column=1, padx=100, pady=100)
def create_frame_2():
def show_values():
print w1.get(), w2.get(), w3.get()
global frame_2
frame_2 = Frame(window)
frame_2.configure(bg='purple')
btn_ent = Button(frame_2, text='Enter', command=timed_window)
btn_ent.grid(row=3, column=3, padx=5, pady=5)
label_chem = Label(frame_2, bg='purple', text='Please Choose Chemical Levels')
label_chem.grid(row=0, column=2, padx=5, pady=5)
label_nic = Label(frame_2, bg='purple', text='Nictonine (mg)')
label_nic.grid(row=1, column=1, padx=5, pady=5)
label_glyc = Label(frame_2, bg='purple', text='Glycol (mg)')
label_glyc.grid(row=1, column=2, padx=5, pady=5)
label_gli = Label(frame_2 , bg='purple', text='Glycerine (mg)')
label_gli.grid(row=1, column=3, padx=5, pady=5)
w1 = Scale(frame_2, bg='purple', from_=30, to=0, orient=VERTICAL, resolution=0.5)
w1.grid(row=2, column=1, padx=5, pady=5)
w2 = Scale(frame_2, bg='purple', from_=30, to=0, orient=VERTICAL, resolution=0.5)
w2.grid(row=2, column=2, padx=5, pady=5)
w3 = Scale(frame_2, bg='purple', from_=30, to=0, orient=VERTICAL, resolution=0.5)
w3.grid(row=2, column=3, padx=5, pady=5)
btn_back = Button(frame_2, text='Back', command=show_frame_1)
btn_back.grid(row=3, column=1, padx=5, pady=5)
#-----------------------------------------------
def show_frame_1():
frame_2.pack_forget()
window.title('company name')
frame_1.pack()
def show_frame_2():
frame_1.pack_forget()
window.title('random title')
frame_2.pack()
#-----------------------------------------------
def timed_window():
global time
time = 50
def countdown():
global time
if time > 0:
time -= 1
lab.config(text=str(time))
subwindow.after(100, countdown) # 100 miliseconds
else:
subwindow.destroy()
subwindow = Toplevel(window)
subwindow.title('countdown')
subwindow.configure(bg='purple')
lab = Label(subwindow, bg='purple', text=str(time))
lab.pack(padx=20, pady=20)
subwindow.after(100, countdown) # 100 miliseconds
#-----------------------------------------------
window = Tk()
create_frame_1()
create_frame_2()
show_frame_1()
window.mainloop()
I have a program where the main window is divided into two sections each section has a collection of forms (simple label/input columns). The default is 4 of these columns in the first section and 2 in the second section. I would like the user to be able to change this ratio. I think I have all of the programming in place to do this, I just can't get the main window to redraw with the correct structure. Any help would be much appreciated. Thanks.
I like the simplicity and idea behind your example, however, I'm modifying some legacy code and don't have the time to rewrite my layouts as definitions. I tried to create a def that would simply do grid_columnconfig(), but that didn't work. I've reduced the code so that it looks like what I'm working with and it is also functional. If you change the variable 'max_pol_modules' it adjusts columns on the left versus columns on the right, so, I'm trying to change this variable through an interface widget and redraw.
from Tkinter import *
import tkFont
max_pol_modules = 3
max_bus_modules = 6 - max_pol_modules
tech_green = '#5E9732'
button_grey = '#666666'
grey = '#777777'
def config1():
global max_pol_modules, max_bus_modules
max_pol_modules = 1
max_bus_modules = 6 - max_pol_modules
# print max_bus_modules
# left_frame.update()
def config2():
global max_pol_modules, max_bus_modules
max_pol_modules = 2
max_bus_modules = 6 - max_pol_modules
# print max_bus_modules
def config3():
global max_pol_modules, max_bus_modules
max_pol_modules = 3
max_bus_modules = 6 - max_pol_modules
# print max_bus_modules
def config4():
global max_pol_modules, max_bus_modules
max_pol_modules = 4
max_bus_modules = 6 - max_pol_modules
# print max_bus_modules
def about():
box.showinfo("About GUI","GE Bus Converter and Point of Load GUI")
def bar(frame, row, span):
"create a bar to separate a section"
x = Frame(frame, relief=GROOVE, bd=2, width=86*(span+1), height=2)
x.grid(row=row, column=0, columnspan=10, pady=7, sticky=S+E)
x.grid_propagate(0)
def bar2(frame, row, span):
"create a bar to separate a section"
x = Frame(frame, relief=GROOVE, bd=2, width=86*(span+1), height=2)
x.grid(row=row, column=0, columnspan=10, pady=3, sticky=S+E)
x.grid_propagate(0)
def bar3(frame, row, span):
"create a bar to separate a section"
x = Frame(frame, relief=GROOVE, bd=2, width=100, height=2)
x.grid(row=row, column=0, columnspan=10, pady=7, sticky=S+E)
x.grid_propagate(0)
root = Tk()
menubar = Menu(root)
submenu=Menu(menubar,tearoff=0)
submenu2=Menu(submenu,tearoff=0)
submenu2.add_command(label="1 - 5", command=config1)
submenu2.add_command(label="2 - 4", command=config2)
submenu2.add_command(label="3 - 3", command=config3)
submenu2.add_command(label="4 - 2", command=config4)
submenu_help = Menu(submenu,tearoff=0)
submenu_help.add_command(label="About",command=about)
submenu.add_cascade(label="Change Configuration",menu=submenu2)
submenu.add_command(label="Exit", command=root.quit)
menubar.add_cascade(label="Settings",menu=submenu)
menubar.add_cascade(label="Help", menu=submenu_help)
# display the menu
root.config(menu=menubar)
entry_wid = 6
small_font = tkFont.Font(family='Arial', size=8, weight='bold')
lite_font = tkFont.Font(family='Arial', size=9)
large_font = tkFont.Font(family='Arial', size=9)
heading_font = tkFont.Font(family='Arial', size=10, weight='bold')
button_font = tkFont.Font(family='Arial', size=8, weight='bold')
root.option_add('*font', lite_font)
root.option_add('*background', '#C2C2C4')
root.option_add('*Label.font', small_font)
root.option_add('*Entry.background', 'white')
root.option_add('*Button.font', button_font)
root.option_add('*Button.background', button_grey)
root.option_add('*Button.foreground', 'yellow')
root.option_add('*Text.background', 'white')
root.option_add('*Text.font', small_font)
root.option_add('*ScrolledText.font', lite_font)
left_frame = Frame(root)
right_frame = Frame(root)
pol_frame = Frame(left_frame, bd=2, relief=SUNKEN)
x = Label(pol_frame, text="POL Address", anchor=E)
x.grid(row=0, column=0, sticky=E)
x = Label(pol_frame, text="Rtrim (Kohms)", anchor=E)
x.grid(row=1, column=0, sticky=E)
x = Label(pol_frame, text="Nominal Vout (V)", anchor=E)
x.grid(row=2, column=0, sticky=E)
bar2(pol_frame, 0, max_pol_modules)
module_address = []
module_i2c = []
module_status = []
module_resistor = []
module_vout_nominal = []
for i in range(max_pol_modules):
# Module ID and address
f = Frame(pol_frame)
x = Label(f, text=i+1)
x.grid(row=0, column=0)
v = StringVar()
x = Entry(f, textvariable=v, width=3, justify=CENTER)
x.grid(row=0, column=1)
f.grid(row=0, column=i+1, pady=8, padx=20)
module_address.append(v)
module_i2c.append("")
module_status.append(0)
# module resistor
v = StringVar()
x = Entry(pol_frame, textvariable=v, width=entry_wid, justify=CENTER)
f = lambda event, module=i: change_resistor_event(event, module)
g = lambda value, m=i, o=16: set_change(value, m, o)
x.bind("<KeyRelease>", f, "+")
x.bind("<KeyRelease>", g, "+")
x.bind("<FocusOut>", f, "+")
x.grid(row=1, column=i+1, pady=0)
module_resistor.append(v)
# module nominal vout
v = StringVar()
x = Label(pol_frame, textvariable=v, width=entry_wid-1,
relief=SUNKEN, bg='#DDDDDD', font=lite_font)
x.grid(row=2, column=i+1, pady=0)
module_vout_nominal.append(v)
bus_frame = Frame(left_frame, bd=2, relief=SUNKEN)
#x = Label(bus_frame, text="Module (address)", anchor=E)
#x.grid(row=0, column=max_pol_modules+1, sticky=E)
x = Label(bus_frame, text="Bus Conv Address", anchor=E)
x.grid(row=0, column=0, sticky=E)
config_bus = []
r = 0
#for i in range(max_pol_modules,max_pol_modules+max_bus_modules):
for i in range(max_bus_modules):
# Module ID and address
f = Frame(bus_frame)
x = Label(f, text=i+5)
x.grid(row=0, column=0)
v = StringVar()
x = Entry(f, textvariable=v, width=3, justify=CENTER)
x.grid(row=0, column=1)
f.grid(row=0, column=i+2, pady=8, padx=20)
module_address.append(v)
module_i2c.append("")
module_status.append(0)
bar2(bus_frame, r, max_bus_modules)
r += 1
# the measured values
measure_info = ["Vout (V)", "Iout (A)", "Vin (V)", "Temp (degC)"]
measures_bus = []
for mi in measure_info:
x = Label(bus_frame, text=mi, anchor=E)
x.grid(row=r, column=0, sticky=E)
m = []
for j in range(max_bus_modules):
v = StringVar()
x = Label(bus_frame, textvariable=v, width=entry_wid-1,
relief=SUNKEN, bg='#DDDDDD', font=lite_font)
x.grid(row=r, column=j+2)
m.append(v)
measures_bus.append(m)
r += 1
pol_frame.grid(row=0, column=0, sticky=N+W)
bus_frame.grid(row=0, column=1, sticky=N+W)
left_frame.grid(row=0, column=0, sticky=N)
right_frame.grid(row=0, column=1, sticky=N)
root.mainloop()
Edited Example where form[4] and form[5] need to be deleted.
import Tkinter as tk
class App(tk.Tk):
def __init__(self, *args, **kwargs):
tk.Tk.__init__(self, *args, **kwargs)
self.forms = []
self.toolbar = tk.Frame(self)
self.toolbar.pack(side="top", fill="x", expand=False)
button2 = tk.Button(self.toolbar, text="2 columns", command=self.layout2col)
button3 = tk.Button(self.toolbar, text="3 columns", command=self.layout3col)
button2.pack(side="left")
button3.pack(side="left")
self.forms_frame = tk.Frame(self, borderwidth=2, relief="groove")
self.forms_frame.pack(side="top", fill="both", expand="True", padx=2, pady=2)
for i in range(6):
frame = tk.LabelFrame(self.forms_frame, text="Form %s" % i)
self.forms.append(frame)
label = tk.Label(frame, text="Field %s" % i)
entry = tk.Entry(frame, width=20)
label.pack(side="left", fill="y")
entry.pack(side="left", fill="both", expand=True)
self.layout2col()
def layout3col(self):
self.forms[0].grid(column=0, row=0, padx=4, pady=2, sticky="ew")
self.forms[1].grid(column=0, row=1, padx=4, pady=2, sticky="ew")
self.forms[2].grid(column=1, row=0, padx=4, pady=2, sticky="ew")
self.forms[3].grid(column=1, row=1, padx=4, pady=2, sticky="ew")
self.forms[4].grid(column=2, row=0, padx=4, pady=2, sticky="ew")
self.forms[5].grid(column=2, row=1, padx=4, pady=2, sticky="ew")
self.forms_frame.grid_columnconfigure(0, weight=1)
self.forms_frame.grid_columnconfigure(1, weight=1)
self.forms_frame.grid_columnconfigure(2, weight=1)
def layout2col(self):
self.forms[0].grid(column=0, row=0, padx=4, pady=2, sticky="ew")
self.forms[1].grid(column=0, row=1, padx=4, pady=2, sticky="ew")
self.forms[2].grid(column=1, row=0, padx=4, pady=2, sticky="ew")
self.forms[3].grid(column=1, row=1, padx=4, pady=2, sticky="ew")
self.forms_frame.grid_columnconfigure(0, weight=1)
self.forms_frame.grid_columnconfigure(1, weight=1)
self.forms_frame.grid_columnconfigure(2, weight=0)
if __name__ == "__main__":
app = App()
app.mainloop()
Since you are using the grid geometry manager, you just need to use the grid method to place them in their new rows and columns. You may need to also call rowconfigure and/or columnconfigure to attach appropriate weights to the new rows and columns.
Here's a bit of a contrived example showing the general principle. It could be more efficient but hopefully it gives you a rough idea:
import Tkinter as tk
class App(tk.Tk):
def __init__(self, *args, **kwargs):
tk.Tk.__init__(self, *args, **kwargs)
self.forms = []
self.toolbar = tk.Frame(self)
self.toolbar.pack(side="top", fill="x", expand=False)
button2 = tk.Button(self.toolbar, text="2 columns", command=self.layout2col)
button3 = tk.Button(self.toolbar, text="3 columns", command=self.layout3col)
button2.pack(side="left")
button3.pack(side="left")
self.forms_frame = tk.Frame(self, borderwidth=2, relief="groove")
self.forms_frame.pack(side="top", fill="both", expand="True", padx=2, pady=2)
for i in range(6):
frame = tk.LabelFrame(self.forms_frame, text="Form %s" % i)
self.forms.append(frame)
label = tk.Label(frame, text="Field %s" % i)
entry = tk.Entry(frame, width=20)
label.pack(side="left", fill="y")
entry.pack(side="left", fill="both", expand=True)
self.layout2col()
def layout3col(self):
self.forms[0].grid(column=0, row=0, padx=4, pady=2, sticky="ew")
self.forms[1].grid(column=0, row=1, padx=4, pady=2, sticky="ew")
self.forms[2].grid(column=1, row=0, padx=4, pady=2, sticky="ew")
self.forms[3].grid(column=1, row=1, padx=4, pady=2, sticky="ew")
self.forms[4].grid(column=2, row=0, padx=4, pady=2, sticky="ew")
self.forms[5].grid(column=2, row=1, padx=4, pady=2, sticky="ew")
self.forms_frame.grid_columnconfigure(0, weight=1)
self.forms_frame.grid_columnconfigure(1, weight=1)
self.forms_frame.grid_columnconfigure(2, weight=1)
def layout2col(self):
self.forms[0].grid(column=0, row=0, padx=4, pady=2, sticky="ew")
self.forms[1].grid(column=0, row=1, padx=4, pady=2, sticky="ew")
self.forms[2].grid(column=0, row=2, padx=4, pady=2, sticky="ew")
self.forms[3].grid(column=1, row=0, padx=4, pady=2, sticky="ew")
self.forms[4].grid(column=1, row=1, padx=4, pady=2, sticky="ew")
self.forms[5].grid(column=1, row=2, padx=4, pady=2, sticky="ew")
self.forms_frame.grid_columnconfigure(0, weight=1)
self.forms_frame.grid_columnconfigure(1, weight=1)
self.forms_frame.grid_columnconfigure(2, weight=0)
if __name__ == "__main__":
app = App()
app.mainloop()
You've probably already tried this, but can you call update() on your root widget?
You might also need to pack() again, first.