# `tkinter` — Python interface to Tcl/Tk

Вихідний код: Lib/tkinter/__init__.py

Пакет `tkinter` («інтерфейс Tk») є стандартним інтерфейсом Python до інструментарію GUI Tcl/Tk. І Tk, і `tkinter` доступні на більшості платформ Unix, включаючи macOS, а також у системах Windows.

Запуск `python -m tkinter` з командного рядка має відкрити вікно, яке демонструє простий інтерфейс Tk, повідомляючи, що `tkinter` правильно встановлено у вашій системі, а також показує, яка версія Tcl/Tk встановлено, тому ви можете прочитати документацію Tcl/Tk, що стосується цієї версії.

Tkinter підтримує низку версій Tcl/Tk, створених із підтримкою потоків або без неї. Офіційний двійковий випуск Python включає в себе Tcl/Tk 8.6. Перегляньте вихідний код для модуля `_tkinter`, щоб дізнатися більше про підтримувані версії.

Tkinter не є тонкою обгорткою, але додає достатню кількість власної логіки, щоб зробити досвід більш пітонічним. Ця документація зосереджуватиметься на цих доповненнях і змінах, а подробиці, які не змінилися, див. в офіційній документації Tcl/Tk.

Примітка

Tcl/Tk 8.5 (2007) представив сучасний набір тематичних компонентів інтерфейсу користувача разом із новим API для їх використання. І старі, і нові API все ще доступні. Більшість документації, яку ви знайдете в Інтернеті, все ще використовує старий API і може бути дуже застарілим.

Дивись також

- TkDocs

    Розширений підручник зі створення інтерфейсів користувача за допомогою Tkinter. Пояснює ключові концепції та ілюструє рекомендовані підходи за допомогою сучасного API.

- Довідник Tkinter 8.5: графічний інтерфейс для Python

    Довідкова документація для Tkinter 8.5 із детальним описом доступних класів, методів і параметрів.

Ресурси Tcl/Tk:

- Tk команди

    Вичерпне посилання на кожну з базових команд Tcl/Tk, що використовуються Tkinter.

- Домашня сторінка Tcl/Tk

    Додаткова документація та посилання на розробку ядра Tcl/Tk.

Книги:

- Сучасний Tkinter для зайнятих розробників Python

    Автор: Марк Розман. (ISBN 978-1999149567)

- Python GUI programming with Tkinter

    By Alan D. Moore. (ISBN 978-1788835886)

- Programming Python

    Марк Лутц; має чудове покриття Tkinter. (ISBN 978-0596158101)

- Tcl і Tk Toolkit (2-е видання)

    Джон Остерхаут, винахідник Tcl/Tk, і Кен Джонс; не охоплює Tkinter. (ISBN 978-0321336330)

## Архітектура

Tcl/Tk не є окремою бібліотекою, а складається з кількох окремих модулів, кожен з яких має окремі функції та власну офіційну документацію. Двійкові випуски Python також постачають додатковий модуль разом із ним.

Tcl

  Tcl — це динамічна інтерпретована мова програмування, як і Python. Хоча його можна використовувати самостійно як мову програмування загального призначення, найчастіше його вбудовують у додатки C як механізм сценаріїв або інтерфейс до набору інструментів Tk. Бібліотека Tcl має інтерфейс C для створення та керування одним або декількома екземплярами інтерпретатора Tcl, запуску команд і сценаріїв Tcl у цих екземплярах і додавання спеціальних команд, реалізованих у Tcl або C. Кожен інтерпретатор має чергу подій, а також є засоби для надсилання до нього подій та їх обробки. На відміну від Python, модель виконання Tcl розроблена навколо кооперативної багатозадачності, і Tkinter усуває цю різницю (докладніше див. Модель потоків).

Тк

  Tk is a Tcl package implemented in C that adds custom commands to create and manipulate GUI widgets. Each `Tk` object embeds its own Tcl interpreter instance with Tk loaded into it. Tk’s widgets are very customizable, though at the cost of a dated appearance. Tk uses Tcl’s event queue to generate and process GUI events.

Ттк

  Тематичний Tk (Ttk) — це новіша сімейство віджетів Tk, які забезпечують набагато кращий вигляд на різних платформах, ніж багато класичних віджетів Tk. Ttk поширюється як частина Tk, починаючи з Tk версії 8.5. Прив’язки Python надаються в окремому модулі, `tkinter.ttk`.

Внутрішньо Tk і Ttk використовують засоби базової операційної системи, тобто Xlib на Unix/X11, Cocoa на macOS, GDI на Windows.

Коли ваша програма Python використовує клас у Tkinter, наприклад, для створення віджета, модуль `tkinter` спочатку збирає рядок команди Tcl/Tk. Він передає цей командний рядок Tcl до внутрішнього двійкового модуля `_tkinter`, який потім викликає інтерпретатор Tcl для його оцінки. Потім інтерпретатор Tcl звернеться до пакетів Tk та/або Ttk, які, у свою чергу, звернуться до Xlib, Cocoa або GDI.

## Модулі Tkinter

