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

turtle

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

Спасательный круг Tkinter

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

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

В следующей строке создается виджет метки, содержащий статическую текстовую строку. Метод 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")

Полное объяснение той или иной опции и ее поведения можно найти на man-страницах Tk для соответствующего виджета.

Обратите внимание, что на man-страницах для каждого виджета перечислены «СТАНДАРТНЫЕ ОПЦИИ» и «СПЕЦИФИЧЕСКИЕ ОПЦИИ ВИДЖЕТА». Первые - это список опций, общих для многих виджетов, вторые - опции, характерные для конкретного виджета. Стандартные параметры документированы на странице options(3) man.

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

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

Некоторые опции, например bg, являются синонимами обычных опций с длинными именами (bg - сокращение от «background»). Если передать методу config() имя сокращенной опции, он вернет 2-кортеж, а не 5-кортеж. Переданный обратно кортеж будет содержать имя синонима и «настоящую» опцию (например, ('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 из команды widget позволяет следить за определенными событиями и вызывать функцию обратного вызова при наступлении этого типа события. Метод 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.

Тк

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

Тк

Поле события 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_root

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

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

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

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

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

Нотация индексов для виджетов Text очень богата и лучше всего описана на man-страницах 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 (возможны и другие варианты).

Изменено в версии 3.13: Добавлен метод PhotoImage copy_replace() для копирования области с одного изображения на другое, возможно, с пиксельным масштабированием и/или поддискретизацией. Добавьте параметр from_coords в методы PhotoImage copy(), zoom() и subsample(). Добавьте параметры zoom и subsample в метод PhotoImage copy().

Объект изображения можно использовать везде, где виджет поддерживает опцию 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 представляет собой исключающую комбинацию любых трех констант, указанных ниже. Обратный вызов выполняется следующим образом:

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

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

_tkinter.READABLE
_tkinter.WRITABLE
_tkinter.EXCEPTION

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