mirror of
https://github.com/TomSchimansky/CustomTkinter.git
synced 2023-08-10 21:13:13 +03:00
[feat] Event Generation on Canvas
For widgets based on the _canvas, attempting to use event_generate for custom events failed. Typical notation in tkinter would allow such bindings but in customtkinter, operations are performed on hidden widgets. Thus a function override is required to operate as expected. Widgets that are not based on _canvas or where a combination of hidden widgets were not updated. Signed off by Trask Crane (hcrane3@gatech.edu)
This commit is contained in:
@@ -107,13 +107,13 @@ class CTk(tkinter.Tk, CTkAppearanceModeBaseClass, CTkScalingBaseClass):
|
|||||||
def _set_scaling(self, new_widget_scaling, new_window_scaling):
|
def _set_scaling(self, new_widget_scaling, new_window_scaling):
|
||||||
super()._set_scaling(new_widget_scaling, new_window_scaling)
|
super()._set_scaling(new_widget_scaling, new_window_scaling)
|
||||||
|
|
||||||
# Force new dimensions on window by using min, max, and geometry. Without min, max it won't work.
|
# Force new dimensions on window by using abs_min, max, and geometry. Without abs_min, max it won't work.
|
||||||
super().minsize(self._apply_window_scaling(self._current_width), self._apply_window_scaling(self._current_height))
|
super().minsize(self._apply_window_scaling(self._current_width), self._apply_window_scaling(self._current_height))
|
||||||
super().maxsize(self._apply_window_scaling(self._current_width), self._apply_window_scaling(self._current_height))
|
super().maxsize(self._apply_window_scaling(self._current_width), self._apply_window_scaling(self._current_height))
|
||||||
|
|
||||||
super().geometry(f"{self._apply_window_scaling(self._current_width)}x{self._apply_window_scaling(self._current_height)}")
|
super().geometry(f"{self._apply_window_scaling(self._current_width)}x{self._apply_window_scaling(self._current_height)}")
|
||||||
|
|
||||||
# set new scaled min and max with delay (delay prevents weird bug where window dimensions snap to unscaled dimensions when mouse releases window)
|
# set new scaled abs_min and max with delay (delay prevents weird bug where window dimensions snap to unscaled dimensions when mouse releases window)
|
||||||
self.after(1000, self._set_scaled_min_max) # Why 1000ms delay? Experience! (Everything tested on Windows 11)
|
self.after(1000, self._set_scaled_min_max) # Why 1000ms delay? Experience! (Everything tested on Windows 11)
|
||||||
|
|
||||||
def block_update_dimensions_event(self):
|
def block_update_dimensions_event(self):
|
||||||
@@ -196,7 +196,7 @@ class CTk(tkinter.Tk, CTkAppearanceModeBaseClass, CTkScalingBaseClass):
|
|||||||
# update width and height attributes
|
# update width and height attributes
|
||||||
width, height, x, y = self._parse_geometry_string(geometry_string)
|
width, height, x, y = self._parse_geometry_string(geometry_string)
|
||||||
if width is not None and height is not None:
|
if width is not None and height is not None:
|
||||||
self._current_width = max(self._min_width, min(width, self._max_width)) # bound value between min and max
|
self._current_width = max(self._min_width, min(width, self._max_width)) # bound value between abs_min and max
|
||||||
self._current_height = max(self._min_height, min(height, self._max_height))
|
self._current_height = max(self._min_height, min(height, self._max_height))
|
||||||
else:
|
else:
|
||||||
return self._reverse_geometry_scaling(super().geometry())
|
return self._reverse_geometry_scaling(super().geometry())
|
||||||
|
|||||||
@@ -109,13 +109,13 @@ class CTkToplevel(tkinter.Toplevel, CTkAppearanceModeBaseClass, CTkScalingBaseCl
|
|||||||
def _set_scaling(self, new_widget_scaling, new_window_scaling):
|
def _set_scaling(self, new_widget_scaling, new_window_scaling):
|
||||||
super()._set_scaling(new_widget_scaling, new_window_scaling)
|
super()._set_scaling(new_widget_scaling, new_window_scaling)
|
||||||
|
|
||||||
# Force new dimensions on window by using min, max, and geometry. Without min, max it won't work.
|
# Force new dimensions on window by using abs_min, max, and geometry. Without abs_min, max it won't work.
|
||||||
super().minsize(self._apply_window_scaling(self._current_width), self._apply_window_scaling(self._current_height))
|
super().minsize(self._apply_window_scaling(self._current_width), self._apply_window_scaling(self._current_height))
|
||||||
super().maxsize(self._apply_window_scaling(self._current_width), self._apply_window_scaling(self._current_height))
|
super().maxsize(self._apply_window_scaling(self._current_width), self._apply_window_scaling(self._current_height))
|
||||||
|
|
||||||
super().geometry(f"{self._apply_window_scaling(self._current_width)}x{self._apply_window_scaling(self._current_height)}")
|
super().geometry(f"{self._apply_window_scaling(self._current_width)}x{self._apply_window_scaling(self._current_height)}")
|
||||||
|
|
||||||
# set new scaled min and max with delay (delay prevents weird bug where window dimensions snap to unscaled dimensions when mouse releases window)
|
# set new scaled abs_min and max with delay (delay prevents weird bug where window dimensions snap to unscaled dimensions when mouse releases window)
|
||||||
self.after(1000, self._set_scaled_min_max) # Why 1000ms delay? Experience! (Everything tested on Windows 11)
|
self.after(1000, self._set_scaled_min_max) # Why 1000ms delay? Experience! (Everything tested on Windows 11)
|
||||||
|
|
||||||
def block_update_dimensions_event(self):
|
def block_update_dimensions_event(self):
|
||||||
@@ -137,7 +137,7 @@ class CTkToplevel(tkinter.Toplevel, CTkAppearanceModeBaseClass, CTkScalingBaseCl
|
|||||||
# update width and height attributes
|
# update width and height attributes
|
||||||
width, height, x, y = self._parse_geometry_string(geometry_string)
|
width, height, x, y = self._parse_geometry_string(geometry_string)
|
||||||
if width is not None and height is not None:
|
if width is not None and height is not None:
|
||||||
self._current_width = max(self._min_width, min(width, self._max_width)) # bound value between min and max
|
self._current_width = max(self._min_width, min(width, self._max_width)) # bound value between abs_min and max
|
||||||
self._current_height = max(self._min_height, min(height, self._max_height))
|
self._current_height = max(self._min_height, min(height, self._max_height))
|
||||||
else:
|
else:
|
||||||
return self._reverse_geometry_scaling(super().geometry())
|
return self._reverse_geometry_scaling(super().geometry())
|
||||||
|
|||||||
@@ -194,3 +194,7 @@ class CTkFrame(CTkBaseClass):
|
|||||||
raise ValueError("'funcid' argument can only be None, because there is a bug in" +
|
raise ValueError("'funcid' argument can only be None, because there is a bug in" +
|
||||||
" tkinter and its not clear whether the internal callbacks will be unbinded or not")
|
" tkinter and its not clear whether the internal callbacks will be unbinded or not")
|
||||||
self._canvas.unbind(sequence, None)
|
self._canvas.unbind(sequence, None)
|
||||||
|
|
||||||
|
def event_generate(self, sequence, **kw):
|
||||||
|
""" called on the tkinter.Canvas """
|
||||||
|
self._canvas.event_generate(sequence, **kw)
|
||||||
|
|||||||
@@ -281,6 +281,10 @@ class CTkLabel(CTkBaseClass):
|
|||||||
self._canvas.unbind(sequence, None)
|
self._canvas.unbind(sequence, None)
|
||||||
self._label.unbind(sequence, None)
|
self._label.unbind(sequence, None)
|
||||||
|
|
||||||
|
def event_generate(self, sequence, **kw):
|
||||||
|
""" called on the tkinter.Canvas """
|
||||||
|
self._canvas.event_generate(sequence, **kw)
|
||||||
|
|
||||||
def focus(self):
|
def focus(self):
|
||||||
return self._label.focus()
|
return self._label.focus()
|
||||||
|
|
||||||
|
|||||||
@@ -302,6 +302,10 @@ class CTkProgressBar(CTkBaseClass):
|
|||||||
" tkinter and its not clear whether the internal callbacks will be unbinded or not")
|
" tkinter and its not clear whether the internal callbacks will be unbinded or not")
|
||||||
self._canvas.unbind(sequence, None)
|
self._canvas.unbind(sequence, None)
|
||||||
|
|
||||||
|
def event_generate(self, sequence, **kw):
|
||||||
|
""" called on the tkinter.Canvas """
|
||||||
|
self._canvas.event_generate(sequence, **kw)
|
||||||
|
|
||||||
def focus(self):
|
def focus(self):
|
||||||
return self._canvas.focus()
|
return self._canvas.focus()
|
||||||
|
|
||||||
|
|||||||
@@ -271,6 +271,10 @@ class CTkScrollbar(CTkBaseClass):
|
|||||||
self._canvas.unbind(sequence, None) # unbind all callbacks for sequence
|
self._canvas.unbind(sequence, None) # unbind all callbacks for sequence
|
||||||
self._create_bindings(sequence=sequence) # restore internal callbacks for sequence
|
self._create_bindings(sequence=sequence) # restore internal callbacks for sequence
|
||||||
|
|
||||||
|
def event_generate(self, sequence, **kw):
|
||||||
|
""" called on the tkinter.Canvas """
|
||||||
|
self._canvas.event_generate(sequence, **kw)
|
||||||
|
|
||||||
def focus(self):
|
def focus(self):
|
||||||
return self._canvas.focus()
|
return self._canvas.focus()
|
||||||
|
|
||||||
|
|||||||
@@ -387,6 +387,10 @@ class CTkSlider(CTkBaseClass):
|
|||||||
self._canvas.unbind(sequence, None)
|
self._canvas.unbind(sequence, None)
|
||||||
self._create_bindings(sequence=sequence) # restore internal callbacks for sequence
|
self._create_bindings(sequence=sequence) # restore internal callbacks for sequence
|
||||||
|
|
||||||
|
def event_generate(self, sequence, **kw):
|
||||||
|
""" called on the tkinter.Canvas """
|
||||||
|
self._canvas.event_generate(sequence, **kw)
|
||||||
|
|
||||||
def focus(self):
|
def focus(self):
|
||||||
return self._canvas.focus()
|
return self._canvas.focus()
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user