Підтримка Tkinter розподілена на кілька модулів. Для більшості програм знадобиться головний модуль `tkinter`, а також модуль `tkinter.ttk`, який надає сучасний тематичний набір віджетів і API:

    from tkinter import *
    from tkinter import ttk

class tkinter.Tk(screenName=None, baseName=None, className='Tk', useTk=True, sync=False, use=None)

  Створіть віджет Tk верхнього рівня, який зазвичай є головним вікном програми, та ініціалізуйте інтерпретатор Tcl для цього віджета. Кожен екземпляр має власний асоційований інтерпретатор Tcl.

  Клас `Tk` зазвичай створюється з використанням усіх значень за замовчуванням. Однак наразі розпізнаються такі аргументи ключових слів:

  screenName

    Якщо задано (у вигляді рядка), установлює змінну середовища `DISPLAY`. (лише X11)

  базова назва

    Ім’я файлу профілю. За замовчуванням baseName походить від назви програми (`sys.argv[0]`).

  назва класу

    Назва класу віджетів. Використовується як файл профілю, а також як ім’я, з яким викликається Tcl (argv0 у interp).

  useTk

    Якщо `True`, ініціалізувати підсистему Tk. Функція `tkinter.Tcl()` встановлює значення `False`.

  синхронізація

    Якщо `True`, виконувати всі команди X-сервера синхронно, щоб повідомляти про помилки негайно. Можна використовувати для налагодження. (лише X11)

  використання

    Визначає id вікна, у яке потрібно вставити програму, замість того, щоб воно створювалося як незалежне вікно верхнього рівня. id потрібно вказати так само, як значення параметра -use для віджетів верхнього рівня (тобто воно має форму, подібну до тієї, яку повертає `winfo_id()`).

    Зауважте, що на деяких платформах це працюватиме належним чином, лише якщо id посилається на фрейм Tk або верхній рівень, для якого ввімкнено параметр -container.

  `Tk` reads and interprets profile files, named `.className.tcl` and `.baseName.tcl`, into the Tcl interpreter and calls `exec()` on the contents of `.className.py` and `.baseName.py`. The path for the profile files is the `HOME` environment variable or, if that isn’t defined, then `os.curdir`.

  tk

    Об’єкт програми Tk, створений шляхом створення екземпляра `Tk`. Це забезпечує доступ до інтерпретатора Tcl. Кожен віджет, до якого приєднано той самий екземпляр `Tk`, має однакове значення для свого атрибута `tk`.

  master

    Об’єкт віджета, який містить цей віджет. Для `Tk`, master є `None`, оскільки це головне вікно. Терміни master і parent подібні та іноді використовуються як взаємозамінні назви аргументів; однак виклик `winfo_parent()` повертає рядок назви віджета, тоді як `master` повертає об’єкт. parent/child відображає деревоподібний зв’язок, тоді як master/slave відображає структуру контейнера.

  children

    Безпосередні нащадки цього віджета як `dict` з іменами дочірніх віджетів як ключі та дочірні об’єкти екземплярів як значення.

tkinter.Tcl(screenName=None, baseName=None, className='Tk', useTk=False)

  Функція `Tcl()` є фабричною функцією, яка створює об’єкт, подібний до створеного класом `Tk`, за винятком того, що вона не ініціалізує підсистему Tk. Це найчастіше корисно, коли керуєте інтерпретатором Tcl у середовищі, де не потрібно створювати сторонні вікна верхнього рівня або де це неможливо (наприклад, системи Unix/Linux без X-сервера). Для об’єкта, створеного об’єктом `Tcl()`, можна створити вікно верхнього рівня (та ініціалізувати підсистему Tk), викликавши його метод `loadtk()`.

Модулі, які забезпечують підтримку Tk, включають:

`tkinter`

  Головний модуль Tkinter.

`tkinter.colorchooser`

  Діалогове вікно, у якому користувач може вибрати колір.

`tkinter.commondialog`

  Базовий клас для діалогових вікон, визначених в інших модулях, перелічених тут.

`tkinter.filedialog`

  Загальні діалоги, які дозволяють користувачеві вказати файл для відкриття або збереження.

`tkinter.font`

  Утиліти для допомоги в роботі зі шрифтами.

`tkinter.messagebox`

  Доступ до стандартних діалогових вікон Tk.

`tkinter.scrolledtext`

  Текстовий віджет із вбудованою вертикальною смугою прокручування.

`tkinter.simpledialog`

  Основні діалоги та функції зручності.

`tkinter.ttk`

  Тематичний набір віджетів, представлений у Tk 8.5, надає сучасні альтернативи для багатьох класичних віджетів у головному модулі `tkinter`.

Додаткові модулі:

`_tkinter`

  Двійковий модуль, який містить низькорівневий інтерфейс для Tcl/Tk. Він автоматично імпортується головним модулем `tkinter` і ніколи не повинен використовуватися безпосередньо програмістами додатків. Зазвичай це спільна бібліотека (або DLL), але в деяких випадках може бути статично пов’язана з інтерпретатором Python.

`idlelib`

  Інтегроване середовище розробки та навчання Python (IDLE). На основі `tkinter`.

`tkinter.constants`

  Символічні константи, які можна використовувати замість рядків під час передачі різних параметрів викликам Tkinter. Автоматично імпортується основним модулем `tkinter`.

