start working on scrollable frame

This commit is contained in:
Tom Schimansky 2023-02-04 16:53:48 +01:00
parent 9e2584c958
commit a478334fb7
6 changed files with 108 additions and 6 deletions

View File

@ -33,6 +33,7 @@ from .windows.widgets import CTkSlider
from .windows.widgets import CTkSwitch from .windows.widgets import CTkSwitch
from .windows.widgets import CTkTabview from .windows.widgets import CTkTabview
from .windows.widgets import CTkTextbox from .windows.widgets import CTkTextbox
from .windows.widgets import CTkScrollableFrame
# import windows # import windows
from .windows import CTk from .windows import CTk

View File

@ -13,3 +13,4 @@ from .ctk_slider import CTkSlider
from .ctk_switch import CTkSwitch from .ctk_switch import CTkSwitch
from .ctk_tabview import CTkTabview from .ctk_tabview import CTkTabview
from .ctk_textbox import CTkTextbox from .ctk_textbox import CTkTextbox
from .ctk_scrollable_frame import CTkScrollableFrame

View File

@ -179,8 +179,7 @@ class CTkBaseClass(tkinter.Frame, CTkAppearanceModeBaseClass, CTkScalingBaseClas
elif isinstance(image, CTkImage): elif isinstance(image, CTkImage):
return image return image
else: else:
warnings.warn(f"{type(self).__name__} Warning: Given image is not CTkImage but {type(image)}. " + warnings.warn(f"{type(self).__name__} Warning: Given image is not CTkImage but {type(image)}. Image can not be scaled on HighDPI displays, use CTkImage instead.\n")
f"Image can not be scaled on HighDPI displays, use CTkImage instead.\n")
return image return image
def _update_dimensions_event(self, event): def _update_dimensions_event(self, event):

View File

@ -40,7 +40,7 @@ class CTkButton(CTkBaseClass):
text: str = "CTkButton", text: str = "CTkButton",
font: Optional[Union[tuple, CTkFont]] = None, font: Optional[Union[tuple, CTkFont]] = None,
textvariable: Union[tkinter.Variable, None] = None, textvariable: Union[tkinter.Variable, None] = None,
image: Union[CTkImage, None] = None, image: Union[CTkImage, "ImageTk.PhotoImage", None] = None,
state: str = "normal", state: str = "normal",
hover: bool = True, hover: bool = True,
command: Union[Callable[[], None], None] = None, command: Union[Callable[[], None], None] = None,
@ -169,8 +169,11 @@ class CTkButton(CTkBaseClass):
def _update_image(self): def _update_image(self):
if self._image_label is not None: if self._image_label is not None:
if isinstance(self._image, CTkImage):
self._image_label.configure(image=self._image.create_scaled_photo_image(self._get_widget_scaling(), self._image_label.configure(image=self._image.create_scaled_photo_image(self._get_widget_scaling(),
self._get_appearance_mode())) self._get_appearance_mode()))
elif self._image is not None:
self._image_label.configure(image=self._image)
def destroy(self): def destroy(self):
if isinstance(self._font, CTkFont): if isinstance(self._font, CTkFont):

View File

@ -24,8 +24,8 @@ class CTkFrame(CTkBaseClass):
bg_color: Union[str, Tuple[str, str]] = "transparent", bg_color: Union[str, Tuple[str, str]] = "transparent",
fg_color: Optional[Union[str, Tuple[str, str]]] = None, fg_color: Optional[Union[str, Tuple[str, str]]] = None,
border_color: Optional[Union[str, Tuple[str, str]]] = None, border_color: Optional[Union[str, Tuple[str, str]]] = None,
background_corner_colors: Union[Tuple[Union[str, Tuple[str, str]]], None] = None,
background_corner_colors: Union[Tuple[Union[str, Tuple[str, str]]], None] = None,
overwrite_preferred_drawing_method: Union[str, None] = None, overwrite_preferred_drawing_method: Union[str, None] = None,
**kwargs): **kwargs):

View File

