small fixes

This commit is contained in:
Tom Schimansky 2022-03-01 19:10:18 +01:00
parent afc8ce8c3d
commit ecd4881ffb
9 changed files with 31 additions and 183 deletions

View File

@ -1,4 +1,4 @@
__version__ = "2.3"
__version__ = "2.4"
from .customtkinter_button import CTkButton
from .customtkinter_slider import CTkSlider

View File

@ -51,7 +51,7 @@
"progressbar_corner_radius": 100,
"slider_border_width": 5,
"slider_corner_radius": 8,
"slider_button_length": 0,
"slider_button_length": 10,
"slider_button_corner_radius": 8
}
}

View File

@ -98,7 +98,7 @@ class CTkDrawEngine:
# create inner button parts
if not self._canvas.find_withtag("inner_parts"):
self._canvas.create_polygon((0, 0, 0, 0), tags=("inner_line_1", "inner_parts"))
self._canvas.create_polygon((0, 0, 0, 0), tags=("inner_line_1", "inner_parts"), joinstyle=tkinter.ROUND)
requires_recoloring = True
if corner_radius <= border_width:
@ -107,19 +107,18 @@ class CTkDrawEngine:
bottom_right_shift = 0
self._canvas.coords("inner_line_1",
(border_width + inner_corner_radius,
border_width + inner_corner_radius,
border_width + inner_corner_radius,
width - (border_width + inner_corner_radius) + bottom_right_shift,
border_width + inner_corner_radius,
width - (border_width + inner_corner_radius) + bottom_right_shift,
height - (border_width + inner_corner_radius) + bottom_right_shift,
border_width + inner_corner_radius,
height - (border_width + inner_corner_radius) + bottom_right_shift))
height - (border_width + inner_corner_radius) + bottom_right_shift)
self._canvas.itemconfig("inner_line_1",
joinstyle=tkinter.ROUND,
width=inner_corner_radius * 2)
if requires_recoloring:
if requires_recoloring: # new parts were added -> manage z-order
self._canvas.tag_lower("inner_parts")
self._canvas.tag_lower("border_parts")
@ -238,7 +237,7 @@ class CTkDrawEngine:
width - border_width,
height - inner_corner_radius - border_width))
if requires_recoloring:
if requires_recoloring: # new parts were added -> manage z-order
self._canvas.tag_lower("inner_parts")
self._canvas.tag_lower("border_parts")
@ -350,7 +349,7 @@ class CTkDrawEngine:
requires_recoloring = self._draw_rounded_rect_with_border_polygon_shapes(width, height, corner_radius, border_width, inner_corner_radius)
if corner_radius <= border_width:
bottom_right_shift = -1 # weird canvas rendering inaccuracy that has to be corrected in some cases
bottom_right_shift = 0 # weird canvas rendering inaccuracy that has to be corrected in some cases
else:
bottom_right_shift = 0
@ -503,14 +502,6 @@ class CTkDrawEngine:
else:
inner_corner_radius = 0
# scale slider_value to a smaller range to be the progress_value of the underlaying progressbar
if orientation == "w" or orientation == "e":
x = (button_length / width) / 2
else:
x = (button_length / height) / 2
print(x)
new_slider_value = slider_value * (1 - 2 * x) + x
if self._rendering_method == "polygon_shapes" or self._rendering_method == "circle_shapes":
return self._draw_rounded_slider_with_border_and_button_polygon_shapes(width, height, corner_radius, border_width, inner_corner_radius,
button_length, button_corner_radius, slider_value, orientation)
@ -521,13 +512,14 @@ class CTkDrawEngine:
def _draw_rounded_slider_with_border_and_button_polygon_shapes(self, width: int, height: int, corner_radius: int, border_width: int, inner_corner_radius: int,
button_length: int, button_corner_radius: int, slider_value: float, orientation: str) -> bool:
# draw normal progressbar
requires_recoloring = self._draw_rounded_progress_bar_with_border_polygon_shapes(width, height, corner_radius, border_width, inner_corner_radius,
slider_value, orientation)
# create button parts
# create slider button part
if not self._canvas.find_withtag("slider_parts"):
self._canvas.create_polygon((0, 0, 0, 0), tags=("slider_line_1", "slider_parts"), joinstyle=tkinter.ROUND)
self._canvas.tag_raise("slider_parts")
self._canvas.tag_raise("slider_parts") # manage z-order
requires_recoloring = True
if corner_radius <= border_width:
@ -550,9 +542,11 @@ class CTkDrawEngine:
def _draw_rounded_slider_with_border_and_button_font_shapes(self, width: int, height: int, corner_radius: int, border_width: int, inner_corner_radius: int,
button_length: int, button_corner_radius: int, slider_value: float, orientation: str) -> bool:
# draw normal progressbar
requires_recoloring = self._draw_rounded_progress_bar_with_border_font_shapes(width, height, corner_radius, border_width, inner_corner_radius,
slider_value, orientation)
# create 4 circles (if not needed, then less)
if not self._canvas.find_withtag("slider_oval_1_a"):
self._canvas.create_aa_circle(0, 0, 0, tags=("slider_oval_1_a", "slider_corner_part", "slider_parts"), anchor=tkinter.CENTER)
self._canvas.create_aa_circle(0, 0, 0, tags=("slider_oval_1_b", "slider_corner_part", "slider_parts"), anchor=tkinter.CENTER, angle=180)
@ -579,6 +573,7 @@ class CTkDrawEngine:
elif self._canvas.find_withtag("border_oval_3_a") and not (button_length > 0 and height > 2 * button_corner_radius):
self._canvas.delete("slider_oval_3_a", "slider_oval_3_b")
# create the 2 rectangles (if needed)
if not self._canvas.find_withtag("slider_rectangle_1") and button_length > 0:
self._canvas.create_rectangle(0, 0, 0, 0, tags=("slider_rectangle_1", "slider_rectangle_part", "slider_parts"), width=0)
requires_recoloring = True
@ -591,6 +586,7 @@ class CTkDrawEngine:
elif self._canvas.find_withtag("slider_rectangle_2") and not height > 2 * button_corner_radius:
self._canvas.delete("slider_rectangle_2")
# set positions of circles and rectangles
slider_x_position = corner_radius + (button_length / 2) + (width - 2 * corner_radius - button_length) * slider_value
self._canvas.coords("slider_oval_1_a", slider_x_position - (button_length / 2), button_corner_radius, button_corner_radius)
self._canvas.coords("slider_oval_1_b", slider_x_position - (button_length / 2), button_corner_radius, button_corner_radius)
@ -608,7 +604,7 @@ class CTkDrawEngine:
slider_x_position - (button_length / 2) - button_corner_radius, button_corner_radius,
slider_x_position + (button_length / 2) + button_corner_radius, height - button_corner_radius)
if requires_recoloring:
if requires_recoloring: # new parts were added -> manage z-order
self._canvas.tag_raise("slider_parts")
return requires_recoloring
return requires_recoloring

