Tkinter-based GUI that is supposed to update the dictionary values. It works fine, there are still two issues:
- in order to update the entry value I used the
bind
method, i.e.object.bind("<Key>", self._accept)
, it works only with the Enter key, with the other keys it prints the previous value inserted in the entry [SOLVED] - I can't figure out how to set
entry_c2=entry_c1
when the corresponding checkbox is deactivated.
import tkinter as tk
def create_input_dictionary():
out = {'Header': ['LLL', 'Min', 'Max'],
'Do': ['l1', 'mm', '25', '35'],
'Di': ['l2', 'mm', '19', '29'],
'tt': ['l3', 'mm', '0.8', '1.2'],
'y': ['l4', '-', '2', '3'],
'eps': ['l5', 'mm', '0.1', '0.2'],
'Header': ['LLL', 'Min', 'Max'],
'P': ['l6', 'MPa', '3', '5'],
'T': ['l7', '°C', '30', '50'],
'V': ['l8', 'm/s', '3', '5'],
'nos': ['l10', '10']
}
return out
def isfloat(value):
"""The function checks if an element is a number"""
try:
float(value)
return True
except ValueError:
return False
def isinteger(value):
"""The function checks if an element is a number"""
try:
int(value)
return True
except ValueError:
return False
def isnumber(value):
return isfloat(value) or isinteger(value)
def allarefloats(var_list):
"""The function checks if all the elements in the lists are numbers"""
check = True
for item in var_list:
check = check and isfloat(item)
return check
def allareinteger(var_list):
"""The function checks if all the elements in the lists are numbers"""
check = True
for item in var_list:
check = check and isinteger(item)
return check
def areallnumbers(var_list):
check = True
for item in var_list:
check = check and (isfloat(item) or isinteger(item))
return check
class DictionaryEntry(tk.Frame):
"""get entry and update dictionary values"""
def __init__(self, parent, key_dict, values_dict, row_entry, bg=None, **kwargs):
if bg is None:
bg = parent['bg']
super().__init__(parent, bg=bg, **kwargs)
self.row = row_entry
self.key = key_dict
self.values = values_dict
self.nac = tk.IntVar()
self.entry_c1 = None
self.entry_c2 = None
if isnumber(self.values[-1]):
if isnumber(self.values[-2]):
self.variable = tk.StringVar(value=self.values[-2]), tk.StringVar(self, self.values[-1])
tk.Checkbutton(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(parent, text=label, padx=10, pady=5).grid(row=self.row, column=1, sticky='nw')
self.entry_c1 = tk.Entry(parent, textvariable=self.variable[0], width=10, state='normal')
self.entry_c1.grid(row=self.row, column=2)
self.entry_c2 = tk.Entry(parent, textvariable=self.variable[1], width=10, state='disabled')
self.entry_c2.grid(row=self.row, column=3)
else:
self.variable = tk.StringVar(self, value=self.values[-1])
tk.Label(parent, text='SIMULATION PARAMETERS', padx=10, pady=5).grid(row=self.row, columnspan=4,
sticky='ns')
tk.Label(parent, text=self.values[0], padx=10, pady=5).grid(row=self.row 1, columnspan=2, sticky='ns')
self.variable = tk.StringVar(self, self.values[-1])
self.entry_c1 = tk.Entry(parent, textvariable=self.variable, width=10, state='normal')
self.entry_c1.grid(row=self.row 1, column=2, columnspan=2)
self.entry_c1.bind("<Key>", self._accept)
if self.entry_c2 is not None:
self.entry_c2.bind("<Key>", self._accept)
else:
tk.Label(parent, text=self.values[0], padx=10, pady=5).grid(row=self.row, column=1, sticky='ns')
tk.Label(parent, text=self.values[1], padx=10, pady=5).grid(row=self.row, column=2, sticky='ns')
tk.Label(parent, text=self.values[2], padx=10, pady=5).grid(row=self.row, column=3, sticky='ns')
print(self.entry_c1, self.entry_c2)
def naccheck(self):
if self.nac.get() == 0:
self.entry_c2.configure(state='disabled')
else:
self.entry_c2.configure(state='normal')
def _accept(self, event): # finire!! update dictionary
"""Accept value change when return is pressed or losing focus"""
try:
if self.entry_c1 is not None:
self.values[-2] = self.entry_c1.get()
if self.entry_c2 is not None:
self.values[-1] = self.entry_c2.get()
except ValueError:
pass
if __name__ == '__main__':
dictionary = create_input_dictionary()
root = tk.Tk()
radio_button_frame = tk.Frame(root, padx=10, pady=5)
input_data_frame = tk.Frame(root, padx=10, pady=5)
simul_button_frame = tk.Frame(root, padx=10, pady=5)
# place the container within the main window using grid
radio_button_frame.grid(row=0, column=0, sticky='ns')
input_data_frame.grid(row=1, column=0, sticky='ns')
simul_button_frame.grid(row=2, column=0, sticky='ns')
row = 0
for key, values in dictionary.items():
obj = DictionaryEntry(input_data_frame, key, values, row)
dictionary.update({key: obj.values})
row = 1
tk.Button(simul_button_frame, text="click me", command=lambda: print(dictionary)).pack(padx=10, pady=5)
root.update()
root.mainloop()
EDIT: First point marked as fixed
CodePudding user response:
For item 1, just bind <KeyRelease>
instead of <Key>
.
For item 2, just copy the content from entry_c1
to entry_c2
before disabling entry_c2
inside naccheck()
:
def naccheck(self):
if self.nac.get() == 0:
# copy value from entry_c1 to entry_c2
value = self.variable[0].get()
self.variable[1].set(value)
# update self.values[-1] as well
self.values[-1] = value
# then disable entry_c2
self.entry_c2.configure(state='disabled')
else:
self.entry_c2.configure(state='normal')