Исходный код EJIO.ctk_extender.widget.form.fields.directory
## /ctk_extender/widget/form/fields/directory.py
import customtkinter as ctk
from tkinter import filedialog
from typing import Any
from .base import InputField
from ...container import WidgetContainer
from ...components import Label
from ...geometry import GridStrategy
__all__ = ['FormDirectoryField']
[документация]
class FormDirectoryField(WidgetContainer, InputField):
"""Поле формы для выбора директорий с поддержкой валидации и ограничений."""
__slots__ = ('_name', '_label_text', '_file_types', '_multiple', '_required', '_value', '_entry', '_btn')
def __init__(
self,
parent: Any,
name: str,
label_text: str,
required: bool = False,
geometry: Any = None,
**kwargs: Any
) -> None:
self._name: str = name
self._label_text: str = label_text
self._required: bool = required
self._value: str = ""
self._entry: ctk.CTkEntry | None = None
self._btn: ctk.CTkButton | None = None
super().__init__(parent, geometry, **kwargs)
[документация]
def build(self) -> ctk.CTkFrame:
frame = super().build()
frame.configure(fg_color="transparent")
# 1. Текстовая подпись
self.add_widget(Label, text=self._label_text, geometry=GridStrategy(row=0, column=0, sticky="w", padx=(0, 10)))
# Контейнер для инпута и кнопки
row_frame = ctk.CTkFrame(frame, fg_color="transparent")
row_frame.grid(row=0, column=1, sticky="ew")
frame.grid_columnconfigure(1, weight=1)
# 2. Неизменяемое поле вывода пути
self._entry = ctk.CTkEntry(row_frame, font=("Consolas", 11), state="disabled")
self._entry.pack(side="left", fill="x", expand=True, padx=(0, 5))
# 3. Кнопка вызова проводника
self._btn = ctk.CTkButton(row_frame, text="📁", width=36, height=28, command=self._browse)
self._btn.pack(side="right")
return frame
def _browse(self) -> None:
master = self.ctk_instance.winfo_toplevel()
path = filedialog.askdirectory(title=self._label_text, master=master) #TODO: посмотреть изменения
if path:
self._value = path
self._update_ui(path)
def _update_ui(self, text: str) -> None:
if self._entry:
self._entry.configure(state="normal")
self._entry.delete(0, "end")
self._entry.insert(0, text)
self._entry.configure(state="disabled")
@property
def name(self) -> str: return self._name
[документация]
def clear(self) -> None:
self._value = "" if not self._multiple else []
self._update_ui("")
[документация]
def validate(self) -> str | None:
if self._required and not self._value:
return f"Field '{self._label_text}' required to fill out."
return None