enhanced dropdown_menu_fallback.py

This commit is contained in:
Tom Schimansky 2022-06-13 15:08:13 +02:00
parent 9c479bc1de
commit 91e7e3077c
7 changed files with 101 additions and 26 deletions

View File

@ -3,3 +3,4 @@ class Settings:
cursor_manipulation_enabled = True
deactivate_macos_window_header_manipulation = False
deactivate_windows_window_header_manipulation = False
use_dropdown_fallback = True

View File

@ -51,7 +51,7 @@ class CTkEntry(CTkBaseClass):
highlightthickness=0,
width=self.apply_widget_scaling(self._current_width),
height=self.apply_widget_scaling(self._current_height))
self.canvas.grid(column=0, row=0, sticky="we")
self.canvas.grid(column=0, row=0, sticky="nswe")
self.draw_engine = DrawEngine(self.canvas)
self.entry = tkinter.Entry(master=self,
@ -61,8 +61,9 @@ class CTkEntry(CTkBaseClass):
font=self.apply_font_scaling(self.text_font),
state=self.state,
**kwargs)
self.entry.grid(column=0, row=0, sticky="we",
padx=self.apply_widget_scaling(self.corner_radius) if self.corner_radius >= 6 else self.apply_widget_scaling(6))
self.entry.grid(column=0, row=0, sticky="nswe",
padx=self.apply_widget_scaling(self.corner_radius) if self.corner_radius >= 6 else self.apply_widget_scaling(6),
pady=(self.apply_widget_scaling(self.border_width), self.apply_widget_scaling(self.border_width + 1)))
super().bind('<Configure>', self.update_dimensions_event)
self.entry.bind('<FocusOut>', self.set_placeholder)

View File

@ -3,6 +3,7 @@ import sys
from typing import Union
from .dropdown_menu import DropdownMenu
from .dropdown_menu_fallback import DropdownMenuFallback
from .ctk_canvas import CTkCanvas
from ..theme_manager import ThemeManager
@ -168,15 +169,22 @@ class CTkOptionMenu(CTkBaseClass):
self.text_label.configure(bg=ThemeManager.single_color(self.fg_color, self._appearance_mode))
def open_dropdown_menu(self):
self.dropdown_menu = DropdownMenu(x_position=self.winfo_rootx(),
y_position=self.winfo_rooty() + self.apply_widget_scaling(self._current_height + 4),
width=self._current_width,
values=self.values,
command=self.set,
fg_color=self.dropdown_color,
button_hover_color=self.dropdown_hover_color,
button_color=self.dropdown_color,
text_color=self.dropdown_text_color)
if not Settings.use_dropdown_fallback:
self.dropdown_menu = DropdownMenu(x_position=self.winfo_rootx(),
y_position=self.winfo_rooty() + self.apply_widget_scaling(self._current_height + 4),
width=self._current_width,
values=self.values,
command=self.set,
fg_color=self.dropdown_color,
button_hover_color=self.dropdown_hover_color,
button_color=self.dropdown_color,
text_color=self.dropdown_text_color)
else:
self.dropdown_menu = DropdownMenuFallback(master=self,
values=self.values,
command=self.set)
self.dropdown_menu.open(x=self.winfo_rootx(),
y=self.winfo_rooty() + self.apply_widget_scaling(self._current_height + 0))
def configure(self, *args, **kwargs):
require_redraw = False # some attribute changes require a call of self.draw() at the end

View File

@ -1,6 +1,8 @@
import customtkinter
import tkinter
import sys
from distutils.version import StrictVersion as Version
import platform
from typing import Union
from ..theme_manager import ThemeManager
@ -55,8 +57,15 @@ class DropdownMenu(tkinter.Toplevel):
self.grid_rowconfigure(0, weight=1)
if sys.platform.startswith("darwin"):
self.overrideredirect(True) # remove title-bar
self.overrideredirect(False)
if Version(platform.python_version()) < Version("3.10"):
self.focus()
self.overrideredirect(True) # remove title-bar
self.overrideredirect(False)
else:
self.overrideredirect(True)
self.geometry(f"+{round(x_position)}+{round(y_position)}")
self.focus_set()
self.wm_attributes("-transparent", True) # turn off window shadow
self.config(bg='systemTransparent') # transparent bg
self.frame = customtkinter.CTkFrame(self,
@ -74,16 +83,17 @@ class DropdownMenu(tkinter.Toplevel):
border_width=0,
width=self.width,
corner_radius=self.corner_radius,
fg_color=self.fg_color, overwrite_preferred_drawing_method="circle_shapes")
else:
fg_color=self.fg_color,
overwrite_preferred_drawing_method="circle_shapes")
else: # Linux
self.overrideredirect(True) # remove title-bar
self.configure(bg="#010302")
self.wm_attributes("-transparentcolor", "#010302")
# self.configure(bg="#010302")
# self.wm_attributes("-transparentcolor", "#010302")
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")
corner_radius=0,
fg_color=self.fg_color)
self.frame.grid(row=0, column=0, sticky="nsew", rowspan=1)
self.frame.grid_rowconfigure(len(self.values) + 1, minsize=self.apply_spacing_scaling(y_spacing)) # add spacing at the bottom
@ -108,7 +118,6 @@ class DropdownMenu(tkinter.Toplevel):
self.button_list.append(button)
self.bind("<FocusOut>", self.focus_loss_event)
self.frame.canvas.bind("<Button-1>", self.focus_loss_event)
def apply_widget_scaling(self, value: Union[int, float, str]) -> Union[float, str]:
if isinstance(value, (int, float)):

