mirror of
https://github.com/TomSchimansky/CustomTkinter.git
synced 2023-08-10 21:13:13 +03:00
Compare commits
7 Commits
Author | SHA1 | Date | |
---|---|---|---|
22b4dfb2d3 | |||
9146e02718 | |||
3b259e4d01 | |||
7a99aa318c | |||
9ff6cc8268 | |||
3a1d12f8ea | |||
45e47f5970 |
14
CHANGELOG.md
14
CHANGELOG.md
@ -4,6 +4,20 @@ All notable changes to this project will be documented in this file.
|
||||
The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/),
|
||||
and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).
|
||||
|
||||
## [4.4.0] - 2022-06-14
|
||||
### Changed
|
||||
- Changed custom dropdown menu to normal tkinter.Menu because of multiple platform specific bugs
|
||||
|
||||
## [4.3.0] - 2022-06-1
|
||||
### Added
|
||||
- Added CTkComboBox
|
||||
- Small fixes for new dropdown menu
|
||||
|
||||
## [4.2.0] - 2022-05-30
|
||||
### Added
|
||||
- CTkOptionMenu with custom dropdown menu
|
||||
- Support for clicking on labels of CTkCheckBox, CTkRadioButton, CTkSwitch
|
||||
|
||||
## [4.1.0] - 2022-05-24
|
||||
### Added
|
||||
- Configure width and height for frame, button, label, progressbar, slider, entry
|
||||
|
@ -1,4 +1,4 @@
|
||||
__version__ = "4.4.0"
|
||||
__version__ = "4.4.1"
|
||||
|
||||
import os
|
||||
import sys
|
||||
|
@ -29,12 +29,19 @@ class CTkCanvas(tkinter.Canvas):
|
||||
9: 'E', 8: 'F', 7: 'C', 6: 'I', 5: 'E', 4: 'G', 3: 'P', 2: 'R', 1: 'R',
|
||||
0: 'A'}
|
||||
|
||||
radius_to_char_fine_linux = {19: 'A', 18: 'A', 17: 'B', 16: 'B', 15: 'B', 14: 'B', 13: 'F', 12: 'C',
|
||||
11: 'F', 10: 'C',
|
||||
9: 'D', 8: 'G', 7: 'D', 6: 'F', 5: 'D', 4: 'G', 3: 'M', 2: 'H', 1: 'H',
|
||||
0: 'A'}
|
||||
|
||||
if sys.platform.startswith("win"):
|
||||
if sys.getwindowsversion().build > 20000: # Windows 11
|
||||
cls.radius_to_char_fine = radius_to_char_fine_windows_11
|
||||
else: # < Windows 11
|
||||
cls.radius_to_char_fine = radius_to_char_fine_windows_10
|
||||
else: # macOS and Linux
|
||||
elif sys.platform.startswith("linux"): # Optimized on Kali Linux
|
||||
cls.radius_to_char_fine = radius_to_char_fine_linux
|
||||
else:
|
||||
cls.radius_to_char_fine = radius_to_char_fine_windows_10
|
||||
|
||||
def get_char_from_radius(self, radius: int) -> str:
|
||||
|
@ -2,7 +2,6 @@ import tkinter
|
||||
import sys
|
||||
from typing import Union
|
||||
|
||||
from .dropdown_menu_old import DropdownMenu
|
||||
from .dropdown_menu import DropdownMenu
|
||||
|
||||
from .ctk_canvas import CTkCanvas
|
||||
@ -162,15 +161,15 @@ class CTkComboBox(CTkBaseClass):
|
||||
outline=ThemeManager.single_color(self.border_color, self._appearance_mode),
|
||||
fill=ThemeManager.single_color(self.border_color, self._appearance_mode))
|
||||
|
||||
self.entry.configure(fg=ThemeManager.single_color(self.text_color, self._appearance_mode))
|
||||
self.entry.configure(bg=ThemeManager.single_color(self.fg_color, self._appearance_mode))
|
||||
self.entry.configure(bg=ThemeManager.single_color(self.fg_color, self._appearance_mode),
|
||||
fg=ThemeManager.single_color(self.text_color, self._appearance_mode),
|
||||
disabledforeground=ThemeManager.single_color(self.text_color_disabled, self._appearance_mode),
|
||||
disabledbackground=ThemeManager.single_color(self.fg_color, self._appearance_mode))
|
||||
|
||||
if self.state == tkinter.DISABLED:
|
||||
self.entry.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:
|
||||
self.entry.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))
|
||||
|
||||
|
@ -2,7 +2,6 @@ import tkinter
|
||||
import sys
|
||||
from typing import Union
|
||||
|
||||
from .dropdown_menu_old import DropdownMenu
|
||||
from .dropdown_menu import DropdownMenu
|
||||
|
||||
from .ctk_canvas import CTkCanvas
|
||||
|
@ -34,6 +34,14 @@ class DropdownMenu(tkinter.Menu):
|
||||
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.configure_menu_for_platforms()
|
||||
|
||||
self.values = values
|
||||
self.command = command
|
||||
|
||||
self.add_menu_commands()
|
||||
|
||||
def configure_menu_for_platforms(self):
|
||||
if sys.platform == "darwin":
|
||||
self.configure(tearoff=False,
|
||||
font=self.apply_font_scaling(self.text_font))
|
||||
@ -61,16 +69,17 @@ class DropdownMenu(tkinter.Menu):
|
||||
activeforeground=ThemeManager.single_color(self.text_color, self._appearance_mode),
|
||||
font=self.apply_font_scaling(self.text_font))
|
||||
|
||||
self.values = values
|
||||
self.command = command
|
||||
|
||||
self.add_menu_commands()
|
||||
|
||||
def add_menu_commands(self):
|
||||
for value in self.values:
|
||||
self.add_command(label=value.ljust(self.min_character_width),
|
||||
command=lambda v=value: self.button_callback(v),
|
||||
compound="left")
|
||||
if sys.platform.startswith("linux"):
|
||||
for value in self.values:
|
||||
self.add_command(label=" " + value.ljust(self.min_character_width) + " ",
|
||||
command=lambda v=value: self.button_callback(v),
|
||||
compound="left")
|
||||
else:
|
||||
for value in self.values:
|
||||
self.add_command(label=value.ljust(self.min_character_width),
|
||||
command=lambda v=value: self.button_callback(v),
|
||||
compound="left")
|
||||
|
||||
def open(self, x: Union[int, float], y: Union[int, float]):
|
||||
if sys.platform == "darwin":
|
||||
@ -78,7 +87,10 @@ class DropdownMenu(tkinter.Menu):
|
||||
else:
|
||||
y += self.apply_widget_scaling(3)
|
||||
|
||||
self.post(int(x), int(y))
|
||||
if sys.platform == "darwin" or sys.platform.startswith("win"):
|
||||
self.post(int(x), int(y))
|
||||
else: # Linux
|
||||
self.tk_popup(int(x), int(y))
|
||||
|
||||
def button_callback(self, value):
|
||||
if self.command is not None:
|
||||
@ -157,3 +169,5 @@ class DropdownMenu(tkinter.Menu):
|
||||
self._appearance_mode = 1
|
||||
elif mode_string.lower() == "light":
|
||||
self._appearance_mode = 0
|
||||
|
||||
self.configure_menu_for_platforms()
|
||||
|
@ -1,149 +0,0 @@
|
||||
import customtkinter
|
||||
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 DropdownMenu(tkinter.Toplevel):
|
||||
def __init__(self, *args,
|
||||
fg_color="#555555",
|
||||
button_color="gray50",
|
||||
button_hover_color="gray35",
|
||||
text_color="black",
|
||||
corner_radius=6,
|
||||
button_corner_radius=3,
|
||||
width=120,
|
||||
button_height=24,
|
||||
x_position=0,
|
||||
y_position=0,
|
||||
x_spacing=3,
|
||||
y_spacing=3,
|
||||
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.values = values
|
||||
self.command = command
|
||||
|
||||
# color
|
||||
self.appearance_mode = AppearanceModeTracker.get_mode() # 0: "Light" 1: "Dark"
|
||||
self.fg_color = fg_color
|
||||
self.button_color = button_color
|
||||
self.button_hover_color = button_hover_color
|
||||
self.text_color = text_color
|
||||
|
||||
# shape
|
||||
self.corner_radius = corner_radius
|
||||
self.button_corner_radius = button_corner_radius
|
||||
self.button_height = button_height
|
||||
self.width = width
|
||||
self.height = max(len(self.values), 1) * (self.button_height + self.apply_spacing_scaling(y_spacing)) + self.apply_spacing_scaling(y_spacing)
|
||||
|
||||
self.geometry(f"{round(self.apply_widget_scaling(self.width))}x" +
|
||||
f"{round(self.apply_widget_scaling(self.height))}+" +
|
||||
f"{round(x_position)}+{round(y_position)}")
|
||||
self.grid_columnconfigure(0, weight=1)
|
||||
self.grid_rowconfigure(0, weight=1)
|
||||
|
||||
if sys.platform.startswith("darwin"):
|
||||
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,
|
||||
border_width=0,
|
||||
width=self.width,
|
||||
corner_radius=self.corner_radius,
|
||||
fg_color=ThemeManager.single_color(self.fg_color, self.appearance_mode))
|
||||
|
||||
elif sys.platform.startswith("win"):
|
||||
self.overrideredirect(True) # remove title-bar
|
||||
#self.configure(bg="#010302")
|
||||
#self.wm_attributes("-transparent", "#010302")
|
||||
self.focus()
|
||||
self.focus()
|
||||
self.frame = customtkinter.CTkFrame(self,
|
||||
border_width=0,
|
||||
width=self.width,
|
||||
corner_radius=0,
|
||||
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.frame = customtkinter.CTkFrame(self,
|
||||
border_width=0,
|
||||
width=self.width,
|
||||
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
|
||||
self.frame.grid_columnconfigure(0, weight=1)
|
||||
|
||||
self.button_list = []
|
||||
for index, option in enumerate(self.values):
|
||||
button = customtkinter.CTkButton(self.frame,
|
||||
text=option,
|
||||
height=self.button_height,
|
||||
width=self.width - 2 * self.apply_widget_scaling(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))
|
||||
button.text_label.configure(anchor="w")
|
||||
button.text_label.grid(row=0, column=0, rowspan=2, columnspan=2, sticky="w")
|
||||
button.grid(row=index, column=0,
|
||||
padx=self.apply_widget_scaling(x_spacing),
|
||||
pady=(self.apply_widget_scaling(y_spacing), 0), sticky="ew")
|
||||
self.button_list.append(button)
|
||||
|
||||
self.bind("<FocusOut>", self.focus_loss_event)
|
||||
|
||||
def apply_widget_scaling(self, value: Union[int, float, str]) -> Union[float, str]:
|
||||
if isinstance(value, (int, float)):
|
||||
return value * self._widget_scaling
|
||||
else:
|
||||
return value
|
||||
|
||||
def apply_spacing_scaling(self, value: Union[int, float, str]) -> Union[float, str]:
|
||||
if isinstance(value, (int, float)):
|
||||
return value * self._spacing_scaling
|
||||
else:
|
||||
return value
|
||||
|
||||
def set_scaling(self, new_widget_scaling, new_spacing_scaling, new_window_scaling):
|
||||
return
|
||||
|
||||
def focus_loss_event(self, event):
|
||||
self.destroy()
|
||||
if sys.platform.startswith("darwin"):
|
||||
self.update()
|
||||
|
||||
def button_callback(self, index):
|
||||
self.destroy()
|
||||
if sys.platform.startswith("darwin"):
|
||||
self.update()
|
||||
|
||||
if self.command is not None:
|
||||
self.command(self.values[index])
|
@ -158,7 +158,7 @@ class App(customtkinter.CTk):
|
||||
|
||||
self.button_5 = customtkinter.CTkButton(master=self.frame_right,
|
||||
text="CTkButton",
|
||||
border_width=3, # <- custom border_width
|
||||
border_width=2, # <- custom border_width
|
||||
fg_color=None, # <- no fg_color
|
||||
command=self.button_event)
|
||||
self.button_5.grid(row=8, column=2, columnspan=1, pady=20, padx=20, sticky="we")
|
||||
|
@ -7,7 +7,7 @@ build-backend = "setuptools.build_meta"
|
||||
github_url = "https://github.com/TomSchimansky/CustomTkinter"
|
||||
|
||||
[tool.tbump.version]
|
||||
current = "4.4.0"
|
||||
current = "4.4.1"
|
||||
|
||||
# Example of a semver regexp.
|
||||
# Make sure this matches current_version before
|
||||
|
@ -1,6 +1,6 @@
|
||||
[metadata]
|
||||
name = customtkinter
|
||||
version = 4.4.0
|
||||
version = 4.4.1
|
||||
description = Create modern looking GUIs with Python
|
||||
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
|
||||
|
Reference in New Issue
Block a user