`tkinter.dnd`

  (експериментальний) Підтримка перетягування для `tkinter`. Це стане застарілим, коли його буде замінено на Tk DND.

`turtle`

  Графіка Turtle у вікні Tk.

## Tkinter Life Preserver

Цей розділ не призначений для вичерпного підручника з Tk або Tkinter. Для цього зверніться до одного із зовнішніх ресурсів, згаданих раніше. Натомість цей розділ надає дуже швидку орієнтацію щодо того, як виглядає програма Tkinter, визначає основні концепції Tk і пояснює, як структурована оболонка Tkinter.

Решта цього розділу допоможе вам визначити класи, методи та параметри, які вам знадобляться у вашій програмі Tkinter, і де знайти більш детальну документацію щодо них, у тому числі в офіційному довідковому посібнику Tcl/Tk.

### Програма «Привіт, світ».

Ми почнемо з огляду програми «Hello World» у Tkinter. Це не найменше, що ми можемо написати, але достатньо, щоб проілюструвати деякі ключові поняття, які вам потрібно знати.

    from tkinter import *
    from tkinter import ttk
    root = Tk()
    frm = ttk.Frame(root, padding=10)
    frm.grid()
    ttk.Label(frm, text="Hello World!").grid(column=0, row=0)
    ttk.Button(frm, text="Quit", command=root.destroy).grid(column=1, row=0)
    root.mainloop()

Після імпорту в наступному рядку створюється екземпляр класу `Tk`, який ініціалізує Tk і створює пов’язаний з ним інтерпретатор Tcl. Він також створює вікно верхнього рівня, відоме як кореневе вікно, яке служить головним вікном програми.

Наступний рядок створює рамковий віджет, який у цьому випадку міститиме мітку та кнопку, яку ми створимо далі. Рама встановлюється всередині вікна.

Наступний рядок створює віджет мітки, що містить статичний текстовий рядок. Метод `grid()` використовується для вказівки відносного розташування (положення) мітки всередині віджета кадру, що містить її, подібно до того, як працюють таблиці в HTML.

Потім створюється віджет кнопки, який розміщується праворуч від мітки. При натисканні викличе метод `destroy()` кореневого вікна.

Нарешті, метод `mainloop()` виводить все на дисплей і реагує на введення користувача, доки програма не завершить роботу.

### Важливі поняття Tk

Навіть ця проста програма ілюструє такі ключові концепції Tk:

віджети

  Інтерфейс користувача Tkinter складається з окремих віджетів. Кожен віджет представлено як об’єкт Python, створений із таких класів, як `ttk.Frame`, `ttk.Label` і `ttk.Button`.

ієрархія віджетів

  Віджети впорядковані в ієрархію. Мітка та кнопка містилися у фреймі, який, у свою чергу, містився в кореневому вікні. Під час створення кожного дочірнього віджета його батьківський віджет передається як перший аргумент конструктору віджетів.

параметри конфігурації

  Віджети мають параметри конфігурації, які змінюють їхній зовнішній вигляд і поведінку, наприклад текст для відображення в мітці або кнопці. Різні класи віджетів матимуть різні набори параметрів.

управління геометрією

  Віджети не додаються автоматично до інтерфейсу користувача під час їх створення. Менеджер геометрії, як-от `grid`, контролює, де в інтерфейсі користувача вони розміщені.

цикл подій

  Tkinter реагує на введення користувача, зміни вашої програми та навіть оновлює дисплей лише під час активного запуску циклу подій. Якщо ваша програма не запускає цикл подій, ваш інтерфейс користувача не оновлюватиметься.

### Розуміння того, як Tkinter обертає Tcl/Tk

When your application uses Tkinter’s classes and methods, internally Tkinter is assembling strings representing Tcl/Tk commands, and executing those commands in the Tcl interpreter attached to your application’s `Tk` instance.

Незалежно від того, чи це спроба навігації по довідковій документації, спроба знайти правильний метод або параметр, адаптація деякого існуючого коду або налагодження вашої програми Tkinter, іноді буде корисно зрозуміти, як виглядають ці основні команди Tcl/Tk.

Для ілюстрації, ось еквівалент Tcl/Tk основної частини сценарію Tkinter вище.

    ttk::frame .frm -padding 10
    grid .frm
    grid [ttk::label .frm.lbl -text "Hello World!"] -column 0 -row 0
    grid [ttk::button .frm.btn -text "Quit" -command "destroy ."] -column 1 -row 0

Синтаксис Tcl подібний до багатьох мов оболонки, де першим словом є команда, яка має бути виконана, а аргументи цієї команди йдуть за нею, розділені пробілами. Не вдаючись у подробиці, зауважте наступне:

- Команди, які використовуються для створення віджетів (наприклад, `ttk::frame`), відповідають класам віджетів у Tkinter.

- Параметри віджета Tcl (наприклад, `-text`) відповідають аргументам ключових слів у Tkinter.

- Віджети посилаються за шляхом у Tcl (наприклад, `.frm.btn`), тоді як Tkinter використовує не імена, а посилання на об’єкти.

