CustomTkinter/customtkinter/windows/ctk_input_dialog.py
2023-08-10 18:40:04 +02:00

122 lines
6.0 KiB
Python

from typing import Union, Tuple, Optional
from .widgets import CTkLabel
from .widgets import CTkEntry
from .widgets import CTkButton
from .widgets import CTkComboBox
from .widgets.theme import ThemeManager
from .ctk_toplevel import CTkToplevel
class CTkInputDialog(CTkToplevel):
"""
Dialog with extra window, message, entry widget, cancel and ok button.
For detailed information check out the documentation.
"""
def __init__(self,
fg_color: Optional[Union[str, Tuple[str, str]]] = None,
text_color: Optional[Union[str, Tuple[str, str]]] = None,
button_fg_color: Optional[Union[str, Tuple[str, str]]] = None,
button_hover_color: Optional[Union[str, Tuple[str, str]]] = None,
button_text_color: Optional[Union[str, Tuple[str, str]]] = None,
entry_fg_color: Optional[Union[str, Tuple[str, str]]] = None,
entry_border_color: Optional[Union[str, Tuple[str, str]]] = None,
entry_text_color: Optional[Union[str, Tuple[str, str]]] = None,
values: Optional[Union[str, list[str]]] = None,
title: str = "CTkDialog",
text: str = "CTkDialog"):
super().__init__(fg_color=fg_color)
self._fg_color = ThemeManager.theme["CTkToplevel"]["fg_color"] if fg_color is None else self._check_color_type(fg_color)
self._text_color = ThemeManager.theme["CTkLabel"]["text_color"] if text_color is None else self._check_color_type(button_hover_color)
self._button_fg_color = ThemeManager.theme["CTkButton"]["fg_color"] if button_fg_color is None else self._check_color_type(button_fg_color)
self._button_hover_color = ThemeManager.theme["CTkButton"]["hover_color"] if button_hover_color is None else self._check_color_type(button_hover_color)
self._button_text_color = ThemeManager.theme["CTkButton"]["text_color"] if button_text_color is None else self._check_color_type(button_text_color)
self._entry_fg_color = ThemeManager.theme["CTkEntry"]["fg_color"] if entry_fg_color is None else self._check_color_type(entry_fg_color)
self._entry_border_color = ThemeManager.theme["CTkEntry"]["border_color"] if entry_border_color is None else self._check_color_type(entry_border_color)
self._entry_text_color = ThemeManager.theme["CTkEntry"]["text_color"] if entry_text_color is None else self._check_color_type(entry_text_color)
self._user_input: Union[str, None] = None
self._running: bool = False
self._text = text
self._values = values
self.title(title)
self.lift() # lift window on top
self.attributes("-topmost", True) # stay on top
self.protocol("WM_DELETE_WINDOW", self._on_closing)
self.after(10, self._create_widgets) # create widgets with slight delay, to avoid white flickering of background
self.resizable(False, False)
self.grab_set() # make other windows not clickable
def _create_widgets(self):
self.grid_columnconfigure((0, 1), weight=1)
self.rowconfigure(0, weight=1)
self._label = CTkLabel(master=self,
width=300,
wraplength=300,
fg_color="transparent",
text_color=self._text_color,
text=self._text,)
self._label.grid(row=0, column=0, columnspan=2, padx=20, pady=20, sticky="ew")
if self._values is not None:
self._entry = CTkComboBox(master=self,
width=230,
fg_color=self._entry_fg_color,
border_color=self._entry_border_color,
text_color=self._entry_text_color,
values=self._values)
else:
self._entry = CTkEntry(master=self,
width=230,
fg_color=self._entry_fg_color,
border_color=self._entry_border_color,
text_color=self._entry_text_color)
self._entry.grid(row=1, column=0, columnspan=2, padx=20, pady=(0, 20), sticky="ew")
self._ok_button = CTkButton(master=self,
width=100,
border_width=0,
fg_color=self._button_fg_color,
hover_color=self._button_hover_color,
text_color=self._button_text_color,
text='Ok',
command=self._ok_event)
self._ok_button.grid(row=2, column=0, columnspan=1, padx=(20, 10), pady=(0, 20), sticky="ew")
self._cancel_button = CTkButton(master=self,
width=100,
border_width=0,
fg_color=self._button_fg_color,
hover_color=self._button_hover_color,
text_color=self._button_text_color,
text='Cancel',
command=self._cancel_event)
self._cancel_button.grid(row=2, column=1, columnspan=1, padx=(10, 20), pady=(0, 20), sticky="ew")
self.after(150, lambda: self._entry.focus()) # set focus to entry with slight delay, otherwise it won't work
self._entry.bind("<Return>", self._ok_event)
def _ok_event(self, event=None):
self._user_input = self._entry.get()
self.grab_release()
self.destroy()
def _on_closing(self):
self.grab_release()
self.destroy()
def _cancel_event(self):
self.grab_release()
self.destroy()
def get_input(self):
self.master.wait_window(self)
return self._user_input