View File

@ -0,0 +1,55 @@
import tkinter
import sys
from distutils.version import StrictVersion as Version
import platform
from typing import Union
from ..theme_manager import ThemeManager
from ..appearance_mode_tracker import AppearanceModeTracker
from ..scaling_tracker import ScalingTracker
class DropdownMenuFallback(tkinter.Menu):
def __init__(self, *args,
fg_color="#555555",
button_hover_color="gray35",
text_color="default_theme",
text_font="default_theme",
command=None,
values=None,
**kwargs):
super().__init__(*args, **kwargs)
ScalingTracker.add_widget(self.set_scaling, self)
self._widget_scaling = ScalingTracker.get_widget_scaling(self)
self._spacing_scaling = ScalingTracker.get_spacing_scaling(self)
self.fg_color = fg_color
self.button_hover_color = button_hover_color
self.text_color = ThemeManager.theme["color"]["text"] if text_color == "default_theme" else text_color
self.text_font = (ThemeManager.theme["text"]["font"], ThemeManager.theme["text"]["size"]) if text_font == "default_theme" else text_font
self.menu = tkinter.Menu(master=self)
if sys.platform.startswith("win"):
self.menu.configure()
self.values = values
self.command = command
for value in self.values:
self.menu.add_command(label=value.ljust(16), command=lambda v=value: self.button_callback(v))
def open(self, x, y):
if sys.platform == "darwin":
y = y + 8
self.menu.post(x, y)
def button_callback(self, value):
if self.command is not None:
self.command(value)
def set_scaling(self, new_widget_scaling, new_spacing_scaling, new_window_scaling):
self._widget_scaling = new_widget_scaling
self._spacing_scaling = new_spacing_scaling

View File

@ -2,7 +2,7 @@
name = customtkinter
version = 4.3.0
description = Create modern looking GUIs with Python
long_description = '# CustomTkinter UI-Library\nhttps://github.com/TomSchimansky/CustomTkinter/blob/master/documentation_images/Windows_dark.png\n\nMore Information: https://github.com/TomSchimansky/CustomTkinter'
long_description = CustomTkinter UI-Library\n\n[](https://github.com/TomSchimansky/CustomTkinter/blob/master/documentation_images/Windows_dark.png)\n\nMore Information: https://github.com/TomSchimansky/CustomTkinter
long_description_content_type = text/markdown
url = https://github.com/TomSchimansky/CustomTkinter
author = Tom Schimansky

View File

@ -1,4 +1,5 @@
import tkinter
import tkinter.ttk as ttk
import customtkinter
app = customtkinter.CTk()
@ -16,14 +17,14 @@ countries = ['Bahamas', 'Canada', 'Cuba', 'United States']
variable = tkinter.StringVar()
variable.set("test")
# optionmenu_tk = tkinter.OptionMenu(app, variable, *countries, command=select_callback)
# optionmenu_tk.pack(pady=10, padx=10)
optionmenu_tk = tkinter.OptionMenu(app, variable, *countries, command=select_callback)
optionmenu_tk.pack(pady=10, padx=10)
optionmenu_1 = customtkinter.CTkOptionMenu(app, variable=variable, values=countries, command=select_callback)
optionmenu_1.pack(pady=20, padx=10)
# combobox_tk = ttk.Combobox(app, values=countries)
# combobox_tk.pack(pady=10, padx=10)
combobox_tk = ttk.Combobox(app, values=countries)
combobox_tk.pack(pady=10, padx=10)
combobox_1 = customtkinter.CTkComboBox(app, variable=variable, values=countries, command=select_callback)
combobox_1.pack(pady=20, padx=10)