- Місце віджета в ієрархії віджетів закодовано в його (ієрархічному) шляху, який використовує `.` (точку) як роздільник шляху. Ім’я шляху для кореневого вікна - це просто `.` (крапка). У Tkinter ієрархія визначається не шляхом, а вказівкою батьківського віджета під час створення кожного дочірнього віджета.

- Операції, які реалізовані як окремі команди в Tcl (наприклад, `grid` або `destroy`), представлені як методи в об’єктах віджетів Tkinter. Як ви незабаром побачите, в інших випадках Tcl використовує те, що здається викликами методів для об’єктів віджетів, які більш точно відображають те, що використовується в Tkinter.

### Як мені…? Який варіант робить…?

Якщо ви не впевнені, як щось зробити в Tkinter, і не можете відразу знайти це в підручнику чи довідковій документації, яку використовуєте, є кілька стратегій, які можуть бути корисними.

По-перше, пам’ятайте, що деталі роботи окремих віджетів можуть відрізнятися в різних версіях як Tkinter, так і Tcl/Tk. Якщо ви шукаєте документацію, переконайтеся, що вона відповідає версіям Python і Tcl/Tk, встановленим у вашій системі.

Коли ви шукаєте, як використовувати API, корисно знати точну назву класу, опції або методу, який ви використовуєте. Самоаналіз в інтерактивній оболонці Python або за допомогою `print()` може допомогти вам визначити, що вам потрібно.

Щоб дізнатися, які параметри конфігурації доступні для будь-якого віджета, викличте його метод `configure()`, який повертає словник, що містить різноманітну інформацію про кожен об’єкт, включаючи його типові та поточні значення. Використовуйте `keys()`, щоб отримати лише назви кожного параметра.

    btn = ttk.Button(frm, ...)
    print(btn.configure().keys())

Оскільки більшість віджетів мають багато спільних параметрів конфігурації, може бути корисно дізнатися, які є специфічними для певного класу віджетів. Порівняння списку опцій зі списком простіших віджетів, як-от рамка, є одним із способів зробити це.

    print(set(btn.configure().keys()) - set(frm.configure().keys()))

Так само ви можете знайти доступні методи для об’єкта віджета за допомогою стандартної функції `dir()`. Якщо ви спробуєте це, ви побачите, що існує понад 200 поширених методів віджетів, тому знову ж таки буде корисно визначити ті, які є специфічними для класу віджетів.

    print(dir(btn))
    print(set(dir(btn)) - set(dir(frm)))

### Навігація довідковим посібником Tcl/Tk

Як зазначалося, офіційний довідковий посібник Tk commands (сторінки довідок) часто є найточнішим описом того, що виконують конкретні операції з віджетами. Навіть якщо ви знаєте назву потрібного вам параметра або методу, у вас все одно може бути кілька місць, де слід шукати.

Хоча всі операції в Tkinter реалізовані як виклики методів для об’єктів віджетів, ви бачили, що багато операцій Tcl/Tk відображаються як команди, які приймають шлях до віджета як свій перший параметр, за яким слідують додаткові параметри, напр.

    destroy .
    grid .frm.btn -column 0 -row 0

Інші, однак, більше схожі на методи, викликані об’єктом віджета (насправді, коли ви створюєте віджет у Tcl/Tk, він створює команду Tcl з іменем шляху до віджета, причому першим параметром цієї команди є ім’я методу для виклику).

    .frm.btn invoke
    .frm.lbl configure -text "Goodbye"

В офіційній довідковій документації Tcl/Tk ви знайдете більшість операцій, які виглядають як виклики методів на сторінці довідки для певного віджета (наприклад, ви знайдете метод `invoke()` на кнопці ttk::button). сторінка довідки), тоді як функції, які приймають віджет як параметр, часто мають власну сторінку довідки (наприклад, grid).

Ви знайдете багато поширених параметрів і методів на сторінках довідки options або ttk::widget, а інші можна знайти на сторінці довідки для певного класу віджетів.

Ви також побачите, що багато методів Tkinter мають складені імена, наприклад, `winfo_x()`, `winfo_height()`, `winfo_viewable()`. Ви знайдете документацію для всього цього на сторінці довідки winfo.

Примітка

Дещо збентежує те, що у всіх віджетах Tkinter також є методи, які фактично не працюють з віджетом, а працюють у глобальному масштабі, незалежно від будь-якого віджета. Прикладами є методи доступу до буфера обміну або системного дзвінка. (Вони реалізовані як методи в базовому класі `Widget`, від якого успадковуються всі віджети Tkinter).

## Модель різьблення

Python і Tcl/Tk мають дуже різні моделі потоків, які `tkinter` намагається поєднати. Якщо ви використовуєте потоки, вам, можливо, потрібно це знати.

Інтерпретатор Python може мати багато потоків, пов’язаних із ним. У Tcl можна створити кілька потоків, але кожен потік має окремий екземпляр інтерпретатора Tcl, пов’язаний з ним. Потоки також можуть створювати більше одного екземпляра інтерпретатора, хоча кожен екземпляр інтерпретатора може використовуватися лише тим потоком, який його створив.

