First, when the number of rectangles is entered less than 24 it works fine. When I put the number of rectangles more than 24, the entry boxes exceed the window height and I cannot see it. I want to use a scroll bar at the right side when the number of entry boxes exceeds the window height. The documentation implies that only the List, Textbox, Canvas and Entry widgets support the scrollbar interface. So, how can I do for gridboxes?
Note : The code is verifiable.
from tkinter import *
temp_recta = []
def save_content(top):
for j in range(0, int(rectangles.get()) * 2):
temp_recta.append(rectangle_values[j].get())
root = Toplevel()
l1 = Label(root, text="Size of Sheet[Height]:")
l1.grid(row=0, column=0)
l2 = Label(root, text="Size of Sheet[Width]:")
l2.grid(row=1, column=0)
height = StringVar()
e1 = Entry(root, textvariable=height)
e1.grid(row=0, column=1)
width = StringVar()
e2 = Entry(root, textvariable=width)
e2.grid(row=1, column=1)
b5 = Button(root, text="Proceed", width=12, command=lambda: save_sheetsize(e1, e2, root))
b5.grid(row=2, column=0)
b6 = Button(root, text="Back", width=12, command=lambda: (root.destroy(), top.deiconify()))
b6.grid(row=2, column=1)
root.title("Sheet Size")
def save_sheetsize(e1, e2, root):
global x
global y
x = float(e2.get())
y = float(e1.get())
root.destroy()
window.destroy()
rectangle_values = []
x = 0
y = 0
k = 0
def open_window():
window.withdraw()
global k
top = Toplevel()
top.title("Rectangles")
for i in range(0, int(rectangles.get()) * 2):
if (i % 2) == 0:
l4 = Label(top, text="Size of rectangle:")
l4.grid(row=i, column=0)
rectangle_values.append(StringVar())
en = Entry(top, textvariable=rectangle_values[i])
en.grid(row=i, column=1)
b3 = Button(top, text="Save", width=12, command=lambda: (top.withdraw(), save_content(top)))
b3.grid(row=int(rectangles.get()) * 2 + 1, column=0)
b4 = Button(top, text="Back", width=12, command=lambda: (top.destroy(), window.deiconify()))
b4.grid(row=int(rectangles.get()) * 2 + 1, column=1)
k = int(rectangles.get())
window = Tk()
l3 = Label(window, text="Number of Rectangles:")
l3.grid(row=0, column=0)
rectangles = StringVar()
e3 = Entry(window, textvariable=rectangles)
e3.grid(row=0, column=1)
b1 = Button(window, text='Submit', width=12, command=open_window)
b1.grid(row=3, column=1)
window.title("Rectangle Configuration")
window.mainloop()
Here is a simple class to do this. Add your text widget and it will give you a scrollbar when your window is full of text.
import tkinter
class Scrollbar:
def __init__(self,text):
self.frame = text.master
self.text = text
self.text.configure(wrap='none')
self.for_x_view()
self.for_y_view()
def for_x_view(self):
# scroll Bar x For width
scroll_x=tkinter.Scrollbar(self.frame, orient='horizontal',command=self.text.xview)
scroll_x.config(command=self.text.xview)
self.text.configure(xscrollcommand=scroll_x.set)
scroll_x.pack(side='bottom', fill='x', anchor='w')
return
def for_y_view(self):
# Scroll Bar y For Height
scroll_y = tkinter.Scrollbar(self.frame)
scroll_y.config(command=self.text.yview)
self.text.configure(yscrollcommand=scroll_y.set)
scroll_y.pack(side='right', fill='y')
return
if __name__ == '__main__':
root = tkinter.Tk()
pad = tkinter.Text(root,wrap='none')
Scrollbar(pad)
pad.pack()
root.mainloop()
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()