@ -0,0 +1,98 @@
from typing import Union, Tuple, List, Optional
import tkinter
from .ctk_frame import CTkFrame
from .ctk_scrollbar import CTkScrollbar
class CTkScrollableFrame(tkinter.Frame):
_xscrollincrement = 4 # horizontal scrolling speed
_yscrollincrement = 8 # vertical scrolling speed
def __init__(self,
master: any,
width: int = 200,
height: int = 200,
corner_radius: Optional[Union[int, str]] = None,
border_width: Optional[Union[int, str]] = None,
bg_color: Union[str, Tuple[str, str]] = "transparent",
fg_color: Optional[Union[str, Tuple[str, str]]] = None,
border_color: Optional[Union[str, Tuple[str, str]]] = None,
activate_x_scrollbars: bool = False,
activate_y_scrollbars: bool = True):
self._activate_x_scrollbars = activate_x_scrollbars
self._activate_y_scrollbars = activate_y_scrollbars
self.parent_frame = CTkFrame(master=master, width=width, height=height, corner_radius=corner_radius, border_width=border_width)
self.parent_canvas = tkinter.Canvas(master=self.parent_frame, yscrollincrement=self._yscrollincrement, xscrollincrement=self._xscrollincrement)
if self._activate_x_scrollbars:
self.x_scrollbar = CTkScrollbar(master=self.parent_frame, orientation="horizontal", command=self.parent_canvas.xview)
self.parent_canvas.configure(xscrollcommand=self.x_scrollbar.set)
if self._activate_y_scrollbars:
self.y_scrollbar = CTkScrollbar(master=self.parent_frame, orientation="vertical", command=self.parent_canvas.yview)
self.parent_canvas.configure(yscrollcommand=self.y_scrollbar.set)
self._create_grid()
super().__init__(master=self.parent_canvas, width=0)
self.bind("<Configure>", lambda e: self.parent_canvas.configure(scrollregion=self.parent_canvas.bbox("all")))
self.bind_all("<MouseWheel>", self._mouse_wheel_all)
self.bind_all("<KeyPress-Shift_L>", self._keyboard_shift_press_all)
self.bind_all("<KeyPress-Shift_R>", self._keyboard_shift_press_all)
self.bind_all("<KeyRelease-Shift_L>", self._keyboard_shift_release_all)
self.bind_all("<KeyRelease-Shift_R>", self._keyboard_shift_release_all)
self.parent_canvas.bind("<Configure>", self._parent_canvas_configure)
self._create_window_id = self.parent_canvas.create_window(0, 0, window=self, anchor="nw")
self._shift_pressed = False
self.mouse_over_widget = False
def _create_grid(self):
self.parent_frame.grid_columnconfigure(0, weight=1)
self.parent_frame.grid_rowconfigure(0, weight=1)
self.parent_canvas.grid(row=0, column=0, sticky="nsew")
if self._activate_x_scrollbars:
self.parent_frame.grid_rowconfigure(1, weight=0)
self.x_scrollbar.grid(row=1, column=0, sticky="nsew")
if self._activate_y_scrollbars:
self.parent_frame.grid_columnconfigure(1, weight=0)
self.y_scrollbar.grid(row=0, column=1, sticky="nsew")
def _parent_canvas_configure(self, event):
#self.parent_canvas.itemconfigure(self._create_window_id, width=event.width, height=event.height)
pass
def _mouse_wheel_all(self, event):
if self.check_if_master_is_canvas(event.widget):
if self._shift_pressed:
self.parent_canvas.xview("scroll", -event.delta, "units")
else:
self.parent_canvas.yview("scroll", -event.delta, "units")
def _keyboard_shift_press_all(self, event):
self._shift_pressed = True
def _keyboard_shift_release_all(self, event):
self._shift_pressed = False
def check_if_master_is_canvas(self, widget):
if widget == self.parent_canvas:
return True
elif widget.master is not None:
return self.check_if_master_is_canvas(widget.master)
else:
return False
def pack(self, **kwargs):
self.parent_frame.pack(**kwargs)
def place(self, **kwargs):
self.parent_frame.place(**kwargs)
def grid(self, **kwargs):
self.parent_frame.grid(**kwargs)