tkinter — Интерфейс Python для Tcl/Tk

Исходный код: Lib/tkinter/__init__.py.


Пакет tkinter («интерфейс Tk») - это стандартный интерфейс Python к набору инструментов графического интерфейса 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 reference: a GUI for Python

    Справочная документация для Tkinter 8.5 с подробным описанием доступных классов, методов и опций.

Ресурсы Tcl/Tk:

  • Tk commands

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

  • Tcl/Tk Home Page

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

Книги:

Архитектура

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

Tcl

Tcl - это динамический интерпретируемый язык программирования, такой же, как Python. Хотя он может использоваться самостоятельно как язык программирования общего назначения, чаще всего он встраивается в приложения на языке C в качестве скриптового механизма или интерфейса к набору инструментов Tk. Библиотека Tcl имеет интерфейс C для создания и управления одним или несколькими экземплярами интерпретатора Tcl, запуска команд и сценариев Tcl в этих экземплярах, а также добавления пользовательских команд, реализованных либо на Tcl, либо на C. Каждый интерпретатор имеет очередь событий, и есть средства для отправки событий в нее и их обработки. В отличие от Python, модель выполнения Tcl построена на кооперативной многозадачности, и Tkinter устраняет это различие (подробнее см. Threading model).

Tk

Tk - это Tcl package, реализованный на языке C, который добавляет пользовательские команды для создания и манипулирования виджетами графического интерфейса. Каждый объект Tk встраивает свой собственный экземпляр интерпретатора Tcl с загруженным в него Tk. Виджеты Tk очень настраиваемы, хотя и ценой устаревшего внешнего вида. Tk использует очередь событий Tcl для генерации и обработки событий GUI.

Ttk

Themed 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

Имя файла профиля. По умолчанию baseName берется из имени программы (sys.argv[0]).

className

Имя класса виджета. Используется как файл профиля, а также как имя, с которым вызывается Tcl (argv0 в interp).

useTk

Если True, инициализируйте подсистему Tk. Функция tkinter.Tcl() устанавливает это значение в False.

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

Если True, то все команды X-сервера выполняются синхронно, так что об ошибках сообщается немедленно. Может использоваться для отладки. (Только для X11)

использовать

Указывает id окна, в которое будет встроено приложение, вместо того, чтобы оно создавалось как независимое окно toplevel. id должен быть указан так же, как значение опции -use для двухуровневых виджетов (то есть иметь форму, подобную той, которую возвращает winfo_id()).

Обратите внимание, что на некоторых платформах это будет работать корректно, только если id ссылается на фрейм Tk или toplevel, у которого включена опция -container.

Tk читает и интерпретирует файлы профилей с именами .className.tcl и .baseName.tcl в интерпретаторе Tcl и вызывает exec() на содержимом .className.py и .baseName.py. Путь к файлам профиля задается переменной окружения HOME или, если она не определена, то os.curdir.

tk

Объект приложения Tk, созданный путем инстанцирования Tk. Он обеспечивает доступ к интерпретатору Tcl. Каждый виджет, присоединенный к одному экземпляру Tk, имеет одно и то же значение для своего атрибута tk.

master

