mirror of
https://github.com/TomSchimansky/CustomTkinter.git
synced 2023-08-10 21:13:13 +03:00
fixed scaling for DropdownMenu
This commit is contained in:
parent
9bd55cc159
commit
9d618386e1
@ -21,6 +21,7 @@ class DrawEngine:
|
|||||||
- draw_rounded_progress_bar_with_border()
|
- draw_rounded_progress_bar_with_border()
|
||||||
- draw_rounded_slider_with_border_and_button()
|
- draw_rounded_slider_with_border_and_button()
|
||||||
- draw_checkmark()
|
- draw_checkmark()
|
||||||
|
- draw_dropdown_arrow()
|
||||||
|
|
||||||
"""
|
"""
|
||||||
|
|
||||||
@ -986,3 +987,37 @@ class DrawEngine:
|
|||||||
self._canvas.coords("checkmark", round(width / 2), round(height / 2))
|
self._canvas.coords("checkmark", round(width / 2), round(height / 2))
|
||||||
|
|
||||||
return requires_recoloring
|
return requires_recoloring
|
||||||
|
|
||||||
|
def draw_dropdown_arrow(self, x_position: Union[int, float], y_position: Union[int, float], size: Union[int, float]) -> bool:
|
||||||
|
""" Draws a dropdown bottom facing arrow at (x_position, y_position) in a given size
|
||||||
|
|
||||||
|
returns bool if recoloring is necessary """
|
||||||
|
|
||||||
|
x_position, y_position, size = round(x_position), round(y_position), round(size)
|
||||||
|
requires_recoloring = False
|
||||||
|
|
||||||
|
if self.preferred_drawing_method == "polygon_shapes" or self.preferred_drawing_method == "circle_shapes":
|
||||||
|
if not self._canvas.find_withtag("dropdown_arrow"):
|
||||||
|
self._canvas.create_line(0, 0, 0, 0, tags=("dropdown_arrow"), width=round(size / 4), joinstyle=tkinter.MITER, capstyle=tkinter.ROUND)
|
||||||
|
self._canvas.tag_raise("dropdown_arrow")
|
||||||
|
requires_recoloring = True
|
||||||
|
|
||||||
|
self._canvas.coords("dropdown_arrow",
|
||||||
|
x_position - (size / 2),
|
||||||
|
y_position - (size / 5),
|
||||||
|
x_position,
|
||||||
|
y_position + (size / 5),
|
||||||
|
x_position + (size / 2),
|
||||||
|
y_position - (size / 5))
|
||||||
|
|
||||||
|
elif self.preferred_drawing_method == "font_shapes":
|
||||||
|
return False
|
||||||
|
|
||||||
|
if not self._canvas.find_withtag("checkmark"):
|
||||||
|
self._canvas.create_text(0, 0, text="Z", font=("CustomTkinter_shapes_font", -size), tags=("checkmark", "create_text"), anchor=tkinter.CENTER)
|
||||||
|
self._canvas.tag_raise("checkmark")
|
||||||
|
requires_recoloring = True
|
||||||
|
|
||||||
|
self._canvas.coords("checkmark", round(width / 2), round(height / 2))
|
||||||
|
|
||||||
|
return requires_recoloring
|
||||||
|
@ -120,6 +120,9 @@ class CTkOptionMenu(CTkBaseClass):
|
|||||||
0,
|
0,
|
||||||
self.apply_widget_scaling(left_section_width))
|
self.apply_widget_scaling(left_section_width))
|
||||||
|
|
||||||
|
requires_recoloring_2 = self.draw_engine.draw_dropdown_arrow(self.apply_widget_scaling(self.current_width - (self.current_height / 2)),
|
||||||
|
self.apply_widget_scaling(self.current_height / 2),
|
||||||
|
self.apply_widget_scaling(self.current_height / 3))
|
||||||
if self.text_label is None:
|
if self.text_label is None:
|
||||||
self.text_label = tkinter.Label(master=self,
|
self.text_label = tkinter.Label(master=self,
|
||||||
font=self.apply_font_scaling(self.text_font))
|
font=self.apply_font_scaling(self.text_font))
|
||||||
@ -135,7 +138,7 @@ class CTkOptionMenu(CTkBaseClass):
|
|||||||
if self.current_value is not None:
|
if self.current_value is not None:
|
||||||
self.text_label.configure(text=self.current_value)
|
self.text_label.configure(text=self.current_value)
|
||||||
|
|
||||||
if no_color_updates is False or requires_recoloring:
|
if no_color_updates is False or requires_recoloring or requires_recoloring_2:
|
||||||
|
|
||||||
self.canvas.configure(bg=ThemeManager.single_color(self.bg_color, self.appearance_mode))
|
self.canvas.configure(bg=ThemeManager.single_color(self.bg_color, self.appearance_mode))
|
||||||
|
|
||||||
@ -150,14 +153,18 @@ class CTkOptionMenu(CTkBaseClass):
|
|||||||
|
|
||||||
if self.state == tkinter.DISABLED:
|
if self.state == tkinter.DISABLED:
|
||||||
self.text_label.configure(fg=(ThemeManager.single_color(self.text_color_disabled, self.appearance_mode)))
|
self.text_label.configure(fg=(ThemeManager.single_color(self.text_color_disabled, self.appearance_mode)))
|
||||||
|
self.canvas.itemconfig("dropdown_arrow",
|
||||||
|
fill=ThemeManager.single_color(self.text_color_disabled, self.appearance_mode))
|
||||||
else:
|
else:
|
||||||
self.text_label.configure(fg=ThemeManager.single_color(self.text_color, self.appearance_mode))
|
self.text_label.configure(fg=ThemeManager.single_color(self.text_color, self.appearance_mode))
|
||||||
|
self.canvas.itemconfig("dropdown_arrow",
|
||||||
|
fill=ThemeManager.single_color(self.text_color, self.appearance_mode))
|
||||||
|
|
||||||
self.text_label.configure(bg=ThemeManager.single_color(self.fg_color, self.appearance_mode))
|
self.text_label.configure(bg=ThemeManager.single_color(self.fg_color, self.appearance_mode))
|
||||||
|
|
||||||
def open_dropdown_menu(self):
|
def open_dropdown_menu(self):
|
||||||
self.dropdown_menu = DropdownMenu(x_position=self.winfo_rootx(),
|
self.dropdown_menu = DropdownMenu(x_position=self.winfo_rootx(),
|
||||||
y_position=self.winfo_rooty() + self.current_height + 4,
|
y_position=self.winfo_rooty() + self.apply_widget_scaling(self.current_height + 4),
|
||||||
width=self.current_width,
|
width=self.current_width,
|
||||||
values=self.values,
|
values=self.values,
|
||||||
command=self.set,
|
command=self.set,
|
||||||
|
@ -4,6 +4,7 @@ import sys
|
|||||||
|
|
||||||
from ..theme_manager import ThemeManager
|
from ..theme_manager import ThemeManager
|
||||||
from ..appearance_mode_tracker import AppearanceModeTracker
|
from ..appearance_mode_tracker import AppearanceModeTracker
|
||||||
|
from ..scaling_tracker import ScalingTracker
|
||||||
|
|
||||||
|
|
||||||
class DropdownMenu(tkinter.Toplevel):
|
class DropdownMenu(tkinter.Toplevel):
|
||||||
@ -25,6 +26,9 @@ class DropdownMenu(tkinter.Toplevel):
|
|||||||
**kwargs):
|
**kwargs):
|
||||||
super().__init__(*args, **kwargs)
|
super().__init__(*args, **kwargs)
|
||||||
|
|
||||||
|
ScalingTracker.add_widget(self.set_scaling, self)
|
||||||
|
self.widget_scaling = ScalingTracker.get_widget_scaling(self)
|
||||||
|
|
||||||
self.values = values
|
self.values = values
|
||||||
self.command = command
|
self.command = command
|
||||||
|
|
||||||
@ -41,7 +45,9 @@ class DropdownMenu(tkinter.Toplevel):
|
|||||||
self.button_corner_radius = button_corner_radius
|
self.button_corner_radius = button_corner_radius
|
||||||
self.button_height = button_height
|
self.button_height = button_height
|
||||||
|
|
||||||
self.geometry(f"{round(self.width)}x{round(len(self.values) * (self.button_height + y_spacing) + y_spacing)}+{round(x_position)}+{round(y_position)}")
|
self.geometry(f"{round(self.apply_widget_scaling(self.width))}x" +
|
||||||
|
f"{round(self.apply_widget_scaling(len(self.values) * (self.button_height + y_spacing) + y_spacing))}+" +
|
||||||
|
f"{round(x_position)}+{round(y_position)}")
|
||||||
self.grid_columnconfigure(0, weight=1)
|
self.grid_columnconfigure(0, weight=1)
|
||||||
|
|
||||||
if sys.platform.startswith("darwin"):
|
if sys.platform.startswith("darwin"):
|
||||||
@ -49,7 +55,10 @@ class DropdownMenu(tkinter.Toplevel):
|
|||||||
self.overrideredirect(False)
|
self.overrideredirect(False)
|
||||||
self.wm_attributes("-transparent", True) # turn off window shadow
|
self.wm_attributes("-transparent", True) # turn off window shadow
|
||||||
self.config(bg='systemTransparent') # transparent bg
|
self.config(bg='systemTransparent') # transparent bg
|
||||||
self.frame = customtkinter.CTkFrame(self, border_width=0, width=self.width, corner_radius=self.corner_radius,
|
self.frame = customtkinter.CTkFrame(self,
|
||||||
|
border_width=0,
|
||||||
|
width=self.width,
|
||||||
|
corner_radius=self.corner_radius,
|
||||||
fg_color=ThemeManager.single_color(self.fg_color, self.appearance_mode))
|
fg_color=ThemeManager.single_color(self.fg_color, self.appearance_mode))
|
||||||
|
|
||||||
elif sys.platform.startswith("win"):
|
elif sys.platform.startswith("win"):
|
||||||
@ -57,13 +66,19 @@ class DropdownMenu(tkinter.Toplevel):
|
|||||||
self.configure(bg="#010302")
|
self.configure(bg="#010302")
|
||||||
self.wm_attributes("-transparentcolor", "#010302")
|
self.wm_attributes("-transparentcolor", "#010302")
|
||||||
self.focus()
|
self.focus()
|
||||||
self.frame = customtkinter.CTkFrame(self, border_width=0, width=120, corner_radius=self.corner_radius,
|
self.frame = customtkinter.CTkFrame(self,
|
||||||
|
border_width=0,
|
||||||
|
width=self.width,
|
||||||
|
corner_radius=self.corner_radius,
|
||||||
fg_color=self.fg_color, overwrite_preferred_drawing_method="circle_shapes")
|
fg_color=self.fg_color, overwrite_preferred_drawing_method="circle_shapes")
|
||||||
else:
|
else:
|
||||||
self.overrideredirect(True) # remove title-bar
|
self.overrideredirect(True) # remove title-bar
|
||||||
self.configure(bg="#010302")
|
self.configure(bg="#010302")
|
||||||
self.wm_attributes("-transparentcolor", "#010302")
|
self.wm_attributes("-transparentcolor", "#010302")
|
||||||
self.frame = customtkinter.CTkFrame(self, border_width=0, width=120, corner_radius=self.corner_radius,
|
self.frame = customtkinter.CTkFrame(self,
|
||||||
|
border_width=0,
|
||||||
|
width=self.width,
|
||||||
|
corner_radius=self.corner_radius,
|
||||||
fg_color=self.fg_color, overwrite_preferred_drawing_method="circle_shapes")
|
fg_color=self.fg_color, overwrite_preferred_drawing_method="circle_shapes")
|
||||||
|
|
||||||
self.frame.grid(row=0, column=0, sticky="nsew", rowspan=len(self.values) + 1)
|
self.frame.grid(row=0, column=0, sticky="nsew", rowspan=len(self.values) + 1)
|
||||||
@ -72,17 +87,33 @@ class DropdownMenu(tkinter.Toplevel):
|
|||||||
|
|
||||||
self.button_list = []
|
self.button_list = []
|
||||||
for index, option in enumerate(self.values):
|
for index, option in enumerate(self.values):
|
||||||
button = customtkinter.CTkButton(self.frame, text=option, height=self.button_height, width=self.width - 2 * x_spacing,
|
button = customtkinter.CTkButton(self.frame,
|
||||||
fg_color=self.button_color, text_color=self.text_color,
|
text=option,
|
||||||
hover_color=self.button_hover_color, corner_radius=self.button_corner_radius,
|
height=self.button_height,
|
||||||
|
width=self.width - 2 * x_spacing,
|
||||||
|
fg_color=self.button_color,
|
||||||
|
text_color=self.text_color,
|
||||||
|
hover_color=self.button_hover_color,
|
||||||
|
corner_radius=self.button_corner_radius,
|
||||||
command=lambda i=index: self.button_callback(i))
|
command=lambda i=index: self.button_callback(i))
|
||||||
button.text_label.grid(row=0, column=0, rowspan=2, columnspan=2, sticky="w")
|
button.text_label.grid(row=0, column=0, rowspan=2, columnspan=2, sticky="w")
|
||||||
button.grid(row=index, column=0, padx=x_spacing, pady=(y_spacing, 0), sticky="ew")
|
button.grid(row=index, column=0,
|
||||||
|
padx=x_spacing,
|
||||||
|
pady=(y_spacing, 0), sticky="ew")
|
||||||
self.button_list.append(button)
|
self.button_list.append(button)
|
||||||
|
|
||||||
self.bind("<FocusOut>", self.focus_loss_event)
|
self.bind("<FocusOut>", self.focus_loss_event)
|
||||||
self.frame.canvas.bind("<Button-1>", self.focus_loss_event)
|
self.frame.canvas.bind("<Button-1>", self.focus_loss_event)
|
||||||
|
|
||||||
|
def apply_widget_scaling(self, value):
|
||||||
|
if isinstance(value, (int, float)):
|
||||||
|
return value * self.widget_scaling
|
||||||
|
else:
|
||||||
|
return value
|
||||||
|
|
||||||
|
def set_scaling(self, new_widget_scaling, new_spacing_scaling, new_window_scaling):
|
||||||
|
return
|
||||||
|
|
||||||
def focus_loss_event(self, event):
|
def focus_loss_event(self, event):
|
||||||
self.destroy()
|
self.destroy()
|
||||||
if sys.platform.startswith("darwin"):
|
if sys.platform.startswith("darwin"):
|
||||||
|
Loading…
Reference in New Issue
Block a user