Tkinter Application Returns Random Values
Solution 1:
Well the code structure was a bit too harsh on me, so I had to think of other logical ways but ended up getting a hacky way around.
I've commented the code so as to make the understand easier on-the-go:
from tkinter import *
root = Tk()
root.title("Calculator")
coordinates = [] # making empty list to hold all the numbers
xi,yi,zi = [],[],[] #making empty list to hold only the corresponding numbers
n = 0 #initial value of n
X = Entry(root)
X.grid(row=0, column=0, columnspan=3, padx=12, pady=15)
Y = Entry(root)
Y.grid(row=1, column=0, columnspan=3, padx=12, pady=15)
Z = Entry(root)
Z.grid(row=2, column=0, columnspan=3, padx=12, pady=15)
def x():
global n
n = 1
def y():
global n
n = 2
def z():
global n
n = 3
def S(m):
if n == 1: #if n is 1
X.insert(END,str(m)) #then insert the clicked number to the end of the corresponding entry box
coordinates.append(X.get()) #append to the main list of all numbers
if n == 2:
Y.insert(END,str(m)) #doing same as above for y
coordinates.append(Y.get())
if n == 3:
Z.insert(END,str(m)) #doing same as above for z
coordinates.append(Z.get())
def clear():
#removing all the entry widget
X.delete(0,END)
Y.delete(0,END)
Z.delete(0,END)
#clearing all the lists
coordinates.clear()
xi.clear()
yi.clear()
zi.clear()
def equal():
xi.append(coordinates[len(X.get())-1]) #get the last entered value from the entire list of numbers for x
yi.append(coordinates[len(Y.get())+len(X.get())-1]) #get the last entered value from the entire list of numbers for y
zi.append(coordinates[len(Z.get())+len(X.get())+len(Y.get())-1]) #get the last entered value from the entire list of numbers for z
final_coordinates = xi+yi+zi #make a new final list that has the cordinates only
sq = 0
for d in final_coordinates:
e = float(d)
sq = sq + e**2
mag = sq**0.5
val.config(text=f"The magnitude of the vector is: {round(mag,3)}") #doing this to get rid of overwriting of labels
val.grid(row=3, column=0, columnspan=4, padx=12, pady=15)
b1 = Button(root, text="1", padx=30, pady=15, command=lambda: S(1))
b2 = Button(root, text="2", padx=30, pady=15, command=lambda: S(2))
b3 = Button(root, text="3", padx=30, pady=15, command=lambda: S(3))
b4 = Button(root, text="4", padx=30, pady=15, command=lambda: S(4))
b5 = Button(root, text="5", padx=30, pady=15, command=lambda: S(5))
b6 = Button(root, text="6", padx=30, pady=15, command=lambda: S(6))
b7 = Button(root, text="7", padx=30, pady=15, command=lambda: S(7))
b8 = Button(root, text="8", padx=30, pady=15, command=lambda: S(8))
b9 = Button(root, text="9", padx=30, pady=15, command=lambda: S(9))
b0 = Button(root, text="0", padx=30, pady=15, command=lambda: S(0))
bx = Button(root, text="x", padx=30, pady=15, command=x)
by = Button(root, text="y", padx=30, pady=15, command=y)
bz = Button(root, text="z", padx=30, pady=15, command=z)
bclear = Button(root, text="Clear", padx=19, pady=15, command=clear)
bequal = Button(root, text="=", padx=29, pady=15, command=equal)
b1.grid(row=6, column=0)
b2.grid(row=6, column=1)
b3.grid(row=6, column=2)
b4.grid(row=5, column=0)
b5.grid(row=5, column=1)
b6.grid(row=5, column=2)
b7.grid(row=4, column=0)
b8.grid(row=4, column=1)
b9.grid(row=4, column=2)
b0.grid(row=7, column=1)
bx.grid(row=8, column=0)
by.grid(row=8, column=1)
bz.grid(row=8, column=2)
bclear.grid(row=7, column=2)
bequal.grid(row=7, column=0)
val = Label(root) #declaring here, so that label can be configured later
root.mainloop()
Explanation:
Imagine, we entered 123
in the x box, 852
in the y box and 369
in the z box, so the final list, coordinates
, after appending all x, y, z is
['1', '12', '123', '8', '85', '852', '3', '36', '369']
So now the length of entry on x is 3, and that is our 3rd item on the list. Similarly, the length of the entry on y is 3, that is the 6th item on the list(which is length of x + length of y), same applies to z too. Now since we are indexing it, we will go 1 down(subtract 1) always, because indexing starts from 0, whereas our counting starts from 1.
Also, I removed the placeholders from inside the entry box as it can cause inefficiency, maybe just put a label on top of each entry, stating whats the purpose of the entry widget. Also I have used round(mag,3)
to round the digit upto 3 decimal values, since I gets awkward after that(for me), you could just get rid of it and have the entire numbers spit out.
Hope this gets the job done, but do let me know if any doubts.
Solution 2:
Here is a simple example of a vector calculator that gets rid of the number buttons, and:
- separates the vector calculations from the GUI. The
class Vector
is the "Model" that can be used with or without a GUI. - isolates the various components of the GUI in their own reusable classes: here one class for the entry fields, and one for the output.
You can use this skeletton as a base to add more operations, and polish the use to make it able to chain operations in a smoother manner.
import tkinter as tk
class Vector:
def __init__(self, x, y, z):
self.x = x
self.y = y
self.z = z
def __add__(self, other):
return Vector(self.x + other.x, self.y + other.y, self.z + other.z)
def dot(self, other):
return sum(s*o for s, o in zip(self, other))
def mag(self):
return self.dot(self)**.5
def __iter__(self):
for elt in self.x, self.y, self.z:
yield elt
def __str__(self):
return f'Vector({self.x}, {self.y}, {self.z})'
class VecEntry(tk.Frame):
def __init__(self, master):
self.master = master
super().__init__(master)
tk.Label(self, text='x coord').grid(column=0, row=0)
self.x_entry = tk.Entry(self)
self.x_entry.grid(column=1, row=0)
tk.Label(self, text='y coord').grid(column=0, row=1)
self.y_entry = tk.Entry(self)
self.y_entry.grid(column=1, row=1)
tk.Label(self, text='z coord').grid(column=0, row=2)
self.z_entry = tk.Entry(self)
self.z_entry.grid(column=1, row=2)
def get_coords(self):
x = float(self.x_entry.get())
y = float(self.y_entry.get())
z = float(self.z_entry.get())
return x, y, z
class VecOut(tk.Frame):
def __init__(self, master, vector):
self.master = master
super().__init__(master)
self.vector = vector
tk.Label(self, text='x coord').grid(column=0, row=0)
tk.Label(self, text=str(self.vector.x)).grid(column=1, row=0)
tk.Label(self, text='y coord').grid(column=0, row=1)
tk.Label(self, text=str(self.vector.y)).grid(column=1, row=1)
tk.Label(self, text='z coord').grid(column=0, row=2)
tk.Label(self, text=str(self.vector.z)).grid(column=1, row=2)
tk.Label(self, text='mag: ').grid(column=0, row=3)
tk.Label(self, text=str(self.vector.mag())).grid(column=1, row=3)
class VectorCalc(tk.Tk):
def __init__(self):
super().__init__()
self.vecentry_1 = VecEntry(self)
self.vecentry_1.pack(anchor=tk.NE)
self.vecentry_2 = VecEntry(self)
self.vecentry_2.pack(anchor=tk.NE)
self.add = tk.Button(self, text='+', command=self.add_vectors)
self.add.pack(side=tk.RIGHT)
self.vecout = None
def add_vectors(self):
v0 = Vector(*self.vecentry_1.get_coords())
v1 = Vector(*self.vecentry_2.get_coords())
result = v0 + v1
print(f'{v0} + {v1} = {result}')
print(f'the magnitude of the resultant vector is: {result.mag()}')
self.vecout = VecOut(self, result)
self.vecout.pack()
VectorCalc().mainloop()
Console Output:
Vector(4.0, 4.0, 4.0) + Vector(5.0, 5.0, 5.0) = Vector(9.0, 9.0, 9.0)
the magnitude of the resultant vector is: 15.588457268119896
Post a Comment for "Tkinter Application Returns Random Values"