Документация Python неофициальный перевод

tkinter.md

703 строк · 67.2 КБ · обычная страница · сырой текст · скачать

1> **Источник:** https://python-all.ru/3.11/library/tkinter.html2>3> «Документация Python на русском» – неофициальный перевод официальной документации Python: версии от 2.6 до 3.16, полнотекстовый поиск, английский оригинал рядом с переводом. Эта Markdown-версия страницы предназначена для работы с LLM: вставьте её в ChatGPT, Claude или Cursor.45---67# [`tkinter`](https://python-all.ru/3.11/library/tkinter.html#module-tkinter) – интерфейс Python к Tcl/Tk89**Исходный код:** [Lib/tkinter/\_\_init\_\_.py](https://python-all.ru/src/3.11/Lib/tkinter/__init__.py)1011---1213Пакет [`tkinter`](https://python-all.ru/3.11/library/tkinter.html#module-tkinter) («Tk interface») – это стандартный интерфейс Python к набору инструментов GUI Tcl/Tk. Как Tk, так и [`tkinter`](https://python-all.ru/3.11/library/tkinter.html#module-tkinter) доступны на большинстве Unix-платформ, включая macOS, а также в Windows.1415Запуск `python -m tkinter` из командной строки должен открыть окно, демонстрирующее простой интерфейс Tk, показывая, что [`tkinter`](https://python-all.ru/3.11/library/tkinter.html#module-tkinter) корректно установлен в системе, а также отображая версию Tcl/Tk, чтобы можно было прочитать документацию Tcl/Tk, соответствующую этой версии.1617Tkinter поддерживает ряд версий Tcl/Tk, собранных как с поддержкой потоков, так и без неё. Официальный бинарный дистрибутив Python включает многопоточный Tcl/Tk 8.6. См. исходный код модуля [`_tkinter`](https://python-all.ru/3.11/library/tkinter.html#module-_tkinter) для получения дополнительной информации о поддерживаемых версиях.1819Tkinter – не тонкая обёртка; он добавляет значительную долю собственной логики, чтобы сделать работу более питоничной. Данная документация сосредоточена на этих дополнениях и изменениях, а за неизменными деталями отсылает к официальной документации Tcl/Tk.2021> **Примечание**22>23> Tcl/Tk 8.5 (2007) представил современный набор тематических компонентов пользовательского интерфейса вместе с новым API для их использования. Как старый, так и новый API всё ещё доступны. Большинство онлайн-документации всё ещё использует старый API и может быть безнадёжно устаревшей.2425> **См. также**26>27> - **[TkDocs](https://python-all.ru/3.11/library/tkinter.html)**28>29>   Обширное руководство по созданию пользовательских интерфейсов с помощью Tkinter. Объясняет ключевые концепции и иллюстрирует рекомендуемые подходы с использованием современного API.30> - **[Справочник по Tkinter 8.5: GUI для Python](https://python-all.ru/3.11/library/tkinter.html)**31>32>   Справочная документация по Tkinter 8.5 с подробным описанием доступных классов, методов и опций.33>34> Ресурсы по Tcl/Tk:35>36> - **[Команды Tk](https://python-all.ru/3.11/library/tkinter.html)**37>38>   Исчерпывающий справочник по каждой из базовых команд Tcl/Tk, используемых Tkinter.39> - **[Домашняя страница Tcl/Tk](https://python-all.ru/3.11/library/tkinter.html)**40>41>   Дополнительная документация и ссылки на разработку ядра Tcl/Tk.42>43> Книги:44>45> - **[Современный Tkinter для занятых разработчиков Python](https://python-all.ru/3.11/library/tkinter.html)**46>47>   Автор: Mark Roseman. (ISBN 978-1999149567)48> - **[Программирование GUI на Python с помощью Tkinter](https://python-all.ru/3.11/library/tkinter.html)**49>50>   Автор: Alan D. Moore. (ISBN 978-1788835886)51> - **[Программирование на Python](https://python-all.ru/3.11/library/tkinter.html)**52>53>   Автор: Mark Lutz; отличное освещение Tkinter. (ISBN 978-0596158101)54> - **[Tcl и инструментарий Tk (2-е издание)](https://python-all.ru/3.11/library/tkinter.html)**55>56>   Авторы: John Ousterhout, изобретатель Tcl/Tk, и Ken Jones; Tkinter не рассматривается. (ISBN 978-0321336330)5758## Архитектура5960Tcl/Tk – это не одна библиотека, а набор из нескольких отдельных модулей, каждый со своей функциональностью и собственной официальной документацией. Бинарные дистрибутивы Python также включают дополнительный модуль.6162**Tcl**6364Tcl – это динамический интерпретируемый язык программирования, так же как Python. Хотя его можно использовать самостоятельно как язык общего назначения, чаще всего он встраивается в C-приложения в качестве скриптового движка или интерфейса к набору инструментов Tk. Библиотека Tcl имеет C-интерфейс для создания и управления одним или несколькими экземплярами интерпретатора Tcl, выполнения команд и сценариев Tcl в этих экземплярах, а также добавления пользовательских команд, реализованных на Tcl или C. Каждый интерпретатор имеет очередь событий, и существуют средства для отправки событий в неё и их обработки. В отличие от Python, модель выполнения Tcl построена на кооперативной многозадачности, и Tkinter устраняет это различие (подробнее см. [модель потоков](https://python-all.ru/3.11/library/tkinter.html#threading-model)).6566**Tk**6768Tk – это [пакет Tcl](https://python-all.ru/3.11/library/tkinter.html), реализованный на C, который добавляет пользовательские команды для создания и управления GUI-виджетами. Каждый объект [`Tk`](https://python-all.ru/3.11/library/tkinter.html#tkinter.Tk) содержит собственный экземпляр интерпретатора Tcl с загруженным Tk. Виджеты Tk очень настраиваемы, хотя и ценой устаревшего внешнего вида. Tk использует очередь событий Tcl для генерации и обработки событий GUI.6970**Ttk**7172Themed Tk (Ttk) – это новое семейство виджетов Tk, которое обеспечивает гораздо лучший внешний вид на разных платформах по сравнению со многими классическими виджетами Tk. Ttk распространяется как часть Tk, начиная с версии Tk 8.5. Привязки для Python предоставляются в отдельном модуле [`tkinter.ttk`](https://python-all.ru/3.11/library/tkinter.ttk.html#module-tkinter.ttk).7374Внутренне Tk и Ttk используют средства нижележащей операционной системы, а именно Xlib на Unix/X11, Cocoa на macOS, GDI на Windows.7576Когда ваше Python-приложение использует класс в Tkinter, например, для создания виджета, модуль [`tkinter`](https://python-all.ru/3.11/library/tkinter.html#module-tkinter) сначала собирает строку команды Tcl/Tk. Он передаёт эту строку команды Tcl внутреннему бинарному модулю [`_tkinter`](https://python-all.ru/3.11/library/tkinter.html#module-_tkinter), который затем вызывает интерпретатор Tcl для её выполнения. Интерпретатор Tcl затем обращается к пакетам Tk и/или Ttk, которые, в свою очередь, делают вызовы к Xlib, Cocoa или GDI.7778## Модули Tkinter7980Поддержка Tkinter распределена по нескольким модулям. Большинству приложений понадобится основной модуль [`tkinter`](https://python-all.ru/3.11/library/tkinter.html#module-tkinter), а также модуль [`tkinter.ttk`](https://python-all.ru/3.11/library/tkinter.ttk.html#module-tkinter.ttk), предоставляющий современный набор тематических виджетов и API:8182```python83from tkinter import *84from tkinter import ttk85```8687#### `class tkinter.Tk(screenName=None, baseName=None, className='Tk', useTk=True, sync=False, use=None)`8889Создаёт виджет верхнего уровня Tk, который обычно является главным окном приложения, и инициализирует интерпретатор Tcl для этого виджета. Каждый экземпляр имеет свой собственный связанный интерпретатор Tcl.9091Класс [`Tk`](https://python-all.ru/3.11/library/tkinter.html#tkinter.Tk) обычно создаётся со значениями по умолчанию. Однако в настоящее время распознаются следующие именованные аргументы:9293***screenName***9495При указании (в виде строки) устанавливает переменную окружения `DISPLAY`. (только X11)9697***baseName***9899Имя файла профиля. По умолчанию *baseName* берётся из имени программы (`sys.argv[0]`).100101***className***102103Имя класса виджета. Используется как файл профиля, а также как имя, с которым вызывается Tcl (*argv0* в *interp*).104105***useTk***106107Если `True`, инициализировать подсистему Tk. Функция [`tkinter.Tcl()`](https://python-all.ru/3.11/library/tkinter.html#tkinter.Tcl) устанавливает это в `False`.108109***sync***110111Если `True`, выполнять все команды X-сервера синхронно, чтобы ошибки сообщались немедленно. Может использоваться для отладки. (только X11)112113***use***114115Задаёт *id* окна, в которое встраивается приложение, вместо того чтобы создавать его как независимое окно верхнего уровня. *id* должен быть указан так же, как значение опции -use для виджетов верхнего уровня (то есть иметь форму, подобную возвращаемой `winfo_id()`).116117Обратите внимание, что на некоторых платформах это будет работать корректно только если *id* ссылается на Tk-фрейм или окно верхнего уровня, у которых включена опция -container.118119[`Tk`](https://python-all.ru/3.11/library/tkinter.html#tkinter.Tk) читает и интерпретирует файлы профилей с именами `.className.tcl` и `.baseName.tcl` в интерпретатор Tcl и вызывает [`exec()`](https://python-all.ru/3.11/library/functions.html#exec) для содержимого `.className.py` и `.baseName.py`. Путь к файлам профилей задаётся переменной окружения `HOME` или, если она не определена, то [`os.curdir`](https://python-all.ru/3.11/library/os.html#os.curdir).120121#### `tk`122123Объект приложения Tk, созданный созданием экземпляра [`Tk`](https://python-all.ru/3.11/library/tkinter.html#tkinter.Tk). Он предоставляет доступ к интерпретатору Tcl. Каждый виджет, прикреплённый к тому же экземпляру [`Tk`](https://python-all.ru/3.11/library/tkinter.html#tkinter.Tk), имеет одинаковое значение для своего атрибута [`tk`](https://python-all.ru/3.11/library/tkinter.html#tkinter.Tk.tk).124125#### `master`126127Объект виджета, который содержит данный виджет. Для [`Tk`](https://python-all.ru/3.11/library/tkinter.html#tkinter.Tk) атрибут *master* равен [`None`](https://python-all.ru/3.11/library/constants.html#None), поскольку это главное окно. Термины *master* и *parent* похожи и иногда используются как взаимозаменяемые имена аргументов; однако вызов `winfo_parent()` возвращает строку с именем виджета, тогда как [`master`](https://python-all.ru/3.11/library/tkinter.html#tkinter.Tk.master) возвращает объект. *parent*/*child* отражает древовидное отношение, а *master*/*slave* – структуру контейнера.128129#### `children`130131Непосредственные потомки этого виджета в виде [`dict`](https://python-all.ru/3.11/library/stdtypes.html#dict) с именами дочерних виджетов в качестве ключей и объектами экземпляров потомков в качестве значений.132133#### `tkinter.Tcl(screenName=None, baseName=None, className='Tk', useTk=False)`134135Функция [`Tcl()`](https://python-all.ru/3.11/library/tkinter.html#tkinter.Tcl) является фабричной функцией, которая создаёт объект, очень похожий на создаваемый классом [`Tk`](https://python-all.ru/3.11/library/tkinter.html#tkinter.Tk), за исключением того, что она не инициализирует подсистему Tk. Это чаще всего полезно при управлении интерпретатором Tcl в среде, где не требуется создавать лишние окна верхнего уровня, или где это невозможно (например, в системах Unix/Linux без X-сервера). Объект, созданный объектом [`Tcl()`](https://python-all.ru/3.11/library/tkinter.html#tkinter.Tcl), может создать окно верхнего уровня (и инициализировать подсистему Tk) с помощью вызова его метода `loadtk()`.136137Модули, обеспечивающие поддержку Tk, включают:138139**[`tkinter`](https://python-all.ru/3.11/library/tkinter.html#module-tkinter)**140141Основной модуль Tkinter.142143**[`tkinter.colorchooser`](https://python-all.ru/3.11/library/tkinter.colorchooser.html#module-tkinter.colorchooser)**144145Диалоговое окно для выбора цвета пользователем.146147**[`tkinter.commondialog`](https://python-all.ru/3.11/library/dialog.html#module-tkinter.commondialog)**148149Базовый класс для диалогов, определённых в других перечисленных здесь модулях.150151**[`tkinter.filedialog`](https://python-all.ru/3.11/library/dialog.html#module-tkinter.filedialog)**152153Стандартные диалоги для указания файла для открытия или сохранения.154155**[`tkinter.font`](https://python-all.ru/3.11/library/tkinter.font.html#module-tkinter.font)**156157Утилиты для работы со шрифтами.158159**[`tkinter.messagebox`](https://python-all.ru/3.11/library/tkinter.messagebox.html#module-tkinter.messagebox)**160161Доступ к стандартным диалоговым окнам Tk.162163**[`tkinter.scrolledtext`](https://python-all.ru/3.11/library/tkinter.scrolledtext.html#module-tkinter.scrolledtext)**164165Текстовый виджет со встроенной вертикальной полосой прокрутки.166167**[`tkinter.simpledialog`](https://python-all.ru/3.11/library/dialog.html#module-tkinter.simpledialog)**168169Базовые диалоги и вспомогательные функции.170171**[`tkinter.ttk`](https://python-all.ru/3.11/library/tkinter.ttk.html#module-tkinter.ttk)**172173Набор тематических виджетов, представленный в Tk 8.5, предоставляющий современные альтернативы многим классическим виджетам из основного модуля [`tkinter`](https://python-all.ru/3.11/library/tkinter.html#module-tkinter).174175Дополнительные модули:176177**[`_tkinter`](https://python-all.ru/3.11/library/tkinter.html#module-_tkinter)**178179Двоичный модуль, содержащий низкоуровневый интерфейс к Tcl/Tk. Он автоматически импортируется основным модулем [`tkinter`](https://python-all.ru/3.11/library/tkinter.html#module-tkinter) и никогда не должен использоваться напрямую программистами приложений. Обычно это разделяемая библиотека (или DLL), но в некоторых случаях может быть статически слинкована с интерпретатором Python.180181**[`idlelib`](https://python-all.ru/3.11/library/idle.html#module-idlelib)**182183Интегрированная среда разработки и обучения Python (IDLE). Основана на [`tkinter`](https://python-all.ru/3.11/library/tkinter.html#module-tkinter).184185**`tkinter.constants`**186187Символические константы, которые можно использовать вместо строк при передаче различных параметров вызовам Tkinter. Автоматически импортируются основным модулем [`tkinter`](https://python-all.ru/3.11/library/tkinter.html#module-tkinter).188189**[`tkinter.dnd`](https://python-all.ru/3.11/library/tkinter.dnd.html#module-tkinter.dnd)**190191(экспериментально) Поддержка перетаскивания для [`tkinter`](https://python-all.ru/3.11/library/tkinter.html#module-tkinter). Станет устаревшим, когда будет заменён на Tk DND.192193**[`tkinter.tix`](https://python-all.ru/3.11/library/tkinter.tix.html#module-tkinter.tix)**194195(Устарело) Старый сторонний пакет Tcl/Tk, который добавляет несколько новых виджетов. Лучшие альтернативы для большинства из них можно найти в [`tkinter.ttk`](https://python-all.ru/3.11/library/tkinter.ttk.html#module-tkinter.ttk).196197**[`turtle`](https://python-all.ru/3.11/library/turtle.html#module-turtle)**198199Черепашья графика в окне Tk.200201## Спасательный круг Tkinter202203Этот раздел не задумывался как исчерпывающее руководство по Tk или Tkinter. Для этого обратитесь к одному из внешних ресурсов, упомянутых ранее. Вместо этого данный раздел даёт очень краткое представление о том, как выглядит приложение Tkinter, знакомит с основными концепциями Tk и объясняет структуру обёртки Tkinter.204205Оставшаяся часть этого раздела поможет вам определить классы, методы и параметры, которые понадобятся в вашем приложении Tkinter, а также где найти более подробную документацию по ним, включая официальное справочное руководство Tcl/Tk.206207### Программа Hello World208209Начнём с разбора приложения «Hello World» на Tkinter. Это не самая минимальная версия, которую можно написать, но в ней достаточно деталей, чтобы проиллюстрировать некоторые ключевые концепции, которые необходимо знать.210211```python212from tkinter import *213from tkinter import ttk214root = Tk()215frm = ttk.Frame(root, padding=10)216frm.grid()217ttk.Label(frm, text="Hello World!").grid(column=0, row=0)218ttk.Button(frm, text="Quit", command=root.destroy).grid(column=1, row=0)219root.mainloop()220```221222После импортов следующая строка создаёт экземпляр класса `Tk`, который инициализирует Tk и создаёт связанный с ним интерпретатор Tcl. Она также создаёт главное окно, известное как корневое окно, которое служит основным окном приложения.223224Следующая строка создаёт виджет Frame, который в данном случае будет содержать метку и кнопку, которые мы создадим далее. Frame помещается внутрь корневого окна.225226Следующая строка создаёт виджет-метку, содержащую статическую текстовую строку. Метод `grid()` используется для указания относительного расположения (позиции) метки внутри содержащего её виджета-рамки, подобно тому, как работают таблицы в HTML.227228Затем создаётся виджет-кнопка и размещается справа от метки. При нажатии он вызовет метод `destroy()` корневого окна.229230Наконец, метод `mainloop()` выводит всё на экран и реагирует на ввод пользователя до завершения программы.231232### Важные концепции Tk233234Даже эта простая программа иллюстрирует следующие ключевые концепции Tk:235236**виджеты**237238Пользовательский интерфейс Tkinter состоит из отдельных *виджетов*. Каждый виджет представлен объектом Python, создаваемым из классов, таких как `ttk.Frame`, `ttk.Label` и `ttk.Button`.239240**иерархия виджетов**241242Виджеты организованы в *иерархию*. Метка и кнопка были размещены внутри фрейма, который, в свою очередь, находился внутри корневого окна. При создании каждого *дочернего* виджета его *родительский* виджет передаётся первым аргументом конструктору виджета.243244**параметры конфигурации**245246Виджеты имеют *параметры конфигурации*, которые изменяют их внешний вид и поведение, например текст, отображаемый в метке или кнопке. Разные классы виджетов имеют разные наборы параметров.247248**управление геометрией**249250Виджеты не добавляются в интерфейс автоматически при их создании. *Менеджер геометрии*, такой как `grid`, управляет тем, где они размещаются в интерфейсе.251252**цикл событий**253254Tkinter реагирует на ввод пользователя, изменения в программе и даже обновляет экран только при активном выполнении *цикла событий*. Если программа не выполняет цикл событий, интерфейс не будет обновляться.255256### Понимание того, как Tkinter оборачивает Tcl/Tk257258Когда ваше приложение использует классы и методы Tkinter, внутри Tkinter собирает строки, представляющие команды Tcl/Tk, и выполняет их в интерпретаторе Tcl, прикреплённом к экземпляру `Tk` вашего приложения.259260Будь то попытка разобраться в справочной документации, поиск нужного метода или параметра, адаптация существующего кода или отладка приложения Tkinter, бывают моменты, когда полезно понимать, как выглядят эти базовые команды Tcl/Tk.261262Для иллюстрации ниже приведён эквивалент на Tcl/Tk основной части скрипта Tkinter, показанного выше.263264```python265ttk::frame .frm -padding 10266grid .frm267grid [ttk::label .frm.lbl -text "Hello World!"] -column 0 -row 0268grid [ttk::button .frm.btn -text "Quit" -command "destroy ."] -column 1 -row 0269```270271Синтаксис Tcl похож на многие оболочки: первое слово – это команда, за которой следуют её аргументы, разделённые пробелами. Не вдаваясь в подробности, обратите внимание на следующее:272273- Команды для создания виджетов (например, `ttk::frame`) соответствуют классам виджетов в Tkinter.274- Параметры виджетов Tcl (например, `-text`) соответствуют именованным аргументам в Tkinter.275- В Tcl виджеты идентифицируются по *пути* (например, `.frm.btn`), тогда как Tkinter использует не имена, а ссылки на объекты.276- Положение виджета в иерархии закодировано в его (иерархическом) пути, который использует `.` (точку) в качестве разделителя. Путь корневого окна – это просто `.` (точка). В Tkinter иерархия определяется не путём, а указанием родительского виджета при создании каждого дочернего виджета.277- Операции, которые реализованы как отдельные *команды* в Tcl (например, `grid` или `destroy`), представлены как *методы* объектов виджетов Tkinter. Как вы вскоре увидите, в других случаях Tcl использует то, что выглядит как вызовы методов объектов виджетов, что более точно отражает то, что используется в Tkinter.278279### Как сделать…? Какой параметр…?280281Если вы не уверены, как сделать что-то в Tkinter, и не можете сразу найти это в используемом учебнике или справочной документации, есть несколько стратегий, которые могут помочь.282283Во-первых, помните, что детали работы отдельных виджетов могут различаться в разных версиях как Tkinter, так и Tcl/Tk. При поиске документации убедитесь, что она соответствует версиям Python и Tcl/Tk, установленным в вашей системе.284285При поиске способа использования API полезно знать точное имя класса, параметра или метода, которые вы используете. Интроспекция, будь то в интерактивной оболочке Python или с помощью [`print()`](https://python-all.ru/3.11/library/functions.html#print), может помочь определить, что вам нужно.286287Чтобы узнать, какие параметры конфигурации доступны для любого виджета, вызовите его метод `configure()`, который возвращает словарь, содержащий разнообразную информацию о каждом объекте, включая его значения по умолчанию и текущие. Используйте `keys()`, чтобы получить только имена каждого параметра.288289```python290btn = ttk.Button(frm, ...)291print(btn.configure().keys())292```293294Поскольку большинство виджетов имеют много общих параметров конфигурации, может быть полезно выяснить, какие из них специфичны для конкретного класса виджетов. Один из способов – сравнить список параметров с аналогичным списком более простого виджета, например фрейма.295296```python297print(set(btn.configure().keys()) - set(frm.configure().keys()))298```299300Аналогично, можно найти доступные методы объекта виджета с помощью стандартной функции [`dir()`](https://python-all.ru/3.11/library/functions.html#dir). Если попробовать, окажется, что существует более 200 общих методов виджетов, поэтому снова полезно определить методы, специфичные для класса виджета.301302```python303print(dir(btn))304print(set(dir(btn)) - set(dir(frm)))305```306307### Навигация по справочному руководству Tcl/Tk308309Как уже отмечалось, официальное справочное руководство [команд Tk](https://python-all.ru/3.11/library/tkinter.html) (страницы руководства) часто является наиболее точным описанием того, что делают конкретные операции с виджетами. Даже если имя нужной опции или метода известно, может потребоваться заглянуть в несколько мест.310311Хотя все операции в Tkinter реализованы как вызовы методов объектов виджетов, многие операции Tcl/Tk представлены как команды, которые принимают путь виджета в качестве первого параметра, за которым следуют необязательные параметры, например:312313```python314destroy .315grid .frm.btn -column 0 -row 0316```317318Другие же больше похожи на методы, вызываемые для объекта виджета (на самом деле, при создании виджета в Tcl/Tk создаётся команда Tcl с именем пути к виджету, первым параметром которой является имя вызываемого метода).319320```python321.frm.btn invoke322.frm.lbl configure -text "Goodbye"323```324325В официальной справочной документации Tcl/Tk большинство операций, похожих на вызовы методов, находятся на странице руководства конкретного виджета (например, метод `invoke()` на странице руководства [ttk::button](https://python-all.ru/3.11/library/tkinter.html)), а функции, принимающие виджет в качестве параметра, часто имеют собственную страницу руководства (например, [grid](https://python-all.ru/3.11/library/tkinter.html)).326327Многие общие параметры и методы можно найти на man-страницах [options](https://python-all.ru/3.11/library/tkinter.html) или [ttk::widget](https://python-all.ru/3.11/library/tkinter.html), тогда как остальные находятся на man-странице конкретного класса виджета.328329Многие методы Tkinter имеют составные имена, например, `winfo_x()`, `winfo_height()`, `winfo_viewable()`. Документацию по всем ним можно найти на странице руководства [winfo](https://python-all.ru/3.11/library/tkinter.html).330331> **Примечание**332>333> Несколько сбивает с толку то, что у всех виджетов Tkinter есть методы, которые на самом деле не работают с виджетом, а действуют на глобальном уровне, независимо от какого-либо виджета. Примерами являются методы для доступа к буферу обмена или системному звонку. (Они реализованы как методы в базовом классе `Widget`, от которого наследуют все виджеты Tkinter).334335## Модель многопоточности336337Python и Tcl/Tk имеют очень разные модели многопоточности, которые [`tkinter`](https://python-all.ru/3.11/library/tkinter.html#module-tkinter) пытается согласовать. При использовании потоков следует учитывать это.338339Интерпретатор Python может иметь множество связанных с ним потоков. В Tcl можно создавать несколько потоков, но каждый поток имеет отдельный экземпляр интерпретатора Tcl. Потоки также могут создавать более одного экземпляра интерпретатора, но каждый экземпляр может использоваться только тем потоком, который его создал.340341Каждый объект `Tk`, созданный [`tkinter`](https://python-all.ru/3.11/library/tkinter.html#module-tkinter), содержит интерпретатор Tcl. Он также отслеживает, какой поток создал этот интерпретатор. Вызовы [`tkinter`](https://python-all.ru/3.11/library/tkinter.html#module-tkinter) могут производиться из любого потока Python. Внутренне, если вызов поступает из потока, отличного от создавшего объект `Tk`, в очередь событий интерпретатора помещается событие, и при его выполнении результат возвращается вызывающему потоку Python.342343Приложения Tcl/Tk обычно управляются событиями: после инициализации интерпретатор запускает цикл событий (т.е. `Tk.mainloop()`) и реагирует на события. Поскольку он однопоточный, обработчики событий должны быстро реагировать, иначе они будут блокировать обработку других событий. Чтобы избежать этого, длительные вычисления не должны выполняться в обработчике событий, а либо разбиваются на более мелкие части с помощью таймеров, либо выполняются в другом потоке. Это отличается от многих наборов инструментов для GUI, где GUI работает в совершенно отдельном потоке, отличном от всего кода приложения, включая обработчики событий.344345Если интерпретатор Tcl не выполняет цикл событий и не обрабатывает события, любые вызовы [`tkinter`](https://python-all.ru/3.11/library/tkinter.html#module-tkinter) из потоков, отличных от того, в котором работает интерпретатор Tcl, завершатся ошибкой.346347Существует ряд особых случаев:348349- Библиотеки Tcl/Tk могут быть собраны так, что они не поддерживают многопоточность. В этом случае [`tkinter`](https://python-all.ru/3.11/library/tkinter.html#module-tkinter) вызывает библиотеку из исходного потока Python, даже если он отличается от потока, создавшего интерпретатор Tcl. Глобальная блокировка гарантирует, что в каждый момент времени выполняется только один вызов.350- Хотя [`tkinter`](https://python-all.ru/3.11/library/tkinter.html#module-tkinter) позволяет создать более одного экземпляра объекта `Tk` (с собственным интерпретатором), все интерпретаторы, принадлежащие одному и тому же потоку, используют общую очередь событий, что быстро приводит к проблемам. На практике не следует создавать более одного экземпляра `Tk` одновременно. В противном случае лучше создавать их в отдельных потоках и убедиться, что используется сборка Tcl/Tk с поддержкой потоков.351- Блокирующие обработчики событий – не единственный способ помешать интерпретатору Tcl снова войти в цикл событий. Можно даже запускать несколько вложенных циклов событий или полностью отказаться от цикла событий. Если выполняются какие-либо нетривиальные действия с событиями или потоками, следует учитывать эти возможности.352- Существует несколько отдельных функций [`tkinter`](https://python-all.ru/3.11/library/tkinter.html#module-tkinter), которые в настоящее время работают только при вызове из потока, создавшего интерпретатор Tcl.353354## Краткий справочник355356### Установка опций357358Параметры управляют такими вещами, как цвет и ширина границы виджета. Параметры можно задать тремя способами:359360**При создании объекта – с помощью именованных аргументов**361362```python363fred = Button(self, fg="red", bg="blue")364```365366**После создания объекта – используя имя параметра как индекс словаря**367368```python369fred["fg"] = "red"370fred["bg"] = "blue"371```372373**Использовать метод config() для обновления нескольких атрибутов после создания объекта**374375```python376fred.config(fg="red", bg="blue")377```378379Полное объяснение конкретного параметра и его поведения можно найти на man-страницах Tk для соответствующего виджета.380381Обратите внимание, что man-страницы перечисляют «СТАНДАРТНЫЕ ПАРАМЕТРЫ» и «ПАРАМЕТРЫ, СПЕЦИФИЧНЫЕ ДЛЯ ВИДЖЕТА» для каждого виджета. Первое – список параметров, общих для многих виджетов, второе – параметры, свойственные конкретному виджету. Стандартные параметры задокументированы на man-странице *[options(3)](https://python-all.ru/3.11/library/tkinter.html)*.382383В этом документе не делается различий между стандартными и специфичными для виджета параметрами. Некоторые параметры не применимы к некоторым типам виджетов. Реагирует ли данный виджет на определённый параметр, зависит от класса виджета: кнопки имеют параметр `command`, а метки – нет.384385Опции, поддерживаемые данным виджетом, перечислены на странице руководства этого виджета, или их можно получить во время выполнения, вызвав метод `config()` без аргументов, или вызвав метод `keys()` для этого виджета. Возвращаемое значение этих вызовов – словарь, ключом которого является имя опции в виде строки (например, `'relief'`), а значениями – 5-кортежи.386387Некоторые параметры, например `bg`, являются синонимами распространённых параметров с длинными именами (`bg` – сокращение для «background»). При передаче методу `config()` имени сокращённого параметра будет возвращён 2-кортеж, а не 5-кортеж. Возвращаемый 2-кортеж содержит имя синонима и «реальный» параметр (например, `('bg', 'background')`).388389| Индекс | Значение | Пример |390| --- | --- | --- |391| 0 | имя параметра | `'relief'` |392| 1 | имя параметра для поиска в базе данных | `'relief'` |393| 2 | класс параметра для поиска в базе данных | `'Relief'` |394| 3 | значение по умолчанию | `'raised'` |395| 4 | текущее значение | `'groove'` |396397Пример:398399```python400>>> print(fred.config())401{'relief': ('relief', 'relief', 'Relief', 'raised', 'groove')}402```403404Разумеется, выведенный словарь будет содержать все доступные опции и их значения. Это приведено только в качестве примера.405406### Упаковщик407408Упаковщик – один из механизмов управления геометрией Tk. Менеджеры геометрии используются для задания относительного расположения виджетов внутри их контейнера – их общего *родителя*. В отличие от более громоздкого *разместителя* (который используется реже и здесь не рассматривается), упаковщик принимает качественные спецификации взаимосвязей – *сверху*, *слева от*, *заполнение* и т.д. – и сам вычисляет точные координаты размещения.409410Размер любого *родительского* виджета определяется размером находящихся внутри «дочерних виджетов». Упаковщик используется для управления тем, где дочерние виджеты появляются внутри родителя, в который они упакованы. Виджеты можно упаковывать во фреймы, а фреймы – в другие фреймы, чтобы добиться желаемого расположения. Кроме того, после упаковки расположение динамически настраивается для учета инкрементальных изменений конфигурации.411412Обратите внимание, что виджеты не отображаются, пока их геометрия не задана с помощью менеджера геометрии. Это распространенная ошибка новичков – пропустить задание геометрии и потом удивляться, что виджет создан, но ничего не отображается. Виджет появится только после того, как к нему будет применен, например, метод `pack()` упаковщика.413414Метод pack() можно вызывать с парами «ключевая опция/значение», которые управляют тем, где виджет будет располагаться внутри контейнера и как он будет вести себя при изменении размера главного окна приложения. Вот несколько примеров:415416```python417fred.pack()                     # по умолчанию side = "top"418fred.pack(side="left")419fred.pack(expand=1)420```421422### Опции упаковщика423424За более подробной информацией об упаковщике и его опциях обращайтесь к man-страницам и странице 183 книги Джона Оустерхаута.425426**привязка**427428Тип привязки. Указывает, где упаковщик должен размещать каждый дочерний виджет в его отведенной области.429430**расширение**431432Логическое значение, `0` или `1`.433434**заполнение**435436Допустимые значения: `'x'`, `'y'`, `'both'`, `'none'`.437438**ipadx и ipady**439440Расстояние – задает внутренний отступ с каждой стороны дочернего виджета.441442**padx и pady**443444Расстояние – задает внешний отступ с каждой стороны дочернего виджета.445446**сторона**447448Допустимые значения: `'left'`, `'right'`, `'top'`, `'bottom'`.449450### Привязка переменных виджетов451452Текущее значение некоторых виджетов (например, виджетов ввода текста) может быть напрямую связано с переменными приложения с помощью специальных опций. Эти опции: `variable`, `textvariable`, `onvalue`, `offvalue` и `value`. Такая связь работает в обе стороны: если переменная изменяется по какой-либо причине, связанный с ней виджет обновится, отображая новое значение.453454К сожалению, в текущей реализации [`tkinter`](https://python-all.ru/3.11/library/tkinter.html#module-tkinter) невозможно передать виджету произвольную переменную Python через опцию `variable` или `textvariable`. Единственные переменные, с которыми это работает, – это переменные, являющиеся подклассами класса Variable, определённого в [`tkinter`](https://python-all.ru/3.11/library/tkinter.html#module-tkinter).455456Уже определено много полезных подклассов Variable: `StringVar`, `IntVar`, `DoubleVar` и `BooleanVar`. Чтобы прочитать текущее значение такой переменной, вызовите метод `get()`, а чтобы изменить его – метод `set()`. При соблюдении этого протокола виджет всегда будет отслеживать значение переменной без дополнительного вмешательства.457458Например:459460```python461import tkinter as tk462463class App(tk.Frame):464    def __init__(self, master):465        super().__init__(master)466        self.pack()467468        self.entrythingy = tk.Entry()469        self.entrythingy.pack()470471        # Создайте переменную приложения.472        self.contents = tk.StringVar()473        # Установите её в некоторое значение.474        self.contents.set("this is a variable")475        # Укажите виджету ввода отслеживать эту переменную.476        self.entrythingy["textvariable"] = self.contents477478        # Определите колбэк для события нажатия Return.479        # Он выводит текущее значение переменной.480        self.entrythingy.bind('<Key-Return>',481                             self.print_contents)482483    def print_contents(self, event):484        print("Hi. The current entry content is:",485              self.contents.get())486487root = tk.Tk()488myapp = App(root)489myapp.mainloop()490```491492### Менеджер окон493494В Tk есть служебная команда `wm` для взаимодействия с менеджером окон. Опции команды `wm` позволяют управлять такими вещами, как заголовки, расположение, значки и тому подобное. В [`tkinter`](https://python-all.ru/3.11/library/tkinter.html#module-tkinter) эти команды реализованы как методы класса `Wm`. Виджеты верхнего уровня являются подклассами класса `Wm`, поэтому могут напрямую вызывать методы `Wm`.495496Чтобы получить окно верхнего уровня, содержащее данный виджет, часто можно просто обратиться к родителю виджета. Однако если виджет упакован внутрь фрейма, родитель не будет представлять окно верхнего уровня. Чтобы получить окно верхнего уровня, содержащее произвольный виджет, можно вызвать метод `_root()`. Этот метод начинается с подчеркивания, что указывает на то, что функция является частью реализации, а не интерфейсом к функциональности Tk.497498Вот несколько примеров типичного использования:499500```python501import tkinter as tk502503class App(tk.Frame):504    def __init__(self, master=None):505        super().__init__(master)506        self.pack()507508# создайте приложение509myapp = App()510511#512# здесь вызовы методов класса оконного менеджера513#514myapp.master.title("My Do-Nothing Application")515myapp.master.maxsize(1000, 400)516517# запустите программу518myapp.mainloop()519```520521### Типы данных опций Tk522523**привязка**524525Допустимые значения – направления компаса: `"n"`, `"ne"`, `"e"`, `"se"`, `"s"`, `"sw"`, `"w"`, `"nw"`, а также `"center"`.526527**битовая карта**528529Существует восемь встроенных именованных битовых карт: `'error'`, `'gray25'`, `'gray50'`, `'hourglass'`, `'info'`, `'questhead'`, `'question'`, `'warning'`. Чтобы указать имя файла X bitmap, укажите полный путь к файлу, начинающийся с `@`, например `"@/usr/contrib/bitmap/gumby.bit"`.530531**булевый**532533Можно передать целые числа 0 или 1 или строки `"yes"` или `"no"`.534535**колбэк**536537Это любая функция Python, которая не принимает аргументов. Например:538539```python540def print_it():541    print("hi there")542fred["command"] = print_it543```544545**цвет**546547Цвета можно задавать именами цветов X из файла rgb.txt или строками, представляющими значения RGB в 4-битном: `"#RGB"`, 8-битном: `"#RRGGBB"`, 12-битном: `"#RRRGGGBBB"` или 16-битном: `"#RRRRGGGGBBBB"` диапазонах, где R,G,B обозначают любую допустимую шестнадцатеричную цифру. Подробнее см. на стр. 160 книги Оустерхаута.548549**курсор**550551Можно использовать стандартные имена курсоров X из `cursorfont.h`, без префикса `XC_`. Например, чтобы получить курсор-руку (`XC_hand2`), используйте строку `"hand2"`. Можно также указать собственный файл битовой карты и маски. См. страницу 179 книги Оустерхаута.552553**расстояние**554555Экранные расстояния можно указывать в пикселях или абсолютных единицах. Пиксели задаются числами, а абсолютные расстояния – строками, где последний символ обозначает единицы: `c` для сантиметров, `i` для дюймов, `m` для миллиметров, `p` для типографских пунктов. Например, 3,5 дюйма записывается как `"3.5i"`.556557**шрифт**558559Tk использует формат имени шрифта в виде списка, например `{courier 10 bold}`. Размеры шрифта с положительными числами измеряются в пунктах; с отрицательными – в пикселях.560561**геометрия**562563Это строка вида `widthxheight`, где ширина и высота задаются в пикселях для большинства виджетов (в символах для виджетов, отображающих текст). Например: `fred["geometry"] = "200x100"`.564565**выравнивание**566567Допустимые значения – строки: `"left"`, `"center"`, `"right"` и `"fill"`.568569**регион**570571Это строка из четырёх разделённых пробелами элементов, каждый из которых является допустимым расстоянием (см. выше). Например: `"2 3 4 5"`, `"3i 2i 4.5i 2i"` и `"3c 2c 4c 10.43c"` – все являются допустимыми областями.572573**рельеф**574575Определяет стиль рамки виджета. Допустимые значения: `"raised"`, `"sunken"`, `"flat"`, `"groove"` и `"ridge"`.576577**команда прокрутки**578579Это почти всегда метод `set()` какого-либо виджета полосы прокрутки, но может быть любым методом виджета, принимающим один аргумент.580581**перенос**582583Должно быть одним из: `"none"`, `"char"` или `"word"`.584585### Привязки и события586587Метод bind из команды виджета позволяет отслеживать определённые события и вызывать функцию обратного вызова при наступлении события такого типа. Формат метода bind:588589```python590def bind(self, sequence, func, add=''):591```592593где:594595**последовательность**596597– это строка, обозначающая целевой тип события. (Подробнее см. страницу руководства *[bind(3tk)](https://python-all.ru/3.11/library/tkinter.html)* и страницу 201 книги Джона Оустерхаута *Tcl and the Tk Toolkit (2nd edition)*).598599**функция**600601– это функция Python, принимающая один аргумент, которая вызывается при наступлении события. В качестве аргумента будет передан экземпляр Event. (Функции, используемые таким образом, обычно называются *колбэками*.)602603**добавить**604605является необязательным, может быть `''` или `'+'`. Передача пустой строки означает, что эта привязка заменяет любые другие привязки, связанные с этим событием. Передача `'+'` означает, что эта функция добавляется в список функций, привязанных к данному типу события.606607Например:608609```python610def turn_red(self, event):611    event.widget["activeforeground"] = "red"612613self.button.bind("<Enter>", self.turn_red)614```615616Обратите внимание, как поле widget объекта события используется в `turn_red()` колбэке. Это поле содержит виджет, который перехватил событие X. В следующей таблице перечислены другие поля событий, к которым можно обратиться, и как они обозначаются в Tk; это может пригодиться при обращении к страницам руководства Tk.617618| Tk | Поле события Tkinter | Tk | Поле события Tkinter |619| --- | --- | --- | --- |620| %f | фокус | %A | char |621| %h | рост | %E | send\_event |622| %k | keycode | %K | keysym |623| %s | состояние | %N | keysym\_num |624| %t | time | %T | тип |625| %w | width | %W | widget |626| %x | x | %X | x\_root |627| %y | y | %Y | y\_root |628629### Параметр index630631Ряд виджетов требует передачи параметров «index». Они используются для указания на конкретное место в виджете Text, на определённые символы в виджете Entry или на конкретные пункты меню в виджете Menu.632633**Индексы виджета Entry (index, view index и т.д.)**634635Виджеты Entry имеют опции, относящиеся к позициям символов в отображаемом тексте. Для доступа к этим специальным точкам в текстовых виджетах можно использовать следующие функции [`tkinter`](https://python-all.ru/3.11/library/tkinter.html#module-tkinter):636637**Индексы виджета Text**638639Обозначение индексов для виджетов Text очень богатое и лучше всего описано на страницах руководства Tk.640641**Индексы меню (menu.invoke(), menu.entryconfig() и т.д.)**642643Некоторые опции и методы для меню работают с конкретными пунктами меню. Всякий раз, когда для опции или параметра требуется индекс меню, можно передать:644645- целое число, которое указывает на числовую позицию пункта в виджете, считая сверху, начиная с 0;646- строку `"active"`, которая указывает на позицию меню, находящуюся в данный момент под курсором;647- строку `"last"`, которая указывает на последний пункт меню;648- Целое число, перед которым стоит `@`, например `@6`, где целое число интерпретируется как координата y в пикселях в системе координат меню;649- строку `"none"`, которая указывает на отсутствие какого-либо пункта меню, чаще всего используется с menu.activate() для деактивации всех пунктов, и наконец,650- текстовую строку, которая сопоставляется с образцом с меткой пункта меню при сканировании сверху вниз. Обратите внимание, что этот тип индекса рассматривается после всех остальных, что означает, что совпадения для пунктов меню с метками `last`, `active` или `none` могут быть интерпретированы как указанные выше литералы.651652### Изображения653654Изображения разных форматов можно создать через соответствующий подкласс `tkinter.Image`:655656- `BitmapImage` для изображений в формате XBM.657- `PhotoImage` для изображений в форматах PGM, PPM, GIF и PNG. Последний поддерживается начиная с Tk 8.6.658659Оба типа изображений создаются с помощью опции `file` или `data` (доступны и другие опции).660661Затем объект изображения можно использовать везде, где какой-либо виджет (например, метки, кнопки, меню) поддерживает опцию `image`. В таких случаях Tk не хранит ссылку на изображение. Когда удаляется последняя ссылка на объект изображения из Python, данные изображения также удаляются, и Tk отображает пустой прямоугольник везде, где использовалось изображение.662663> **См. также**664>665> Пакет [Pillow](https://python-all.ru/3.11/library/tkinter.html) добавляет поддержку форматов BMP, JPEG, TIFF, WebP и других.666667## Обработчики файлов668669Tk позволяет регистрировать и удалять функцию обратного вызова, которая будет вызываться из главного цикла Tk, когда возможен ввод-вывод на файловом дескрипторе. Для каждого файлового дескриптора можно зарегистрировать только один обработчик. Пример кода:670671```python672import tkinter673widget = tkinter.Tk()674mask = tkinter.READABLE | tkinter.WRITABLE675widget.tk.createfilehandler(file, mask, callback)676...677widget.tk.deletefilehandler(file)678```679680Эта функция недоступна в Windows.681682Поскольку неизвестно, сколько байт доступно для чтения, не рекомендуется использовать методы [`BufferedIOBase`](https://python-all.ru/3.11/library/io.html#io.BufferedIOBase) или [`TextIOBase`](https://python-all.ru/3.11/library/io.html#io.TextIOBase) [`read()`](https://python-all.ru/3.11/library/io.html#io.BufferedIOBase.read) или [`readline()`](https://python-all.ru/3.11/library/io.html#io.IOBase.readline), так как они будут читать строго заданное количество байт. Для сокетов подойдут методы [`recv()`](https://python-all.ru/3.11/library/socket.html#socket.socket.recv) или [`recvfrom()`](https://python-all.ru/3.11/library/socket.html#socket.socket.recvfrom); для других файлов используйте необработанное чтение или `os.read(file.fileno(), maxbytecount)`.683684#### `Widget.tk.createfilehandler(file, mask, func)`685686Регистрирует функцию обратного вызова обработчика файла *func*. Аргумент *file* может быть объектом с методом [`fileno()`](https://python-all.ru/3.11/library/io.html#io.IOBase.fileno) (например, файлом или сокетом), либо целочисленным файловым дескриптором. Аргумент *mask* представляет собой комбинацию (побитовое ИЛИ) любых из трёх констант ниже. Колбэк вызывается следующим образом:687688```python689callback(file, mask)690```691692#### `Widget.tk.deletefilehandler(file)`693694Удаляет обработчик файла.695696#### `_tkinter.READABLE`697698#### `_tkinter.WRITABLE`699700#### `_tkinter.EXCEPTION`701702Константы, используемые в аргументе *mask*.703