Объект виджета, который содержит данный виджет. Для Tk мастером является 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(), может иметь созданное окно Toplevel (и инициализированную подсистему 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.

tkinter.tix

(устаревший) Старый сторонний пакет Tcl/Tk, добавляющий несколько новых виджетов. Лучшие альтернативы для большинства из них можно найти в tkinter.ttk.

turtle

Черепашья графика в окне Tk.

Tkinter Life Preserver

Этот раздел не является исчерпывающим руководством по Tk или Tkinter. Для этого обратитесь к одному из внешних ресурсов, указанных ранее. Вместо этого в данном разделе дается краткое представление о том, как выглядит приложение Tkinter, определяются основные концепции Tk и объясняется, как устроена обертка Tkinter.

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

Программа Hello World

Мы начнем с приложения «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. Он также создает окно верхнего уровня, известное как корневое окно, которое служит главным окном приложения.

Следующая строка создает виджет фрейма, который в данном случае будет содержать ярлык и кнопку, которые мы создадим дальше. Рамка помещается внутрь корневого окна.

Следующая строка создает виджет label, содержащий статическую текстовую строку. Метод grid() используется для указания относительного расположения (позиции) метки в содержащем ее виджете фрейма, аналогично тому, как работают таблицы в HTML.

Затем создается виджет кнопки, который размещается справа от метки. При нажатии он вызывает метод destroy() корневого окна.

Наконец, метод mainloop() выводит все на дисплей и отвечает на ввод пользователя до тех пор, пока программа не завершится.

Важные концепции Tk

Даже эта простая программа иллюстрирует следующие ключевые концепции Tk:

виджеты

Пользовательский интерфейс Tkinter состоит из отдельных виджетов. Каждый виджет представлен как объект Python, инстанцированный из классов ttk.Frame, ttk.Label и ttk.Button.

иерархия виджетов

Виджеты расположены в иерархии. Ярлык и кнопка содержатся в рамке, которая, в свою очередь, содержится в корневом окне. При создании каждого детского виджета его родительский виджет передается в качестве первого аргумента в конструктор виджетов.

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

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

управление геометрией

Виджеты не добавляются в пользовательский интерфейс автоматически при их создании. Такой геометрический менеджер, как grid, управляет тем, где в пользовательском интерфейсе они размещаются.

цикл событий

Tkinter реагирует на пользовательский ввод, изменения в вашей программе и даже обновляет дисплей только при активном выполнении цикла событий. Если ваша программа не выполняет цикл событий, ваш пользовательский интерфейс не будет обновляться.

Понимание того, как Tkinter оборачивает Tcl/Tk

Когда ваше приложение использует классы и методы Tkinter, внутри Tkinter собирает строки, представляющие команды Tcl/Tk, и выполняет эти команды в интерпретаторе Tcl, прикрепленном к экземпляру вашего приложения Tk.

Будь то навигация по справочной документации, попытка найти нужный метод или опцию, адаптация существующего кода или отладка приложения 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)))

Модель резьбы

Python и Tcl/Tk имеют очень разные модели потоков, которые tkinter пытается соединить. Если вы используете потоки, вам может понадобиться знать об этом.

Интерпретатор Python может иметь множество потоков, связанных с ним. В Tcl можно создать несколько потоков, но каждый поток имеет отдельный экземпляр интерпретатора Tcl, связанный с ним. Потоки также могут создавать более одного экземпляра интерпретатора, но каждый экземпляр интерпретатора может использоваться только одним потоком, который его создал.

Каждый объект Tk, созданный tkinter, содержит интерпретатор Tcl. Он также отслеживает, какой поток создал этот интерпретатор. Вызовы к tkinter могут быть сделаны из любого потока Python. Внутри, если вызов происходит из потока, отличного от того, который создал объект Tk, событие публикуется в очереди событий интерпретатора, а после выполнения результат возвращается в вызывающий поток Python.

Приложения Tcl/Tk обычно управляются событиями, то есть после инициализации интерпретатор запускает цикл событий (т.е. Tk.mainloop()) и реагирует на события. Поскольку интерпретатор однопоточный, обработчики событий должны реагировать быстро, иначе они будут блокировать обработку других событий. Чтобы избежать этого, любые длительные вычисления не должны выполняться в обработчике событий, а либо разбиваться на более мелкие части с помощью таймеров, либо выполняться в другом потоке. Это отличается от многих наборов инструментов GUI, где графический интерфейс работает в совершенно отдельном потоке от всего кода приложения, включая обработчики событий.

Если интерпретатор 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) man.

В этом документе не делается различий между стандартными и специфическими для виджетов опциями. Некоторые опции не применяются к некоторым видам виджетов. Реагирует ли данный виджет на определенную опцию, зависит от класса виджета; кнопки имеют опцию command, а ярлыки - нет.

Опции, поддерживаемые данным виджетом, перечислены в man-странице этого виджета или могут быть запрошены во время выполнения программы путем вызова метода config() без аргументов или путем вызова метода keys() на этом виджете. Возвращаемым значением этих вызовов является словарь, ключом которого является имя опции в виде строки (например, 'relief'), а значениями - 5 кортежей.