View File

@ -1,5 +1,4 @@
import tkinter
import sys
from .customtkinter_tk import CTk
from .customtkinter_frame import CTkFrame
@ -19,8 +18,8 @@ class CTkEntry(tkinter.Frame):
placeholder_text_color="default_theme",
text_font="default_theme",
placeholder_text=None,
corner_radius=8,
border_width=0,
corner_radius="default_theme",
border_width="default_theme",
border_color="default_theme",
width=120,
height=30,

View File

@ -69,11 +69,14 @@ class CTkLabel(tkinter.Frame):
self.text = text
self.text_font = (CTkThemeManager.theme["text"]["font"], CTkThemeManager.theme["text"]["size"]) if text_font == "default_theme" else text_font
self.grid_rowconfigure(0, weight=1)
self.grid_columnconfigure(0, weight=1)
self.canvas = CTkCanvas(master=self,
highlightthickness=0,
width=self.width,
height=self.height)
self.canvas.place(relx=0, rely=0, anchor=tkinter.NW)
self.canvas.grid(row=0, column=0, sticky="nswe")
self.text_label = tkinter.Label(master=self,
highlightthickness=0,
@ -81,7 +84,7 @@ class CTkLabel(tkinter.Frame):
text=self.text,
font=self.text_font,
**kwargs)
self.text_label.place(relx=0.5, rely=0.5, anchor=tkinter.CENTER)
self.text_label.grid(row=0, column=0, padx=self.corner_radius)
self.draw_engine = CTkDrawEngine(self.canvas, CTkSettings.preferred_drawing_method)
@ -134,8 +137,6 @@ class CTkLabel(tkinter.Frame):
if "fg_color" in kwargs:
self.fg_color = kwargs["fg_color"]
require_redraw = True
if self.fg_color is None:
self.fg_color = self.bg_color
del kwargs["fg_color"]
if "bg_color" in kwargs:

View File

