I made a GUI in tkinter and I want the checkbox (there are actually several, the figure is just an example) next to velocity to deactivate both the second value of velocity and the number of steps. To do that I have defined two different methods int he class, double_entry
and single_entry
. The problem I am facing is it seems I cannot call the attribute entry_c
from outside the method single_entry
. When I click on any checkbox I got the following error:
self.entry_c.configure(state='normal')
AttributeError: 'CreateEntry' object has no attribute 'entry_c'
here is how I call the class from the main (importing the file modules as md
:
import modules as md
import tkinter as tk
if __name__ == '__main__':
root = tk.Tk()
dictionary = md.create_input_dictionary()
for index, (key, values) in enumerate(dictionary.items()):
obj = md.CreateEntry(root, values, index)
if md.arenumbers(values[-2]) and md.arenumbers(values[-1]):
obj.double_entry()
elif not md.arenumbers(values[-2]) and md.arenumbers(values[-1]):
obj.single_entry()
else:
pass
root.mainloop()
and here is the class:
import tkinter as tk
def create_input_dictionary():
out = {'Header geometry': ['GEOMETRY DATA', 'Min', 'Max'],
'k1': ['unit_1', 'mm', '25', '25'],
'k2': ['unit_2', 'mm', '19', '19'],
'k3': ['unit_3', '0']
}
return out
def arefloats(*numbers):
try:
return all(arefloats(*n) if isinstance(n, list) else [float(n)]
for n in numbers)
except (ValueError, TypeError):
return False
def areintegers(*numbers):
try:
return all(areintegers(*n) if isinstance(n, list) else [int(n)]
for n in numbers)
except (ValueError, TypeError):
return False
def arenumbers(*numbers):
return areintegers(*numbers) or arefloats(*numbers)
class CreateEntry(tk.Frame):
def __init__(self, parent, values, row, bg=None, **kwargs):
if bg is None:
bg = parent['bg']
super().__init__(parent, bg=bg, **kwargs)
self.parent = parent
self.values = values
self.row = row
def double_entry(self):
self.nac = tk.IntVar(self.parent)
self.variable1 = tk.StringVar(self.parent, value=self.values[-2])
self.variable2 = tk.StringVar(self.parent, value=self.values[-1])
tk.Checkbutton(self.parent, variable=self.nac, command=lambda: self.naccheck()). \
grid(row=self.row, column=0, sticky='ns')
label = self.values[0] + ' (' + self.values[1] + ') '
tk.Label(self.parent, text=label, padx=10, pady=5). \
grid(row=self.row, column=1, sticky='nw')
self.entry_c1 = tk.Entry(self.parent, textvariable=self.variable1, width=10, state='normal')
self.entry_c1.grid(row=self.row, column=2)
self.entry_c2 = tk.Entry(self.parent, textvariable=self.variable2, width=10, state='disabled')
self.entry_c2.grid(row=self.row, column=3)
self.entry_c1.bind("<KeyRelease>", self._accept)
self.entry_c2.bind("<KeyRelease>", self._accept)
def single_entry(self):
variable = tk.StringVar(self.parent, value=self.values[-1])
self.variable = variable
entry_c = tk.Entry(self.parent, textvariable=self.variable, width=10, state='disabled')
self.entry_c = entry_c
self.entry_c.grid(row=self.row + 1, column=2, columnspan=2)
self.entry_c.bind("<KeyRelease>", self._accept)
tk.Label(self.parent, text='SIMULATION PARAMETERS', padx=10, pady=5).grid(row=self.row, columnspan=4,
sticky='ns')
tk.Label(self.parent, text=self.values[0], padx=10, pady=5).grid(row=self.row + 1, column=0, columnspan=2,
sticky='ns')
def labels_entry(self):
tk.Label(self.parent, text=self.values[0], padx=10, pady=5).grid(row=self.row, column=1, sticky='ns')
tk.Label(self.parent, text=self.values[1], padx=10, pady=5).grid(row=self.row, column=2, sticky='ns')
tk.Label(self.parent, text=self.values[2], padx=10, pady=5).grid(row=self.row, column=3, sticky='ns')
def naccheck(self):
if self.nac.get() == 0:
self.variable2.set(self.variable1.get())
self.entry_c2.configure(state='disabled')
self.variable.set('0')
self.entry_c.configure(state='disabled')
else:
self.entry_c2.configure(state='normal')
self.entry_c.configure(state='normal')
def _accept(self, event):
"""Accept value change when a key is released"""
if self.nac.get() == 0:
self.values[-1] = self.entry_c1.get()
else:
self.values[-1] = self.entry_c2.get()