Некоторые опции, например bg, являются синонимами обычных опций с длинными именами (bg является сокращением для «background»). Передавая методу config() имя сокращенной опции, вы получите в ответ кортеж из двух, а не из пяти кортежей. Переданный обратно кортеж будет содержать имя синонима и «настоящую» опцию (например, ('bg', 'background')).

Индекс

Значение

Пример

0

имя опции

'relief'

1

имя опции для поиска в базе данных

'relief'

2

класс опций для поиска в базе данных

'Relief'

3

значение по умолчанию

'raised'

4

текущее значение

'groove'

Пример:

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

Конечно, в напечатанном словаре будут указаны все доступные опции и их значения. Это приведено только в качестве примера.

Пакер

Пакер - это один из механизмов управления геометрией в Tk. Менеджеры геометрии используются для указания относительного позиционирования виджетов внутри их контейнера - их общего мастера. В отличие от более громоздкого placer (который используется реже, и мы не рассматриваем его здесь), упаковщик принимает качественную спецификацию отношений - выше, слева от, заполняет и т.д. - и обрабатывает все, чтобы определить точные координаты размещения для вас.

Размер любого ведущего виджета определяется размером «ведомых виджетов» внутри него. Упаковщик используется для управления расположением подчиненных виджетов внутри мастера, в который они упакованы. Вы можете упаковывать виджеты во фреймы, а фреймы в другие фреймы, чтобы добиться желаемой компоновки. Кроме того, расположение динамически корректируется для учета постепенных изменений конфигурации после ее упаковки.

Обратите внимание, что виджеты не появляются до тех пор, пока их геометрия не будет определена с помощью менеджера геометрии. Это распространенная ранняя ошибка - не указать геометрию, а потом удивляться, когда виджет создается, но ничего не появляется. Виджет появится только после того, как к нему будет применен, например, метод упаковщика pack().

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

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

Опции упаковщика

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

якорь

Тип якоря. Обозначает место, куда упаковщик должен поместить каждого ведомого в его посылке.

расширить

Булево, 0 или 1.

заполнить

Законные значения: 'x', 'y', 'both', 'none'.

ipadx и ipady

Расстояние - обозначение внутренней прокладки с каждой стороны ведомого виджета.

падкс и пади

Расстояние - обозначение внешней прокладки с каждой стороны ведомого виджета.

сторона

Законными значениями являются: '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', 'question', 'warning'. Чтобы указать имя файла растрового изображения 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 бит: "#RRRRGGGGBBBB", где R, G, B представляют собой любые законные шестнадцатеричные цифры. Подробности см. на странице 160 книги Оустерхаута.

курсор

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

расстояние

Расстояния на экране могут быть заданы как в пикселях, так и в абсолютных расстояниях. Пиксели задаются в виде чисел, а абсолютные расстояния - в виде строк, где символ конца обозначает единицы измерения: c для сантиметров, i для дюймов, m для миллиметров, p для точек принтера. Например, 3,5 дюйма выражаются как "3.5i".

шрифт

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

геометрия

Это строка вида widthxheight, где ширина и высота измеряются в пикселях для большинства виджетов (в символах для виджетов, отображающих текст). Например: fred["geometry"] = "200x100".

обосновать

Законными значениями являются строки: "left", "center", "right" и "fill".

регион

Это строка с четырьмя элементами, разделенными пробелами, каждый из которых является законным расстоянием (см. выше). Например: "2 3 4 5" и "3i 2i 4.5i 2i" и "3c 2c 4c 10.43c" - все это законные области.

рельеф

Определяет стиль границ виджета. Допустимыми значениями являются: "raised", "sunken", "flat", "groove" и "ridge".

команда прокрутки

Почти всегда это метод set() какого-либо виджета полосы прокрутки, но это может быть любой метод виджета, принимающий один аргумент.

обернуть

Должен быть одним из: "none", "char" или "word".

Связки и события

Метод bind из команды виджета позволяет следить за определенными событиями и вызывать функцию обратного вызова при наступлении этого типа события. Метод bind имеет следующую форму:

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

где:

последовательность

это строка, обозначающая целевой тип события. (Подробнее см. страницу руководства bind(3tk) и страницу 201 книги Джона Оустерхаута Tcl and the Tk Toolkit (2nd edition)).

func

