mirror of
https://github.com/TomSchimansky/CustomTkinter.git
synced 2023-08-10 21:13:13 +03:00
added CTkImage, compound support for label
This commit is contained in:
parent
7374e7a3bc
commit
62b330ddba
@ -6,8 +6,6 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
|
||||
|
||||
ToDo:
|
||||
- complete other theme files
|
||||
- auto-scaling of images
|
||||
- image tuple for light/dark mode
|
||||
- change font attribute in wiki
|
||||
- add new button attributes to wiki
|
||||
- cursor configuring
|
||||
|
@ -6,6 +6,7 @@ from .theme.theme_manager import ThemeManager
|
||||
from .core_rendering.draw_engine import DrawEngine
|
||||
from .core_widget_classes.widget_base_class import CTkBaseClass
|
||||
from .font.ctk_font import CTkFont
|
||||
from .image.ctk_image import CTkImage
|
||||
|
||||
from customtkinter.utility.utility_functions import pop_from_dict_by_set, check_kwargs_empty
|
||||
|
||||
@ -17,7 +18,7 @@ class CTkLabel(CTkBaseClass):
|
||||
"""
|
||||
|
||||
# attributes that are passed to and managed by the tkinter entry only:
|
||||
_valid_tk_label_attributes = {"compound", "cursor", "image", "justify", "padx", "pady",
|
||||
_valid_tk_label_attributes = {"cursor", "justify", "padx", "pady",
|
||||
"textvariable", "state", "takefocus", "underline", "wraplength"}
|
||||
|
||||
def __init__(self,
|
||||
@ -32,6 +33,8 @@ class CTkLabel(CTkBaseClass):
|
||||
|
||||
text: str = "CTkLabel",
|
||||
font: Union[tuple, CTkFont] = "default_theme",
|
||||
image: Union[tkinter.PhotoImage, CTkImage] = None,
|
||||
compound: str = "center",
|
||||
anchor: str = "center", # label anchor: center, n, e, s, w
|
||||
**kwargs):
|
||||
|
||||
@ -49,6 +52,12 @@ class CTkLabel(CTkBaseClass):
|
||||
self._anchor = anchor
|
||||
self._text = text
|
||||
|
||||
# image
|
||||
self._image = image
|
||||
self._compound = compound
|
||||
if isinstance(self._image, CTkImage):
|
||||
self._image.add_configure_callback(self._update_image)
|
||||
|
||||
# font
|
||||
self._font = CTkFont() if font == "default_theme" else self._check_font_type(font)
|
||||
if isinstance(self._font, CTkFont):
|
||||
@ -65,33 +74,35 @@ class CTkLabel(CTkBaseClass):
|
||||
self._canvas.grid(row=0, column=0, sticky="nswe")
|
||||
self._draw_engine = DrawEngine(self._canvas)
|
||||
|
||||
self._text_label = tkinter.Label(master=self,
|
||||
highlightthickness=0,
|
||||
padx=0,
|
||||
pady=0,
|
||||
borderwidth=1,
|
||||
anchor=self._anchor,
|
||||
text=self._text,
|
||||
font=self._apply_font_scaling(self._font))
|
||||
self._text_label.configure(**pop_from_dict_by_set(kwargs, self._valid_tk_label_attributes))
|
||||
self._label = tkinter.Label(master=self,
|
||||
highlightthickness=0,
|
||||
padx=0,
|
||||
pady=0,
|
||||
borderwidth=0,
|
||||
anchor=self._anchor,
|
||||
compound=self._compound,
|
||||
text=self._text,
|
||||
font=self._apply_font_scaling(self._font))
|
||||
self._label.configure(**pop_from_dict_by_set(kwargs, self._valid_tk_label_attributes))
|
||||
|
||||
text_label_grid_sticky = self._anchor if self._anchor != "center" else ""
|
||||
self._text_label.grid(row=0, column=0, sticky=text_label_grid_sticky,
|
||||
padx=self._apply_widget_scaling(min(self._corner_radius, round(self._current_height/2))))
|
||||
self._label.grid(row=0, column=0, sticky=text_label_grid_sticky,
|
||||
padx=self._apply_widget_scaling(min(self._corner_radius, round(self._current_height/2))))
|
||||
|
||||
check_kwargs_empty(kwargs, raise_error=True)
|
||||
|
||||
self._update_image()
|
||||
self._draw()
|
||||
|
||||
def _set_scaling(self, *args, **kwargs):
|
||||
super()._set_scaling(*args, **kwargs)
|
||||
|
||||
self._canvas.configure(width=self._apply_widget_scaling(self._desired_width), height=self._apply_widget_scaling(self._desired_height))
|
||||
self._text_label.configure(font=self._apply_font_scaling(self._font))
|
||||
self._label.configure(font=self._apply_font_scaling(self._font))
|
||||
|
||||
text_label_grid_sticky = self._anchor if self._anchor != "center" else ""
|
||||
self._text_label.grid(row=0, column=0, sticky=text_label_grid_sticky,
|
||||
padx=self._apply_widget_scaling(min(self._corner_radius, round(self._current_height/2))))
|
||||
self._label.grid(row=0, column=0, sticky=text_label_grid_sticky,
|
||||
padx=self._apply_widget_scaling(min(self._corner_radius, round(self._current_height/2))))
|
||||
|
||||
self._draw(no_color_updates=True)
|
||||
|
||||
@ -104,13 +115,20 @@ class CTkLabel(CTkBaseClass):
|
||||
|
||||
def _update_font(self):
|
||||
""" pass font to tkinter widgets with applied font scaling and update grid with workaround """
|
||||
self._text_label.configure(font=self._apply_font_scaling(self._font))
|
||||
self._label.configure(font=self._apply_font_scaling(self._font))
|
||||
|
||||
# Workaround to force grid to be resized when text changes size.
|
||||
# Otherwise grid will lag and only resizes if other mouse action occurs.
|
||||
self._canvas.grid_forget()
|
||||
self._canvas.grid(row=0, column=0, sticky="nswe")
|
||||
|
||||
def _update_image(self):
|
||||
if isinstance(self._image, CTkImage):
|
||||
self._label.configure(image=self._image.create_scaled_photo_image(self._get_widget_scaling(),
|
||||
self._get_appearance_mode()))
|
||||
elif self._image is not None:
|
||||
self._label.configure(image=self._image)
|
||||
|
||||
def destroy(self):
|
||||
if isinstance(self._font, CTkFont):
|
||||
self._font.remove_size_configure_callback(self._update_font)
|
||||
@ -130,28 +148,35 @@ class CTkLabel(CTkBaseClass):
|
||||
fill=self._apply_appearance_mode(self._fg_color),
|
||||
outline=self._apply_appearance_mode(self._fg_color))
|
||||
|
||||
self._text_label.configure(fg=self._apply_appearance_mode(self._text_color),
|
||||
bg=self._apply_appearance_mode(self._fg_color))
|
||||
self._label.configure(fg=self._apply_appearance_mode(self._text_color),
|
||||
bg=self._apply_appearance_mode(self._fg_color))
|
||||
else:
|
||||
self._canvas.itemconfig("inner_parts",
|
||||
fill=self._apply_appearance_mode(self._bg_color),
|
||||
outline=self._apply_appearance_mode(self._bg_color))
|
||||
|
||||
self._text_label.configure(fg=self._apply_appearance_mode(self._text_color),
|
||||
bg=self._apply_appearance_mode(self._bg_color))
|
||||
self._label.configure(fg=self._apply_appearance_mode(self._text_color),
|
||||
bg=self._apply_appearance_mode(self._bg_color))
|
||||
|
||||
self._canvas.configure(bg=self._apply_appearance_mode(self._bg_color))
|
||||
|
||||
if self._image is not None:
|
||||
self._update_image()
|
||||
|
||||
def configure(self, require_redraw=False, **kwargs):
|
||||
if "anchor" in kwargs:
|
||||
self._anchor = kwargs.pop("anchor")
|
||||
text_label_grid_sticky = self._anchor if self._anchor != "center" else ""
|
||||
self._text_label.grid(row=0, column=0, sticky=text_label_grid_sticky,
|
||||
padx=self._apply_widget_scaling(min(self._corner_radius, round(self._current_height/2))))
|
||||
self._label.grid(row=0, column=0, sticky=text_label_grid_sticky,
|
||||
padx=self._apply_widget_scaling(min(self._corner_radius, round(self._current_height/2))))
|
||||
|
||||
if "compound" in kwargs:
|
||||
self._compound = kwargs.pop("compound")
|
||||
self._label.configure(compound=self._compound)
|
||||
|
||||
if "text" in kwargs:
|
||||
self._text = kwargs.pop("text")
|
||||
self._text_label.configure(text=self._text)
|
||||
self._label.configure(text=self._text)
|
||||
|
||||
if "font" in kwargs:
|
||||
if isinstance(self._font, CTkFont):
|
||||
@ -159,9 +184,16 @@ class CTkLabel(CTkBaseClass):
|
||||
self._font = self._check_font_type(kwargs.pop("font"))
|
||||
if isinstance(self._font, CTkFont):
|
||||
self._font.add_size_configure_callback(self._update_font)
|
||||
|
||||
self._update_font()
|
||||
|
||||
if "image" in kwargs:
|
||||
if isinstance(self._image, CTkImage):
|
||||
self._image.remove_configure_callback(self._update_image)
|
||||
self._image = kwargs.pop("image")
|
||||
if isinstance(self._image, CTkImage):
|
||||
self._image.add_configure_callback(self._update_image)
|
||||
self._update_image()
|
||||
|
||||
if "fg_color" in kwargs:
|
||||
self._fg_color = kwargs.pop("fg_color")
|
||||
require_redraw = True
|
||||
@ -173,11 +205,11 @@ class CTkLabel(CTkBaseClass):
|
||||
if "corner_radius" in kwargs:
|
||||
self._corner_radius = kwargs.pop("corner_radius")
|
||||
text_label_grid_sticky = self._anchor if self._anchor != "center" else ""
|
||||
self._text_label.grid(row=0, column=0, sticky=text_label_grid_sticky,
|
||||
padx=self._apply_widget_scaling(min(self._corner_radius, round(self._current_height/2))))
|
||||
self._label.grid(row=0, column=0, sticky=text_label_grid_sticky,
|
||||
padx=self._apply_widget_scaling(min(self._corner_radius, round(self._current_height/2))))
|
||||
require_redraw = True
|
||||
|
||||
self._text_label.configure(**pop_from_dict_by_set(kwargs, self._valid_tk_label_attributes)) # configure tkinter.Label
|
||||
self._label.configure(**pop_from_dict_by_set(kwargs, self._valid_tk_label_attributes)) # configure tkinter.Label
|
||||
super().configure(require_redraw=require_redraw, **kwargs) # configure CTkBaseClass
|
||||
|
||||
def cget(self, attribute_name: str) -> any:
|
||||
@ -193,31 +225,35 @@ class CTkLabel(CTkBaseClass):
|
||||
return self._text
|
||||
elif attribute_name == "font":
|
||||
return self._font
|
||||
elif attribute_name == "image":
|
||||
return self._image
|
||||
elif attribute_name == "compound":
|
||||
return self._compound
|
||||
elif attribute_name == "anchor":
|
||||
return self._anchor
|
||||
|
||||
elif attribute_name in self._valid_tk_label_attributes:
|
||||
return self._text_label.cget(attribute_name) # cget of tkinter.Label
|
||||
return self._label.cget(attribute_name) # cget of tkinter.Label
|
||||
else:
|
||||
return super().cget(attribute_name) # cget of CTkBaseClass
|
||||
|
||||
def bind(self, sequence: str = None, command: Callable = None, add: str = None) -> str:
|
||||
""" called on the tkinter.Label and tkinter.Canvas """
|
||||
canvas_bind_return = self._canvas.bind(sequence, command, add)
|
||||
label_bind_return = self._text_label.bind(sequence, command, add)
|
||||
label_bind_return = self._label.bind(sequence, command, add)
|
||||
return canvas_bind_return + " + " + label_bind_return
|
||||
|
||||
def unbind(self, sequence: str, funcid: str = None):
|
||||
""" called on the tkinter.Label and tkinter.Canvas """
|
||||
canvas_bind_return, label_bind_return = funcid.split(" + ")
|
||||
self._canvas.unbind(sequence, canvas_bind_return)
|
||||
self._text_label.unbind(sequence, label_bind_return)
|
||||
self._label.unbind(sequence, label_bind_return)
|
||||
|
||||
def focus(self):
|
||||
return self._text_label.focus()
|
||||
return self._label.focus()
|
||||
|
||||
def focus_set(self):
|
||||
return self._text_label.focus_set()
|
||||
return self._label.focus_set()
|
||||
|
||||
def focus_force(self):
|
||||
return self._text_label.focus_force()
|
||||
return self._label.focus_force()
|
||||
|
@ -27,7 +27,6 @@ class CTkImage:
|
||||
self._check_pil_import()
|
||||
|
||||
self._light_image = light_image
|
||||
print(self._light_image)
|
||||
self._dark_image = dark_image
|
||||
self._check_images()
|
||||
self._size = size
|
||||
@ -109,7 +108,6 @@ class CTkImage:
|
||||
|
||||
def create_scaled_photo_image(self, widget_scaling: float, appearance_mode: str) -> ImageTk.PhotoImage:
|
||||
scaled_size = self._get_scaled_size(widget_scaling)
|
||||
print(scaled_size)
|
||||
|
||||
if appearance_mode == "light" and self._light_image is not None:
|
||||
return self._get_scaled_light_photo_image(scaled_size)
|
||||
|
@ -2,21 +2,34 @@ import customtkinter
|
||||
from PIL import Image, ImageTk
|
||||
import os
|
||||
|
||||
PATH = os.path.dirname(os.path.realpath(__file__))
|
||||
|
||||
# load images
|
||||
file_path = os.path.dirname(os.path.realpath(__file__))
|
||||
image_1 = customtkinter.CTkImage(light_image=Image.open(file_path + "/test_images/add_folder_dark.png"),
|
||||
dark_image=Image.open(file_path + "/test_images/add_folder_light.png"),
|
||||
size=(30, 30))
|
||||
image_1.configure(dark_image=Image.open(file_path + "/test_images/add_folder_light.png"))
|
||||
image_2 = customtkinter.CTkImage(light_image=Image.open(file_path + "/test_images/bg_gradient.jpg"),
|
||||
size=(30, 50))
|
||||
|
||||
app = customtkinter.CTk()
|
||||
|
||||
switch_1 = customtkinter.CTkSwitch(app, text="darkmode", command=lambda: customtkinter.set_appearance_mode("dark" if switch_1.get() == 1 else "light"))
|
||||
switch_1.pack(padx=20, pady=20)
|
||||
mode_switch = customtkinter.CTkSwitch(app, text="darkmode",
|
||||
command=lambda: customtkinter.set_appearance_mode("dark" if mode_switch.get() == 1 else "light"))
|
||||
mode_switch.pack(padx=20, pady=20)
|
||||
|
||||
image_1 = customtkinter.CTkImage(light_image=Image.open(PATH + "/test_images/add_folder_dark.png"),
|
||||
dark_image=Image.open(PATH + "/test_images/add_folder_light.png"),
|
||||
size=(30, 50))
|
||||
image_1.configure(dark_image=Image.open(PATH + "/test_images/add_folder_light.png"))
|
||||
scaling_button = customtkinter.CTkSegmentedButton(app, values=[0.8, 0.9, 1.0, 1.1, 1.2, 1.5, 2.0],
|
||||
command=lambda v: customtkinter.set_widget_scaling(v))
|
||||
scaling_button.pack(padx=20, pady=20)
|
||||
|
||||
button_1 = customtkinter.CTkButton(app, image=image_1)
|
||||
button_1.pack(padx=20, pady=20)
|
||||
|
||||
label_1 = customtkinter.CTkLabel(app, text="", image=image_2, compound="right", fg_color="green", width=0)
|
||||
label_1.pack(padx=20, pady=20)
|
||||
label_1.configure(image=image_1)
|
||||
label_2 = customtkinter.CTkLabel(app, image=ImageTk.PhotoImage(Image.open(file_path + "/test_images/bg_gradient.jpg").resize((100, 100))),
|
||||
text="", compound="right", fg_color="green", width=0)
|
||||
label_2.pack(padx=20, pady=20)
|
||||
|
||||
app.mainloop()
|
||||
|
||||
|
BIN
examples/test_images/add_folder_dark.png
Normal file
BIN
examples/test_images/add_folder_dark.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 7.9 KiB |
BIN
examples/test_images/add_folder_light.png
Normal file
BIN
examples/test_images/add_folder_light.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 4.8 KiB |
Loading…
Reference in New Issue
Block a user