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/),
|
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).
|
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
|
## [4.1.0] - 2022-05-24
|
||||||
### Added
|
### Added
|
||||||
- Configure width and height for frame, button, label, progressbar, slider, entry
|
- 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 os
|
||||||
import sys
|
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',
|
9: 'E', 8: 'F', 7: 'C', 6: 'I', 5: 'E', 4: 'G', 3: 'P', 2: 'R', 1: 'R',
|
||||||
0: 'A'}
|
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.platform.startswith("win"):
|
||||||
if sys.getwindowsversion().build > 20000: # Windows 11
|
if sys.getwindowsversion().build > 20000: # Windows 11
|
||||||
cls.radius_to_char_fine = radius_to_char_fine_windows_11
|
cls.radius_to_char_fine = radius_to_char_fine_windows_11
|
||||||
else: # < Windows 11
|
else: # < Windows 11
|
||||||
cls.radius_to_char_fine = radius_to_char_fine_windows_10
|
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
|
cls.radius_to_char_fine = radius_to_char_fine_windows_10
|
||||||
|
|
||||||
def get_char_from_radius(self, radius: int) -> str:
|
def get_char_from_radius(self, radius: int) -> str:
|
||||||
|
@ -2,7 +2,6 @@ import tkinter
|
|||||||
import sys
|
import sys
|
||||||
from typing import Union
|
from typing import Union
|
||||||
|
|
||||||
from .dropdown_menu_old import DropdownMenu
|
|
||||||
from .dropdown_menu import DropdownMenu
|
from .dropdown_menu import DropdownMenu
|
||||||
|
|
||||||
from .ctk_canvas import CTkCanvas
|
from .ctk_canvas import CTkCanvas
|
||||||
@ -162,15 +161,15 @@ class CTkComboBox(CTkBaseClass):
|
|||||||
outline=ThemeManager.single_color(self.border_color, self._appearance_mode),
|
outline=ThemeManager.single_color(self.border_color, self._appearance_mode),
|
||||||
fill=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:
|
if self.state == tkinter.DISABLED:
|
||||||
self.entry.configure(fg=(ThemeManager.single_color(self.text_color_disabled, self._appearance_mode)))
|
|
||||||
self.canvas.itemconfig("dropdown_arrow",
|
self.canvas.itemconfig("dropdown_arrow",
|
||||||
fill=ThemeManager.single_color(self.text_color_disabled, self._appearance_mode))
|
fill=ThemeManager.single_color(self.text_color_disabled, self._appearance_mode))
|
||||||
else:
|
else:
|
||||||
self.entry.configure(fg=ThemeManager.single_color(self.text_color, self._appearance_mode))
|
|
||||||
self.canvas.itemconfig("dropdown_arrow",
|
self.canvas.itemconfig("dropdown_arrow",
|
||||||
fill=ThemeManager.single_color(self.text_color, self._appearance_mode))
|
fill=ThemeManager.single_color(self.text_color, self._appearance_mode))
|
||||||
|
|
||||||
|
@ -2,7 +2,6 @@ import tkinter
|
|||||||
import sys
|
import sys
|
||||||
from typing import Union
|
from typing import Union
|
||||||
|
|
||||||
from .dropdown_menu_old import DropdownMenu
|
|
||||||
from .dropdown_menu import DropdownMenu
|
from .dropdown_menu import DropdownMenu
|
||||||
|
|
||||||
from .ctk_canvas import CTkCanvas
|
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_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.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":
|
if sys.platform == "darwin":
|
||||||
self.configure(tearoff=False,
|
self.configure(tearoff=False,
|
||||||
font=self.apply_font_scaling(self.text_font))
|
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),
|
activeforeground=ThemeManager.single_color(self.text_color, self._appearance_mode),
|
||||||
font=self.apply_font_scaling(self.text_font))
|
font=self.apply_font_scaling(self.text_font))
|
||||||
|
|
||||||
self.values = values
|
|
||||||
self.command = command
|
|
||||||
|
|
||||||
self.add_menu_commands()
|
|
||||||
|
|
||||||
def add_menu_commands(self):
|
def add_menu_commands(self):
|
||||||
for value in self.values:
|
if sys.platform.startswith("linux"):
|
||||||
self.add_command(label=value.ljust(self.min_character_width),
|
for value in self.values:
|
||||||
command=lambda v=value: self.button_callback(v),
|
self.add_command(label=" " + value.ljust(self.min_character_width) + " ",
|
||||||
compound="left")
|
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]):
|
def open(self, x: Union[int, float], y: Union[int, float]):
|
||||||
if sys.platform == "darwin":
|
if sys.platform == "darwin":
|
||||||
@ -78,7 +87,10 @@ class DropdownMenu(tkinter.Menu):
|
|||||||
else:
|
else:
|
||||||
y += self.apply_widget_scaling(3)
|
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):
|
def button_callback(self, value):
|
||||||
if self.command is not None:
|
if self.command is not None:
|
||||||
@ -157,3 +169,5 @@ class DropdownMenu(tkinter.Menu):
|
|||||||
self._appearance_mode = 1
|
self._appearance_mode = 1
|
||||||
elif mode_string.lower() == "light":
|
elif mode_string.lower() == "light":
|
||||||
self._appearance_mode = 0
|
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,
|
self.button_5 = customtkinter.CTkButton(master=self.frame_right,
|
||||||
text="CTkButton",
|
text="CTkButton",
|
||||||
border_width=3, # <- custom border_width
|
border_width=2, # <- custom border_width
|
||||||
fg_color=None, # <- no fg_color
|
fg_color=None, # <- no fg_color
|
||||||
command=self.button_event)
|
command=self.button_event)
|
||||||
self.button_5.grid(row=8, column=2, columnspan=1, pady=20, padx=20, sticky="we")
|
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"
|
github_url = "https://github.com/TomSchimansky/CustomTkinter"
|
||||||
|
|
||||||
[tool.tbump.version]
|
[tool.tbump.version]
|
||||||
current = "4.4.0"
|
current = "4.4.1"
|
||||||
|
|
||||||
# Example of a semver regexp.
|
# Example of a semver regexp.
|
||||||
# Make sure this matches current_version before
|
# Make sure this matches current_version before
|
||||||
|
@ -1,6 +1,6 @@
|
|||||||
[metadata]
|
[metadata]
|
||||||
name = customtkinter
|
name = customtkinter
|
||||||
version = 4.4.0
|
version = 4.4.1
|
||||||
description = Create modern looking GUIs with Python
|
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 = 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
|
long_description_content_type = text/markdown
|
||||||
|
Reference in New Issue
Block a user