Кожен об’єкт `Tk`, створений `tkinter`, містить інтерпретатор Tcl. Він також відстежує, який потік створив цей інтерпретатор. Виклики `tkinter` можна здійснювати з будь-якого потоку Python. Внутрішньо, якщо виклик надходить з потоку, відмінного від того, який створив об’єкт `Tk`, подія публікується в черзі подій інтерпретатора, і після виконання результат повертається до викликаного потоку Python.

Програми Tcl/Tk зазвичай керуються подіями, тобто після ініціалізації інтерпретатор запускає цикл подій (тобто `Tk.mainloop()`) і відповідає на події. Оскільки він однопотоковий, обробники подій повинні реагувати швидко, інакше вони заблокують обробку інших подій. Щоб уникнути цього, будь-які тривалі обчислення не повинні виконуватися в обробнику подій, а розбиваються на менші частини за допомогою таймерів або виконуються в іншому потоці. Це відрізняється від багатьох наборів інструментів графічного інтерфейсу, де графічний інтерфейс працює в повністю окремому потоці від усього коду програми, включаючи обробники подій.

Якщо інтерпретатор Tcl не запускає цикл подій і не обробляє події, будь-які виклики `tkinter`, здійснені з потоків, відмінних від того, що запускає інтерпретатор Tcl, не вдасться.

Існує ряд особливих випадків:

- Бібліотеки Tcl/Tk можна створити таким чином, щоб вони не розпізнавали потоки. У цьому випадку `tkinter` викликає бібліотеку з початкового потоку Python, навіть якщо він відрізняється від потоку, який створив інтерпретатор Tcl. Глобальне блокування забезпечує лише один виклик за один раз.

- У той час як `tkinter` дозволяє створювати більше ніж один екземпляр об’єкта `Tk` (з власним інтерпретатором), усі інтерпретатори, які є частиною одного потоку, спільно використовують спільну чергу подій, яка швидко стає жахливою . На практиці не створюйте більше одного екземпляра `Tk` одночасно. В іншому випадку найкраще створити їх в окремих потоках і переконатися, що ви використовуєте збірку Tcl/Tk з підтримкою потоків.

- Блокування обробників подій — не єдиний спосіб запобігти повторному входу інтерпретатора Tcl у цикл подій. Можна навіть запустити кілька вкладених циклів подій або повністю відмовитися від циклу подій. Якщо ви робите щось складне, коли йдеться про події чи ланцюжки, пам’ятайте про ці можливості.

- Є кілька вибраних функцій `tkinter`, які зараз працюють лише тоді, коли викликаються з потоку, який створив інтерпретатор Tcl.

## Зручний довідник

### Параметри налаштування

Параметри контролюють такі речі, як колір і ширина рамки віджета. Параметри можна встановити трьома способами:

Під час створення об’єкта, використовуючи ключові аргументи

      fred = Button(self, fg="red", bg="blue")

Після створення об’єкта назва параметра розглядається як індекс словника

      fred["fg"] = "red"
      fred["bg"] = "blue"

Використовуйте метод config() для оновлення кількох атрибутів після створення об’єкта

      fred.config(fg="red", bg="blue")

Щоб отримати повне пояснення даного параметра та його поведінки, перегляньте сторінки довідки Tk для відповідного віджета.

Зауважте, що на довідкових сторінках перераховано «СТАНДАРТНІ ПАРАМЕТРИ» та «СПЕЦИФІЧНІ ПАРАМЕТРИ ВІДЖЕТА» для кожного віджета. Перший — це список параметрів, які є спільними для багатьох віджетів, другий — параметри, які є ідіосинкратичними для цього конкретного віджета. Стандартні параметри задокументовані на сторінці довідки options(3).

У цьому документі не робиться різниці між стандартними параметрами та параметрами, що стосуються окремих віджетів. Деякі параметри не застосовуються до деяких типів віджетів. Чи відповідає даний віджет певній опції, залежить від класу віджета; кнопки мають параметр `команда`, а мітки — ні.

Параметри, які підтримує певний віджет, перераховані на сторінці довідки цього віджета, або їх можна запитати під час виконання, викликавши метод `config()` без аргументів або викликавши метод `keys()` у цьому віджеті. Поверненим значенням цих викликів є словник, ключем якого є ім’я опції у вигляді рядка (наприклад, `'relief'`), а значеннями є 5-ти кортежі.

Деякі параметри, як-от `bg`, є синонімами поширених параметрів із довгими назвами (`bg` є скороченням від «фон»). Передача методу `config()` імені скороченого параметра поверне 2-кортеж, а не 5-кортеж. 2-кортеж, переданий назад, міститиме назву синоніму та «справжній» параметр (наприклад, `('bg', 'background')`).

Індекс | Значення | приклад
--- | --- | ---
0 | назва опції | `''рельєф'`
1 | назва параметра для пошуку в базі даних | `''рельєф'`
2 | клас параметрів для пошуку в базі даних | `'Рельєф'`
3 | значення за замовчуванням | `'піднятий''`
4 | поточне значення | `'канавки'`

Приклад:

    >>> print(fred.config())
    {'relief': ('relief', 'relief', 'Relief', 'raised', 'groove')}