это функция Python, принимающая один аргумент, которая будет вызвана при наступлении события. В качестве аргумента будет передан экземпляр Event. (Функции, развернутые таким образом, широко известны как обратные вызовы).

добавить

является необязательной, либо '', либо '+'. Передача пустой строки означает, что эта привязка должна заменить все другие привязки, с которыми связано данное событие. Передача '+' означает, что эта функция должна быть добавлена в список функций, привязанных к данному типу события.

Например:

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

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

Обратите внимание, что в обратном вызове turn_red() происходит обращение к полю виджета события. Это поле содержит виджет, который поймал событие X. В следующей таблице перечислены другие поля событий, к которым вы можете получить доступ, и их обозначения в Tk, что может быть полезно при обращении к man-страницам Tk.

Tk

Поле события Tkinter

Tk

Поле события Tkinter

%f

фокус

%A

char

%h

высота

%E

send_event

%k

код ключа

%K

keysym

%s

государство

%N

keyym_num

%t

время

%T

тип

%w

ширина

%W

виджет

%x

x

%X

x_root

%y

y

%Y

y_корень

Индекс Параметр

Ряд виджетов требует передачи параметров «индекс». Они используются для указания на определенное место в виджете Text, или на определенные символы в виджете Entry, или на определенные пункты меню в виджете Menu.

Индексы виджетов ввода (индекс, индекс представления и т.д.)

Виджеты ввода имеют опции, которые относятся к позициям символов в отображаемом тексте. Вы можете использовать эти функции tkinter для доступа к этим специальным точкам в текстовых виджетах:

Индексы текстовых виджетов

Индексная нотация для виджетов Text очень богата и лучше всего описана на страницах руководства Tk.

Индексы меню (menu.invoke(), menu.entryconfig() и т.д.)

Некоторые опции и методы для меню управляют определенными пунктами меню. Каждый раз, когда для опции или параметра требуется индекс меню, вы можете передать его:

  • целое число, обозначающее числовую позицию записи в виджете, считая сверху, начиная с 0;

  • строка "active", которая относится к позиции меню, находящейся в данный момент под курсором;

  • строка "last", которая ссылается на последний пункт меню;

  • Целое число, которому предшествует @, как в @6, где целое число интерпретируется как координата пикселя y в системе координат меню;

  • строка "none", которая указывает на отсутствие пункта меню вообще, чаще всего используется с menu.activate() для деактивации всех пунктов, и, наконец,

  • текстовая строка, которая сопоставляется с меткой пункта меню при сканировании от верхней части меню к нижней. Обратите внимание, что этот тип индекса рассматривается после всех остальных, что означает, что совпадения с пунктами меню с метками last, active или none могут быть интерпретированы как вышеуказанные литералы.

Изображения

Изображения различных форматов могут быть созданы через соответствующий подкласс tkinter.Image:

  • BitmapImage для изображений в формате XBM.

  • PhotoImage для изображений в форматах PGM, PPM, GIF и PNG. Последний поддерживается начиная с версии Tk 8.6.

Любой тип изображения создается с помощью опции file или data (доступны и другие опции).

Затем объект изображения можно использовать везде, где опция image поддерживается каким-либо виджетом (например, ярлыки, кнопки, меню). В этих случаях Tk не будет сохранять ссылку на изображение. Когда последняя ссылка Python на объект изображения будет удалена, данные изображения также будут удалены, и Tk отобразит пустое поле везде, где использовалось изображение.

См.также

Пакет Pillow добавляет поддержку таких форматов, как BMP, JPEG, TIFF, WebP и др.

Обработчики файлов

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(); для других файлов используйте raw reads или os.read(file.fileno(), maxbytecount).

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

Регистрирует функцию обратного вызова обработчика файлов func. Аргумент file может быть либо объектом с методом fileno() (таким как файл или объект сокета), либо целочисленным дескриптором файла. Аргумент mask представляет собой ORed-комбинацию любых трех констант, указанных ниже. Обратный вызов вызывается следующим образом:

callback(file, mask)
Widget.tk.deletefilehandler(file)

Снимает с регистрации обработчик файлов.

tkinter.READABLE
tkinter.WRITABLE
tkinter.EXCEPTION

Константы, используемые в аргументах mask.

Вернуться на верх