Spaces:
No application file
No application file
| import tkinter as tk | |
| from tkinter import messagebox, ttk | |
| class BoundedNumericalEntry(tk.Entry): | |
| def __init__(self, master=None, min_value=None, max_value=None, variable=None, | |
| vartype=float, width=7, allow_inf=False, **kwargs): | |
| if variable is None: | |
| if vartype == float: | |
| self.var = tk.DoubleVar() | |
| elif vartype == int: | |
| self.var = tk.IntVar() | |
| else: | |
| self.var = tk.StringVar() | |
| else: | |
| self.var = variable | |
| self.fake_var = tk.StringVar(value=self.var.get()) | |
| self.vartype = vartype | |
| self.old_value = self.var.get() | |
| self.allow_inf = allow_inf | |
| self.min_value, self.max_value = min_value, max_value | |
| self.get, self.set = self.fake_var.get, self.fake_var.set | |
| self.validate_command = master.register(self._check_bounds) | |
| tk.Entry.__init__(self, master, textvariable=self.fake_var, validate="focus", width=width, | |
| vcmd=(self.validate_command, '%P', '%d'), **kwargs) | |
| def _check_bounds(self, instr, action_type): | |
| if self.allow_inf and instr == 'INF': | |
| self.fake_var.set('INF') | |
| return True | |
| if action_type == '-1': | |
| try: | |
| new_value = self.vartype(instr) | |
| except ValueError: | |
| pass | |
| else: | |
| if (self.min_value is None or new_value >= self.min_value) and \ | |
| (self.max_value is None or new_value <= self.max_value): | |
| if new_value != self.old_value: | |
| self.old_value = self.vartype(self.fake_var.get()) | |
| self.delete(0, tk.END) | |
| self.insert(0, str(self.old_value)) | |
| self.var.set(self.old_value) | |
| return True | |
| self.delete(0, tk.END) | |
| self.insert(0, str(self.old_value)) | |
| mn = '-inf' if self.min_value is None else str(self.min_value) | |
| mx = '+inf' if self.max_value is None else str(self.max_value) | |
| messagebox.showwarning("Incorrect value in input field", f"Value for {self._name} should be in " | |
| f"[{mn}; {mx}] and of type {self.vartype.__name__}") | |
| return False | |
| class FocusHorizontalScale(tk.Scale): | |
| def __init__(self, *args, highlightthickness=0, sliderrelief=tk.GROOVE, resolution=0.01, | |
| sliderlength=20, length=200, **kwargs): | |
| tk.Scale.__init__(self, *args, orient=tk.HORIZONTAL, highlightthickness=highlightthickness, | |
| sliderrelief=sliderrelief, resolution=resolution, | |
| sliderlength=sliderlength, length=length, **kwargs) | |
| self.bind("<1>", lambda event: self.focus_set()) | |
| class FocusCheckButton(tk.Checkbutton): | |
| def __init__(self, *args, highlightthickness=0, **kwargs): | |
| tk.Checkbutton.__init__(self, *args, highlightthickness=highlightthickness, **kwargs) | |
| self.bind("<1>", lambda event: self.focus_set()) | |
| class FocusButton(tk.Button): | |
| def __init__(self, *args, highlightthickness=0, **kwargs): | |
| tk.Button.__init__(self, *args, highlightthickness=highlightthickness, **kwargs) | |
| self.bind("<1>", lambda event: self.focus_set()) | |
| class FocusLabelFrame(ttk.LabelFrame): | |
| def __init__(self, *args, highlightthickness=0, relief=tk.RIDGE, borderwidth=2, **kwargs): | |
| tk.LabelFrame.__init__(self, *args, highlightthickness=highlightthickness, relief=relief, | |
| borderwidth=borderwidth, **kwargs) | |
| self.bind("<1>", lambda event: self.focus_set()) | |
| def set_frame_state(self, state): | |
| def set_widget_state(widget, state): | |
| if widget.winfo_children is not None: | |
| for w in widget.winfo_children(): | |
| w.configure(state=state) | |
| set_widget_state(self, state) | |