Reputation: 83
I'm currently having multiple validation for different entry widget, and whilst all commands are set up the same way, only the validation for second entry work. Is there a reason why the other ones don't? Here's the part of my code dealing with entries:
import tkinter
from tkinter import *
import math
from tkinter import messagebox
class MyClass(tkinter.Frame):
def __init__(self, *args, **kwargs):
tkinter.Frame.__init__(self, *args, **kwargs)
#Setting up frame and widgets
vcmd1 = (self.register(self.__vcmd1), '%P', '%S')
vcmd2 = (self.register(self.__vcmd2), '%P')
vcmd3 = (self.register(self.__vcmd3), '%P', '%S')
self.v = IntVar()
self.v.set(1)
label_det = Label(self,text="Choose Detector")
self.mcp0 = Radiobutton(self, text="MCP-0",variable=self.v,value=1,command=self.selected)
self.mcp6 = Radiobutton(self, text="MCP-6",variable=self.v,value=2,command=self.selected)
self.mpet = Radiobutton(self,text="MCP-MPET",variable=self.v,value=3,command=self.selected)
label_det.grid(row=0, column=0, columnspan=2)
self.mcp0.grid(row=1,columnspan=2)
self.mcp6.grid(row=2,columnspan=2)
self.mpet.grid(row=3,columnspan=2)
label_iso = Label(self,text="Isotope A, Element (ex: 133,Cs)")
label_vol = Label(self, text="Beam Energy (eV)")
label_range = Label(self, text="Charge Range (ex:1,12)")
label_iso.grid(row=4, column=0, sticky=E)
label_vol.grid(row=5, column=0, sticky=E)
label_range.grid(row=6, column=0, sticky=E)
self.entry1 = tkinter.Entry(self, validate="key", validatecommand=vcmd1)
self.entry2 = tkinter.Entry(self, validate="key", validatecommand=vcmd2)
self.entry3 = tkinter.Entry(self, validate="key", validatecommand=vcmd3)
self.entry1.grid(row=4, column=1)
self.entry2.grid(row=5, column=1)
self.entry3.grid(row=6, column=1)
def __vcmd1(self, P, S):
validString = 'qwertyuiopasdfghjklzxcvbnmQWERTYUIOPASDFGHJKLZXCVBNM,1234567890'
if not S in validString:
messagebox.showinfo("Error", "Not valid")
return False
if "," in P:
messagebox.showinfo("Good", "Contain comma")
if len(P.split(",")) > 2:
messagebox.showinfo("Error", "Expected Form: ex. 133,Cs")
return False
else:
return True
def __vcmd2(self, P):
if P == '':
return True
try:
float(P)
return True
except ValueError:
messagebox.showinfo("Error", "Entry must be a float or integer")
return False
def __vcmd3(self, P, S):
if "," in P:
if len(P.split(",")) > 2:
messagebox.showinfo("Error", "Contain multiple commas")
return False
a = P.split(",")[0]
b = P.split(",")[1]
if a != '' and b != '':
try:
int(a)
int(b)
except ValueError:
messagebox.showinfo("Error", "Expected form: ex. 1,12")
return False
else:
return True
def selected(self):
if self.v.get() == 1:
self.x = 8.0
elif self.v.get() == 2:
self.x = 3.0
else:
self.x = 9.2
return self.x
class TimeGenerator:
def __init__(self,master):
self.frame = MyClass(master)
self.frame.grid(columnspan=2)
self.text = Text(root)
self.iso = self.frame.entry1
self.vol = self.frame.entry2
self.r = self.frame.entry3
button = Button(root, text='Time Range', command=self.calculateTime)
button.grid(row=3, columnspan=2)
def calculateTime(self):
self.text.delete(1.0, END)
dict = {'h': 1, 'he': 2, 'li': 3, 'be': 4, 'b': 5, 'c': 6, 'n': 7, 'o': 8, 'f': 9, 'ne': 10,
'na': 11, 'mg': 12, 'al': 13, 'si': 14, 'p': 15, 's': 16, 'cl': 17, 'ar': 18,
'k': 19, 'ca': 20, 'sc': 21, 'ti': 22, 'v': 23, 'cr': 24, 'mn': 25, 'fe': 26, 'co': 27, 'ni': 28,
'cu': 29, 'zn': 30,
'ga': 31, 'ge': 31, 'as': 33, 'se': 34, 'br': 35, 'kr': 36, 'rb': 37, 'sr': 38, 'y': 39,
'zr': 40, 'nb': 41, 'mo': 42, 'tc': 43, 'ru': 44, 'rh': 45, 'pd': 46, 'ag': 47, 'cd': 48,
'in': 49, 'sn': 50, 'sb': 51, 'te': 52, 'i': 53, 'xe': 54, 'cs': 55, 'ba': 56,
'la': 57, 'ce': 58, 'pr': 59, 'nd': 60, 'pm': 61, 'sm': 62, 'eu': 63, 'gd': 64, 'tb': 65, 'dy': 66,
'ho': 67, 'er': 68, 'tm': 69, 'yb': 70, 'lu': 71,
'hf': 72, 'ta': 73, 'w': 74, 're': 75, 'os': 76, 'ir': 77, 'pt': 78, 'au': 79, 'hg': 80, 'tl': 81,
'pb': 82, 'bi': 83, 'po': 84, 'at': 85, 'rn': 86,
'fr': 87, 'ra': 88, 'ac': 89, 'th': 90, 'pa': 91, 'u': 92, 'np': 93, 'pu': 94, 'am': 95, 'cm': 96,
'bk': 97, 'cf': 98, 'es': 99, 'fm': 100, 'md': 101, 'no': 102, 'lr': 103,
'rf': 104, 'db': 105, 'sg': 106, 'bh': 107, 'hs': 108, 'mt': 109, 'ds': 110, 'rg': 111, 'cn': 112,
'uut': 113, 'fl': 114, 'uup': 115, 'lv': 116, 'uus': 117, 'uuo': 118}
if self.r.get() == "" or self.iso.get() == "" or self.vol.get() == "":
messagebox.showinfo("Error", "No field can be empty")
return None
r = self.r.get().replace(" ", "")
tup = tuple(int(x) for x in r.split(","))
iso = self.iso.get().replace(" ", "")
list = []
for e in iso.split(","):
list.append(e)
if (dict[list[1].lower()] < tup[0]) or (dict[list[1].lower()] < tup[1]):
messagebox.showinfo("Error", "Change state range does not exist for given element")
return None
f = open("/Users/LazyLinh/PycharmProjects/TimeGenGUI/mass.mas12.txt", "r")
i = 0
while (i < 40):
header = f.readline()
i += 1
self.mass = 0
#iterate through text file
for line in f:
line = line.strip()
columns = line.split()
if (list[0] == columns[3]):
if (list[1].lower() == columns[4].lower()):
if (len(columns) == 16):
self.mass = float(columns[13].replace("#","")) + float(columns[14].replace("#",""))/10e6
else:
self.mass = float(columns[12].replace("#","")) + float(columns[13].replace("#",""))/10e6
#Calculation
list = []
for q in range(tup[0], tup[1] + 1):
y = (self.frame.selected() * math.sqrt(self.mass * 1.6605402e-27 / (2 * q *1.6022e-19 * float(self.vol.get())))) * 10e6
list.append(y)
i = tup[0]
#inserting to text widget
for time in list:
self.text.insert("end", "%d: %s\n" % (i, time))
i = i + 1
self.text.grid()
self.iso = self.frame.entry1
self.vol = self.frame.entry2
self.r = self.frame.entry3
root = Tk()
b = TimeGenerator(root)
root.mainloop()
observed errors include being able to add characters not from validString for entry 1, or being able to add multiple ',' for entry 3...
EDIT: I have included my full code and what I tried
Upvotes: 1
Views: 102
Reputation: 385880
The code is technically working, though you have logic errors that perhaps are preventing it from working like you expect.
For the validation function to work, it must return either True
or False
. Any other valid will disable the validation. In your commands there are paths through the code that do not return True
or False
, causing the validation to be turned off.
For example, in _vcmd
1, if P
contains a comma but the expression len(P.split(",")) > 2
is False
, you end up returning None
which will cancel any future validation.
Similarly, in _vcmd3
you have a path through the code that returns None
. Ask yourself what happens when you enter "4,". The function returns None
which, again, cancels future validation.
Bottom line: your functions must always return either True
or False
, or validation will be turned off.
Upvotes: 1