@ -156,20 +156,12 @@ class CTkSlider(tkinter.Frame):
self.draw()
def draw(self, no_color_updates=False):
# # decide the drawing method
# if sys.platform == "darwin":
# # on macOS draw button with polygons (positions are more accurate, macOS has Antialiasing)
# self.draw_with_polygon_shapes()
# else:
# # on Windows and other draw with ovals (corner_radius can be optimised to look better than with polygons)
# self.draw_with_ovals_and_rects()
def draw(self, color_updates=True):
requires_recoloring = self.draw_engine.draw_rounded_slider_with_border_and_button(self.width, self.height, self.corner_radius, self.border_width,
self.button_length, self.button_corner_radius, self.value, "w")
if no_color_updates is False or requires_recoloring:
if color_updates or requires_recoloring:
self.canvas.configure(bg=CTkThemeManager.single_color(self.bg_color, self.appearance_mode))
if self.border_color is None:
@ -192,146 +184,6 @@ class CTkSlider(tkinter.Frame):
self.canvas.itemconfig("slider_parts", fill=CTkThemeManager.single_color(self.button_color, self.appearance_mode),
outline=CTkThemeManager.single_color(self.button_color, self.appearance_mode))
def draw_with_polygon_shapes(self):
""" draw the slider parts with just three polygons that have a rounded border """
coordinate_shift = -1
width_reduced = -1
# create border parts
if self.border_width > 0:
if not self.canvas.find_withtag("border_parts"):
self.canvas.create_line((0, 0, 0, 0), tags=("border_line_1", "border_parts"))
self.canvas.coords("border_line_1",
(self.height / 2,
self.height / 2,
self.width - self.height / 2 + coordinate_shift,
self.height / 2))
self.canvas.itemconfig("border_line_1",
capstyle=tkinter.ROUND,
width=self.height + width_reduced)
# create inner button parts
if not self.canvas.find_withtag("inner_parts"):
self.canvas.create_line((0, 0, 0, 0), tags=("inner_line_1", "inner_parts"))
if self.progress_color != self.fg_color:
if not self.canvas.find_withtag("progress_parts"):
self.canvas.create_line((0, 0, 0, 0), tags=("inner_line_progress", "progress_parts"))
self.canvas.tag_raise("button_parts")
else:
self.canvas.delete("progress_parts")
self.canvas.coords("inner_line_1",
(((self.width + coordinate_shift - self.height) * self.value + self.height / 2),
self.height / 2,
self.width - self.height / 2 + coordinate_shift,
self.height / 2))
if self.progress_color != self.fg_color:
self.canvas.coords("inner_line_progress",
(self.height / 2,
self.height / 2,
((self.width + coordinate_shift - self.height) * self.value + self.height / 2),
self.height / 2))
self.canvas.itemconfig("inner_parts",
capstyle=tkinter.ROUND,
width=self.height - self.border_width * 2 + width_reduced)
self.canvas.itemconfig("progress_parts",
capstyle=tkinter.ROUND,
width=self.height - self.border_width * 2 + width_reduced)
# button parts
if not self.canvas.find_withtag("button_parts"):
self.canvas.create_line((0, 0, 0, 0), tags=("button_line_1", "button_parts"))
self.canvas.coords("button_line_1",
(self.height / 2 + (self.width + coordinate_shift - self.height) * self.value,
self.height / 2,
self.height / 2 + (self.width + coordinate_shift - self.height) * self.value,
self.height / 2))
self.canvas.itemconfig("button_line_1",
capstyle=tkinter.ROUND,
width=self.height + width_reduced)
def draw_with_ovals_and_rects(self):
""" draw the progress bar parts with ovals and rectangles """
# ovals and rects are always rendered too large and need to be made smaller by -1
oval_bottom_right_shift = -1
rect_bottom_right_shift = 0
# frame_border
if self.border_width > 0:
if not self.canvas.find_withtag("border_parts"):
self.canvas.create_oval((0, 0, 0, 0), tags=("border_oval_1", "border_parts"), width=0)
self.canvas.create_rectangle((0, 0, 0, 0), tags=("border_rect_1", "border_parts"), width=0)
self.canvas.create_oval((0, 0, 0, 0), tags=("border_oval_2", "border_parts"), width=0)
self.canvas.coords("border_oval_1", (0,
0,
self.height + oval_bottom_right_shift,
self.height + oval_bottom_right_shift))
self.canvas.coords("border_rect_1", (self.height/2,
0,
self.width-(self.height/2) + rect_bottom_right_shift,
self.height + rect_bottom_right_shift))
self.canvas.coords("border_oval_2", (self.width-self.height,
0,
self.width + oval_bottom_right_shift,
self.height + oval_bottom_right_shift))
# foreground
if not self.canvas.find_withtag("inner_parts"):
self.canvas.create_rectangle((0, 0, 0, 0), tags=("inner_rect_2", "inner_parts"), width=0)
self.canvas.create_oval((0, 0, 0, 0), tags=("inner_oval_2", "inner_parts"), width=0)
# progress parts
if not self.canvas.find_withtag("inner_oval_1"):
self.canvas.delete("inner_oval_1", "inner_rect_1")
if self.progress_color != self.fg_color:
self.canvas.create_oval((0, 0, 0, 0), tags=("inner_oval_1", "progress_parts"), width=0)
self.canvas.create_rectangle((0, 0, 0, 0), tags=("inner_rect_1", "progress_parts"), width=0)
else:
self.canvas.create_oval((0, 0, 0, 0), tags=("inner_oval_1", "inner_parts"), width=0)
if self.progress_color != self.fg_color:
self.canvas.coords("inner_rect_1", (self.height / 2,
self.border_width,
(self.width - self.height) * self.value + (self.height / 2 + rect_bottom_right_shift),
self.height - self.border_width + rect_bottom_right_shift))
self.canvas.coords("inner_rect_2", ((self.width - self.height) * self.value + (self.height / 2 + rect_bottom_right_shift),
self.border_width,
self.width - (self.height / 2 + rect_bottom_right_shift),
self.height - self.border_width + rect_bottom_right_shift))
else:
self.canvas.coords("inner_rect_2", (self.height/2,
self.border_width,
self.width-(self.height/2 + rect_bottom_right_shift),
self.height-self.border_width + rect_bottom_right_shift))
self.canvas.coords("inner_oval_1", (self.border_width,
self.border_width,
self.height - self.border_width + oval_bottom_right_shift,
self.height - self.border_width + oval_bottom_right_shift))
self.canvas.coords("inner_oval_2", (self.width-self.height+self.border_width,
self.border_width,
self.width-self.border_width + oval_bottom_right_shift,
self.height-self.border_width + oval_bottom_right_shift))
# progress parts
if not self.canvas.find_withtag("button_parts"):
self.canvas.create_oval((0, 0, 0, 0), tags=("button_oval_1", "button_parts"), width=0)
self.canvas.coords("button_oval_1",
((self.width - self.height) * self.value,
0,
self.height + (self.width - self.height) * self.value + oval_bottom_right_shift,
self.height + oval_bottom_right_shift))
def clicked(self, event=None):
self.value = event.x / self.width
@ -343,7 +195,7 @@ class CTkSlider(tkinter.Frame):
self.output_value = self.round_to_step_size(self.from_ + (self.value * (self.to - self.from_)))
self.value = (self.output_value - self.from_) / (self.to - self.from_)
self.draw(no_color_updates=True)
self.draw(color_updates=False)
if self.callback_function is not None:
self.callback_function(self.output_value)
@ -389,7 +241,7 @@ class CTkSlider(tkinter.Frame):
self.output_value = self.round_to_step_size(output_value)
self.value = (self.output_value - self.from_) / (self.to - self.from_)
self.draw(no_color_updates=True)
self.draw(color_updates=False)
if self.callback_function is not None:
self.callback_function(self.output_value)

View File

@ -18,7 +18,7 @@ class CTkToplevel(tkinter.Toplevel):
super().__init__(*args, **kwargs)
self.appearance_mode = AppearanceModeTracker.get_mode() # 0: "Light" 1: "Dark"
self.fg_color = CTkThemeManager.WINDOW_BG_COLOR if fg_color == "default_theme" else fg_color
self.fg_color = CTkThemeManager.theme["color"]["window_bg_color"] if fg_color == "default_theme" else fg_color
if "bg" in kwargs:
self.fg_color = kwargs["bg"]

View File

@ -19,7 +19,7 @@ def read(filename):
setup(name="customtkinter",
version="2.3",
version="2.4",
author="Tom Schimansky",
license="Creative Commons Zero v1.0 Universal",
url="https://github.com/TomSchimansky/CustomTkinter",

View File

@ -1,7 +1,7 @@
import customtkinter
import tkinter
customtkinter.CTkSettings.preferred_drawing_method = "font_shapes"
customtkinter.CTkSettings.preferred_drawing_method = "polygon_shapes"
customtkinter.set_default_color_theme("blue")
customtkinter.set_appearance_mode("dark")