Звичайно, надрукований словник міститиме всі доступні варіанти та їхні значення. Це лише як приклад.

### Пакувальник

Пакер є одним із механізмів управління геометрією Tk. Менеджери геометрії використовуються для вказівки відносного розташування віджетів у їхньому контейнері - їхньому спільному master. На відміну від більш громіздкого розсипу (який використовується рідше, і ми не розглядаємо його тут), пакувальник бере якісну специфікацію зв’язку – вгорі, ліворуч, заповнення тощо – і працює все, щоб визначити для вас точні координати розміщення.

Розмір будь-якого головного віджета визначається розміром «підлеглих віджетів» усередині. Пакувальник використовується для керування тим, де підпорядковані віджети з’являються всередині головного, у який вони упаковані. Ви можете запакувати віджети у фрейми, а фрейми – в інші фрейми, щоб отримати потрібний вам макет. Крім того, компонування динамічно налаштовується для врахування поступових змін конфігурації після того, як воно упаковане.

Зауважте, що віджети не з’являться, доки їхню геометрію не буде визначено за допомогою менеджера геометрії. Поширеною ранньою помилкою є пропуск специфікації геометрії, а потім дивуватися, коли віджет створено, але нічого не з’явиться. Віджет з’явиться лише після того, як до нього буде застосовано, наприклад, метод пакувальника `pack()`.

Метод pack() можна викликати за допомогою пар ключове слово-параметр/значення, які визначають, де віджет має з’являтися в своєму контейнері та як він має поводитися, коли змінюється розмір головного вікна програми. Ось кілька прикладів:

    fred.pack()                     # defaults to side = "top"
    fred.pack(side="left")
    fred.pack(expand=1)

### Опції пакувальника

Щоб отримати докладнішу інформацію про пакувальник і параметри, які він може приймати, перегляньте сторінки довідки та сторінку 183 книги Джона Оустерхаута.

якір

  Якірний тип. Позначає, де пакувальник має розмістити кожного підлеглого у своїй посилці.

розширити

  Логічне значення, `0` або `1`.

заповнити

  Правильні значення: `'x'`, `'y'`, `'both'`, `'none'`.

ipadx і ipady

  Відстань — позначення внутрішнього відступу з кожного боку підлеглого віджета.

padx і pady

  Відстань — позначення зовнішніх відступів з кожного боку підлеглого віджета.

бік

  Допустимі значення: `'left'`, `'right'`, `'top'`, `'bottom'`.

### З’єднання змінних віджетів

Налаштування поточного значення деяких віджетів (наприклад, віджетів для введення тексту) можна підключити безпосередньо до змінних програми за допомогою спеціальних параметрів. Ці параметри: `variable`, `textvariable`, `onvalue`, `offvalue` і `value`. Це підключення працює в обох напрямках: якщо змінна змінюється з будь-якої причини, віджет, до якого вона підключена, буде оновлено, щоб відобразити нове значення.

На жаль, у поточній реалізації `tkinter` неможливо передати довільну змінну Python у віджет за допомогою опції `variable` або `textvariable`. Єдині типи змінних, для яких це працює, це змінні, які є підкласами класу під назвою Variable, визначеного в `tkinter`.

Уже визначено багато корисних підкласів Variable: `StringVar`, `IntVar`, `DoubleVar` і `BooleanVar`. Щоб прочитати поточне значення такої змінної, викличте для неї метод `get()`, а щоб змінити її значення, викличте метод `set()`. Якщо ви дотримуєтеся цього протоколу, віджет завжди відстежуватиме значення змінної без подальшого втручання з вашого боку.

Наприклад:

    import tkinter as tk

    class App(tk.Frame):
        def __init__(self, master):
            super().__init__(master)
            self.pack()

            self.entrythingy = tk.Entry()
            self.entrythingy.pack()

            # Create the application variable.
            self.contents = tk.StringVar()
            # Set it to some value.
            self.contents.set("this is a variable")
            # Tell the entry widget to watch this variable.
            self.entrythingy["textvariable"] = self.contents

            # Define a callback for when the user hits return.
            # It prints the current value of the variable.
            self.entrythingy.bind('<Key-Return>',
                                 self.print_contents)

        def print_contents(self, event):
            print("Hi. The current entry content is:",
                  self.contents.get())

    root = tk.Tk()
    myapp = App(root)
    myapp.mainloop()

### Менеджер вікон

У Tk є службова команда `wm` для взаємодії з менеджером вікон. Параметри команди `wm` дозволяють керувати такими речами, як заголовки, розташування, растрові зображення піктограм тощо. У `tkinter` ці команди реалізовано як методи класу `Wm`. Віджети верхнього рівня є підкласами класу `Wm`, тому можуть безпосередньо викликати методи `Wm`.

Щоб отримати доступ до вікна верхнього рівня, яке містить даний віджет, ви часто можете просто звернутися до майстра віджета. Звичайно, якщо віджет було упаковано всередину фрейму, майстер не представлятиме вікно верхнього рівня. Щоб отримати доступ до вікна верхнього рівня, яке містить довільний віджет, ви можете викликати метод `_root()`. Цей метод починається з підкреслення, щоб позначити той факт, що ця функція є частиною реалізації, а не інтерфейсом до функціональності Tk.

Ось кілька прикладів типового використання:

    import tkinter as tk

    class App(tk.Frame):
        def __init__(self, master=None):
            super().__init__(master)
            self.pack()

    # create the application
    myapp = App()

    #
    # here are method calls to the window manager class
    #
    myapp.master.title("My Do-Nothing Application")
    myapp.master.maxsize(1000, 400)

    # start the program
    myapp.mainloop()

### Типи даних параметрів Tk

якір

  Правовими значеннями є точки компаса: `"n"`, `"ne"`, `"e"`, `"se"`, `"s"`, `"sw"`, `"w"`, `"nw"`, а також `"center"`.

растрове зображення

  Є вісім вбудованих іменованих растрових зображень: `'error'`, `'gray25'`, `'gray50'`, `'hourglass'`, `'info'`, `'questhead'`, `'питання'`, `'попередження''`. Щоб вказати ім’я файлу растрового зображення X, укажіть повний шлях до файлу, перед яким стоїть `@`, як у `"@/usr/contrib/bitmap/gumby.bit"`.

логічний

  Ви можете передати цілі числа 0 або 1 або рядки `"yes"` чи `"no"`.

зворотній дзвінок

  Це будь-яка функція Python, яка не приймає аргументів. Наприклад:

      def print_it():
          print("hi there")
      fred["command"] = print_it

колір

  Кольори можна вказати як назви кольорів X у файлі rgb.txt або як рядки, що представляють значення RGB у 4 бітах: `"#RGB"`, 8 бітах: `"#RRGGBB"`, 12 бітах : `"#RRRGGGBBB"`, або 16 біт: `"#RRRRGGGBBBB"` діапазони, де R, G, B тут представляють будь-яку допустиму шістнадцяткову цифру. Подробиці дивіться на сторінці 160 книги Оустерхаута.

курсор

  Можна використовувати стандартні імена курсорів X із `cursorfont.h` без префікса `XC_`. Наприклад, щоб отримати курсор руки (`XC_hand2`), використовуйте рядок `"hand2"`. Ви також можете вказати власний растровий файл і файл маски. Дивіться сторінку 179 книги Оустерхаута.

відстань

  Відстань до екрана можна вказати як у пікселях, так і в абсолютних відстанях. Пікселі подаються у вигляді чисел, а абсолютні відстані – у вигляді рядків із кінцевим символом, що позначає одиниці: `c` для сантиметрів, `i` для дюймів, `m` для міліметрів, `p` для точок принтера . Наприклад, 3,5 дюйма виражається як `"3,5i"`.

шрифт

  Tk використовує формат назви шрифту списку, наприклад `{courier 10 bold}`. Розмір шрифту з додатними числами вимірюється в пунктах; розміри з від’ємними числами вимірюються в пікселях.

геометрія

  Це рядок у формі `ширинаxвисота`, де ширина та висота вимірюються в пікселях для більшості віджетів (у символах для віджетів, що відображають текст). Наприклад: `fred["geometry"] = "200x100"`.

виправдати

  Правильними значеннями є рядки: `"left"`, `"center"`, `"right"` і `"fill"`.

область

  Це рядок із чотирма розділеними пробілами елементами, кожен із яких є допустимою відстанню (див. вище). Наприклад: `"2 3 4 5"` і `"3i 2i 4.5i 2i"` і `"3c 2c 4c 10.43c"` є законними регіонами.

полегшення

  Визначає, яким буде стиль межі віджета. Допустимі значення: `"піднятий"`, `"заглиблений"`, `"плоский"`, `"канавка"` і `"гребінь"`.

команда прокручування

  Це майже завжди метод `set()` якогось віджета смуги прокрутки, але це може бути будь-який метод віджета, який приймає один аргумент.

загорнути

  Має бути одне з: `"none"`, `"char"` або `"word"`.

### Прив’язки та події

Метод прив’язки з команди віджета дозволяє спостерігати за певними подіями та запускати функцію зворотного виклику, коли відбувається подія такого типу. Форма методу прив’язки:

    def bind(self, sequence, func, add=''):

де:

послідовність

  це рядок, який позначає цільовий тип події. (Докладніше див. сторінку довідки bind(3tk) і сторінку 201 книги Джона Оустерхаута Tcl and the Tk Toolkit (2nd edition)).

функц

  це функція Python, яка приймає один аргумент, який викликається, коли відбувається подія. Екземпляр події буде передано як аргумент. (Функції, розгорнуті таким чином, широко відомі як зворотні виклики.)

додати

  є необов’язковим, або `''` або `'+'`. Передача порожнього рядка означає, що ця прив’язка має замінити будь-які інші прив’язки, з якими пов’язана ця подія. Передача `'+'` означає, що цю функцію потрібно додати до списку функцій, пов’язаних із цим типом події.

Наприклад:

    def turn_red(self, event):
        event.widget["activeforeground"] = "red"

    self.button.bind("<Enter>", self.turn_red)

Зверніть увагу, як у зворотному виклику `turn_red()` здійснюється доступ до поля віджета події. Це поле містить віджет, який перехопив подію X. У наведеній нижче таблиці перераховано інші поля подій, до яких ви можете отримати доступ, і те, як вони позначаються в Tk, що може бути корисним під час звернення до довідкових сторінок Tk.

Тк | Поле подій Tkinter | Тк | Поле подій Tkinter
--- | --- | --- | ---
%f | фокус | %A | char
%h | висота | %E | send_event
%k | код ключа | %K | keysym
%s | стан | %N | keysym_num
%t | час | %T | типу
%w | ширина | %W | віджет
%x | x | %X | x_root
%y | р | %Y | y_root

### Параметр індексу

Кілька віджетів потребують передачі параметрів «index». Вони використовуються для вказівки на певне місце у віджеті «Текст», або на певні символи у віджеті «Вхід», або на певні пункти меню у віджеті «Меню».

Індекси віджетів запису (індекс, індекс перегляду тощо)

  Віджети запису мають параметри, які стосуються позицій символів у тексті, що відображається. Ви можете використовувати ці функції `tkinter` для доступу до цих спеціальних пунктів у текстових віджетах:

Індекси текстових віджетів

  Нотація покажчика для текстових віджетів дуже багата і найкраще описана на сторінках керівництва Tk.

Індекси меню (menu.invoke(), menu.entryconfig() тощо)

  Деякі параметри та методи для меню маніпулюють певними записами меню. Щоразу, коли для опції чи параметра потрібен індекс меню, ви можете передати:

  - ціле число, яке відноситься до числової позиції запису у віджеті, починаючи з 0;

  - рядок `"active"`, який посилається на позицію меню, яка зараз знаходиться під курсором;

  - рядок `"last"`, який посилається на останній пункт меню;

  - Ціле число, якому передує `@`, як у `@6`, де ціле число інтерпретується як координата y пікселя в системі координат меню;

  - рядок `"none"`, який вказує на те, що в меню взагалі немає запису, найчастіше використовується з menu.activate(), щоб дезактивувати всі записи, і, нарешті,

  - текстовий рядок, який зіставляється з міткою запису меню, відсканований від верхньої частини меню донизу. Зауважте, що цей тип індексу розглядається після всіх інших, що означає, що збіги для пунктів меню, позначених як `останній`, `активний` або `жоден`, замість цього можуть інтерпретуватися як наведені вище літерали.

### Зображення

Зображення різних форматів можна створювати за допомогою відповідного підкласу `tkinter.Image`:

- `BitmapImage` для зображень у форматі XBM.

- `PhotoImage` для зображень у форматах PGM, PPM, GIF і PNG. Останній підтримується, починаючи з Tk 8.6.

Будь-який тип зображення створюється за допомогою параметра `file` або `data` (інші параметри також доступні).

Змінено в версії 3.13: Added the `PhotoImage` method `copy_replace()` to copy a region from one image to other image, possibly with pixel zooming and/or subsampling. Add from_coords parameter to `PhotoImage` methods `copy()`, `zoom()` and `subsample()`. Add zoom and subsample parameters to `PhotoImage` method `copy()`.

Потім об’єкт зображення можна використовувати скрізь, де параметр `image` підтримується деяким віджетом (наприклад, мітки, кнопки, меню). У цих випадках Tk не зберігатиме посилання на зображення. Коли останнє посилання Python на об’єкт зображення видаляється, дані зображення також видаляються, і Tk відображатиме порожнє поле, де б зображення не використовувалося.

Дивись також

The Pillow package adds support for formats such as BMP, JPEG, TIFF, and WebP, among others.

## Обробники файлів

Tk дозволяє вам зареєструвати та скасувати реєстрацію функції зворотного виклику, яка буде викликана з основного циклу Tk, коли введення/виведення можливе для дескриптора файлу. Для кожного дескриптора файлу можна зареєструвати лише один обробник. Приклад коду:

    import tkinter
    widget = tkinter.Tk()
    mask = tkinter.READABLE | tkinter.WRITABLE
    widget.tk.createfilehandler(file, mask, callback)
    ...
    widget.tk.deletefilehandler(file)

Ця функція недоступна в Windows.

Оскільки ви не знаєте, скільки байтів доступно для читання, ви можете не використовувати `BufferedIOBase` або `TextIOBase` `read()` або `readline()` методи, оскільки вони наполягатимуть на читанні заздалегідь визначеної кількості байтів. Для сокетів добре працюватимуть методи `recv()` або `recvfrom()`; для інших файлів використовуйте необроблені читання або `os.read(file.fileno(), maxbytecount)`.

Widget.tk.createfilehandler(file, mask, func)

  Реєструє функцію зворотного виклику обробника файлів func. Аргумент file може бути або об’єктом із методом `fileno()` (наприклад, об’єкт файл або сокет), або цілочисельним дескриптором файлу. Аргумент mask — це комбінація будь-якої з трьох констант, наведених нижче. Зворотний виклик викликається наступним чином:

      callback(file, mask)

Widget.tk.deletefilehandler(file)

  Скасовує реєстрацію обробника файлів.

_tkinter.READABLE
_tkinter.WRITABLE
_tkinter.EXCEPTION

  Константи, що використовуються в аргументах mask.