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 — не тонкая обёртка: он добавляет немало собственной логики, чтобы сделать работу более идиоматичной для Python. В этой документации основное внимание уделено этим дополнениям и изменениям; сведения о том, что осталось без изменений, см. в официальной документации Tcl/Tk.
Примечание
В Tcl/Tk 8.5 (2007) появился современный набор тематических компонентов пользовательского интерфейса и новый API для работы с ними. Оба API — старый и новый — по-прежнему доступны. Большая часть документации, которую можно найти в интернете, всё ещё описывает старый API и может быть безнадёжно устаревшей.
См. также
-
- TkDocs
-
Подробное руководство по созданию пользовательских интерфейсов с помощью Tkinter. В нём объясняются основные понятия и на примерах демонстрируются рекомендуемые подходы с использованием современного API.
-
- Справочник по Tkinter 8.5: графический интерфейс для Python
-
Справочная документация по Tkinter 8.5 с описанием доступных классов, методов и параметров.
Ресурсы по Tcl/Tk:
-
- Команды Tk
-
Исчерпывающий справочник по всем лежащим в основе Tkinter командам Tcl/Tk.
-
- Домашняя страница Tcl/Tk
-
Дополнительная документация и ссылки на разработку ядра Tcl/Tk.
Книги:
-
- Современный Tkinter для занятых разработчиков на Python
-
Автор: Марк Роузман. (ISBN 978-1999149567)
-
- Разработка графических интерфейсов на Python с помощью Tkinter
-
Автор: Алан Д. Мур. (ISBN 978-1788835886)
-
- Программирование на Python
-
Автор: Марк Лутц; книга отлично освещает Tkinter. (ISBN 978-0596158101)
-
- Tcl и набор инструментов Tk (2-е издание)
-
Авторы: Джон Оустерхаут, создатель Tcl/Tk, и Кен Джонс; Tkinter в книге не рассматривается. (ISBN 978-0321336330)
Архитектура
Tcl/Tk — не одна библиотека, а несколько отдельных модулей, каждый из которых имеет свои функции и собственную официальную документацию. Бинарные выпуски Python также поставляются с дополнительным модулем.
- Tcl
-
Tcl — динамический интерпретируемый язык программирования, как и Python. Хотя его можно использовать самостоятельно как язык общего назначения, чаще всего он встраивается в приложения на C в качестве сценарного движка или интерфейса к набору инструментов Tk. Библиотека Tcl предоставляет интерфейс на C для создания и управления одним или несколькими экземплярами интерпретатора Tcl, выполнения команд и сценариев Tcl в этих экземплярах, а также добавления пользовательских команд, реализованных на Tcl или C. У каждого интерпретатора есть очередь событий, а также средства для отправки событий в неё и их обработки. В отличие от Python, модель выполнения Tcl построена на кооперативной многозадачности, и Tkinter обеспечивает взаимодействие с этой особенностью (подробности см. в разделе Модель потоков).
- Tk
-
Tk — это пакет Tcl, реализованный на C и добавляющий пользовательские команды для создания графических элементов интерфейса и управления ими. Каждый объект
Tkсодержит собственный экземпляр интерпретатора Tcl с загруженным в него Tk. Виджеты Tk допускают широкую настройку, хотя и выглядят несколько устаревшими. Tk использует очередь событий Tcl для создания и обработки событий графического интерфейса. - Ttk
-
Тематический Tk (Ttk) — это более новое семейство виджетов Tk, внешний вид которых на разных платформах значительно лучше, чем у многих классических виджетов Tk. Начиная с версии Tk 8.5, Ttk распространяется вместе с Tk. Привязки для Python предоставляются в отдельном модуле
tkinter.ttk.
Внутри Tk и Ttk используют средства базовой операционной системы: Xlib в Unix/X11, Cocoa в macOS и GDI в Windows.
Когда приложение Python использует класс Tkinter, например для создания виджета, модуль tkinter сначала формирует строку команды Tcl/Tk. Затем он передаёт эту строку во внутренний бинарный модуль _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. - sync
-
Если задано
True, выполняет все команды X-сервера синхронно, чтобы ошибки сообщались немедленно. Можно использовать для отладки. (Только X11) - use
-
Задаёт id окна, в которое нужно встроить приложение, вместо создания его в виде независимого окна верхнего уровня. Значение id нужно указывать так же, как значение параметра -use для виджетов верхнего уровня (то есть оно имеет вид, подобный возвращаемому
winfo_id()).Обратите внимание: на некоторых платформах этот параметр будет работать правильно, только если id указывает на фрейм Tk или окно верхнего уровня, для которого включён параметр -container.
Tkсчитывает файлы профиля с именами.className.tclи.baseName.tcl, интерпретирует их в интерпретаторе Tcl и вызываетexec()для содержимого.className.pyи.baseName.py. Путь к файлам профиля задаётся переменной окруженияHOMEили, если она не определена, значениемos.curdir.-
tk -
Объект приложения Tk, созданный при создании экземпляра
Tk. Он обеспечивает доступ к интерпретатору Tcl. У каждого виджета, присоединённого к одному экземпляруTk, атрибутtkимеет одинаковое значение.
-
master -
Объект виджета, содержащего этот виджет. Для
Tkзначение master равноNone, поскольку это главное окно. Термины master и parent схожи и иногда взаимозаменяемо используются в качестве имён аргументов; однако вызовwinfo_parent()возвращает строку с именем виджета, аmasterвозвращает объект. Пара parent/child отражает древовидную структуру, а master/slave — структуру контейнеров.
-
children -
Непосредственные потомки этого виджета в виде
dict, где ключами являются имена дочерних виджетов, а значениями — объекты их экземпляров.
-
tkinter.Tcl(screenName=None, baseName=None, className='Tk', useTk=False) -
Функция
Tcl()— это фабричная функция, создающая объект, похожий на объект, созданный классомTk, но без инициализации подсистемы Tk. Чаще всего она полезна при работе с интерпретатором Tcl в среде, где не нужно создавать лишние окна верхнего уровня или где это невозможно (например, в системах Unix/Linux без X-сервера). Для объекта, созданного функциейTcl(), можно создать окно 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
Этот раздел не предназначен для исчерпывающего руководства ни по Tk, ни по Tkinter. Для этого обратитесь к одному из внешних ресурсов, упомянутых выше. Вместо этого раздел даёт краткое представление о том, как выглядит приложение Tkinter, знакомит с основными понятиями Tk и объясняет структуру обёртки Tkinter.
Остальная часть раздела поможет вам определить, какие классы, методы и параметры понадобятся в приложении Tkinter и где найти более подробную документацию по ним, в том числе в официальном справочном руководстве Tcl/Tk.
Программа «Привет, мир!»
Начнём с разбора приложения «Привет, мир!» на 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. Он также создаёт окно верхнего уровня, называемое корневым окном и служащее главным окном приложения.
Следующая строка создаёт виджет frame, который в данном случае будет содержать метку и кнопку, создаваемые далее. Этот frame размещается внутри корневого окна.
Затем создаётся виджет метки с неизменяемой текстовой строкой. Метод grid() задаёт относительное расположение метки внутри содержащего её виджета frame — аналогично тому, как работают таблицы в HTML.
Затем создаётся виджет кнопки и размещается справа от метки. При нажатии он вызовет метод destroy() корневого окна.
Наконец, метод mainloop() выводит все элементы на экран и обрабатывает пользовательский ввод до завершения программы.
Важные понятия Tk
Даже эта простая программа иллюстрирует следующие ключевые понятия Tk:
- виджеты
-
Пользовательский интерфейс Tkinter состоит из отдельных виджетов. Каждый виджет представлен объектом Python, созданным на основе таких классов, как
ttk.Frame,ttk.Labelиttk.Button. - иерархия виджетов
-
Виджеты организованы в иерархию. Метка и кнопка находятся внутри frame, который, в свою очередь, помещён в корневое окно. При создании каждого дочернего виджета его родительский виджет передаётся первым аргументом конструктору виджета.
- параметры конфигурации
-
У виджетов есть параметры конфигурации, изменяющие их внешний вид и поведение, например текст, отображаемый в метке или кнопке. У разных классов виджетов могут быть разные наборы параметров.
- управление геометрией
-
Виджеты не добавляются в пользовательский интерфейс автоматически при создании. За их размещение в интерфейсе отвечает менеджер геометрии, например
grid. - цикл обработки событий
-
Tkinter реагирует на пользовательский ввод, изменения в программе и даже обновляет экран только при активной работе цикла обработки событий. Если программа не выполняет этот цикл, пользовательский интерфейс не будет обновляться.
Как Tkinter оборачивает Tcl/Tk
Когда приложение использует классы и методы 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())
Поскольку у большинства виджетов много общих параметров конфигурации, полезно выяснить, какие из них относятся только к конкретному классу виджета. Для этого можно сравнить список параметров со списком для более простого виджета, например frame.
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).
В этом документе стандартные параметры не отделяются от специфичных для виджетов. Некоторые параметры неприменимы к определённым типам виджетов. Поддержка конкретного параметра зависит от класса виджета: у кнопок есть параметр command, а у меток его нет.
Список параметров, поддерживаемых виджетом, приведён на его справочной странице. Его также можно получить во время выполнения, вызвав метод config() без аргументов или метод keys() для этого виджета. Возвращаемое значение этих вызовов — словарь, в котором ключом служит имя параметра в виде строки (например, 'relief'), а значениями — кортежи из 5 элементов.
Некоторые параметры, например bg, являются сокращёнными именами распространённых параметров с длинными названиями (bg — это сокращение для «background»). Если передать методу config() имя сокращённого параметра, он вернёт кортеж из 2 элементов, а не из 5. Возвращаемый кортеж из 2 элементов содержит имя сокращённого параметра и «настоящее» имя параметра (например, ('bg', 'background')).
Индекс | Значение | Пример |
|---|---|---|
0 | имя параметра |
|
1 | имя параметра для поиска в базе данных |
|
2 | класс параметра для поиска в базе данных |
|
3 | значение по умолчанию |
|
4 | текущее значение |
|
Пример:
>>> print(fred.config())
{'relief': ('relief', 'relief', 'Relief', 'raised', 'groove')}
Разумеется, выведенный словарь будет содержать все доступные параметры и их значения. Это лишь пример.
Упаковщик
Упаковщик — один из механизмов управления геометрией в Tk. Менеджеры геометрии используются для задания взаимного расположения виджетов в контейнере — их общем родительском виджете. В отличие от более громоздкого размещателя (который используется реже и здесь не рассматривается), упаковщик позволяет задавать качественные отношения — выше, слева от, заполняя и т. д. — и самостоятельно рассчитывает точные координаты размещения.
Размер любого родительского виджета определяется размерами находящихся в нём «дочерних виджетов». Упаковщик управляет тем, где дочерние виджеты появляются внутри родительского виджета, в который они упакованы. Чтобы добиться нужной компоновки, можно упаковывать виджеты во фреймы, а фреймы — в другие фреймы. Кроме того, после упаковки расположение динамически корректируется при изменении конфигурации.
Обратите внимание, что виджеты не отображаются, пока для них не задана геометрия с помощью менеджера геометрии. Частая ошибка новичков — не указать геометрию, а затем удивляться, почему виджет создан, но ничего не появилось. Виджет появится только после того, как к нему, например, будет применён метод упаковщика pack().
Метод pack() можно вызвать с парами именованных параметров и значений, задающими расположение виджета в контейнере и его поведение при изменении размера главного окна приложения. Вот несколько примеров:
fred.pack() # defaults to side = "top" fred.pack(side="left") fred.pack(expand=1)
Параметры упаковщика
Более подробные сведения об упаковщике и принимаемых им параметрах см. на справочных страницах и на странице 183 книги Джона Оустерхаута.
- anchor
-
Тип привязки. Указывает, где упаковщик должен разместить каждый дочерний виджет в выделенной ему области.
- expand
-
Логическое значение:
0или1. - fill
-
Допустимые значения:
'x','y','both','none'. - ipadx и ipady
-
Расстояние, задающее внутренний отступ с каждой стороны дочернего виджета.
- padx и pady
-
Расстояние, задающее внешний отступ с каждой стороны дочернего виджета.
- side
-
Допустимые значения:
'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
- anchor
-
Допустимы обозначения сторон света:
"n","ne","e","se","s","sw","w","nw", а также"center". - bitmap
-
Встроено восемь именованных растровых изображений:
'error','gray25','gray50','hourglass','info','questhead','question','warning'. Чтобы указать имя файла растрового изображения X, укажите полный путь к файлу с префиксом@, например"@/usr/contrib/bitmap/gumby.bit". - boolean
-
Можно передать целые числа 0 или 1 либо строки
"yes"или"no". - callback
-
Любая функция Python, не принимающая аргументов. Например:
def print_it(): print("hi there") fred["command"] = print_it - color
-
Цвета можно задавать именами цветов X из файла rgb.txt либо строками со значениями RGB в 4-битном:
"#RGB", 8-битном:"#RRGGBB", 12-битном:"#RRRGGGBBB"или 16-битном:"#RRRRGGGGBBBB"формате, где R, G, B — любые допустимые шестнадцатеричные цифры. Подробности см. на странице 160 книги Оустерхаута. - cursor
-
Можно использовать стандартные имена курсоров X из
cursorfont.hбез префиксаXC_. Например, чтобы получить курсор в виде руки (XC_hand2), используйте строку"hand2". Также можно указать собственные файлы растрового изображения и маски. См. страницу 179 книги Оустерхаута. - distance
-
Расстояния на экране можно задавать в пикселях или абсолютных единицах. Пиксели указываются числами, а абсолютные расстояния — строками, последний символ которых обозначает единицу измерения:
cдля сантиметров,iдля дюймов,mдля миллиметров,pдля типографских пунктов. Например, 3,5 дюйма записываются как"3.5i". - font
-
В Tk используется формат имени шрифта в виде списка, например
{courier 10 bold}. Положительные размеры шрифта измеряются в пунктах, отрицательные — в пикселях. - geometry
-
Это строка вида
widthxheight, где ширина и высота для большинства виджетов измеряются в пикселях (а для виджетов, отображающих текст, — в символах). Например:fred["geometry"] = "200x100". - justify
-
Допустимые значения: строки
"left","center","right"и"fill". - region
-
Это строка из четырёх элементов, разделённых пробелами; каждый элемент представляет собой допустимое расстояние (см. выше). Например, допустимыми областями являются
"2 3 4 5","3i 2i 4.5i 2i"и"3c 2c 4c 10.43c". - relief
-
Определяет стиль границы виджета. Допустимые значения:
"raised","sunken","flat","groove"и"ridge". - scrollcommand
-
Почти всегда это метод
set()некоторого виджета полосы прокрутки, но им может быть любой метод виджета, принимающий один аргумент. - wrap
-
Значение должно быть одним из следующих:
"none","char"или"word".
Привязки и события
Метод bind команды виджета позволяет отслеживать определённые события и запускать функцию обратного вызова при возникновении события указанного типа. Метод bind имеет следующий формат:
def bind(self, sequence, func, add=''):
где:
- sequence
-
строка, обозначающая тип события. (Подробности см. на справочной странице bind(3tk) и на странице 201 книги Джона Оустерхаута
Tcl and the Tk Toolkit (2nd edition).) - func
-
функция Python, принимающая один аргумент и вызываемая при возникновении события. В качестве аргумента передаётся экземпляр Event. (Функции, используемые таким образом, обычно называют функциями обратного вызова.)
- add
-
необязательный параметр со значением
''или'+'. Пустая строка означает, что эта привязка заменит все остальные привязки, связанные с данным событием. Значение'+'означает, что эта функция будет добавлена в список функций, привязанных к данному типу события.
Например:
def turn_red(self, event):
event.widget["activeforeground"] = "red"
self.button.bind("<Enter>", self.turn_red)
Обратите внимание, что в функции обратного вызова turn_red() используется поле widget события. Это поле содержит виджет, получивший событие X. В следующей таблице перечислены другие поля события, к которым можно обращаться, и соответствующие им обозначения в Tk; они могут пригодиться при чтении справочных страниц Tk.
Tk | Поле события Tkinter | Tk | Поле события Tkinter |
|---|---|---|---|
%f | focus | %A | char |
%h | height | %E | send_event |
%k | keycode | %K | keysym |
%s | state | %N | keysym_num |
%t | time | %T | type |
%w | width | %W | widget |
%x | x | %X | x_root |
%y | y | %Y | y_root |
Параметр index
Для ряда виджетов требуется передавать параметры «index». Они указывают на конкретное место в виджете Text, на определённые символы в виджете Entry или на конкретные пункты меню в виджете Menu.
- Индексы виджета Entry (index, view index и т. д.)
-
У виджетов Entry есть параметры, указывающие на позиции символов в отображаемом тексте. Для доступа к этим специальным позициям в текстовых виджетах можно использовать следующие функции
tkinter: - Индексы виджета Text
-
Система обозначения индексов для виджетов 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(); для других файлов используйте чтение без буферизации или os.read(file.fileno(), maxbytecount).
-
Widget.tk.createfilehandler(file, mask, func) -
Регистрирует функцию обратного вызова обработчика файла func. Аргумент file может быть объектом с методом
fileno()(например, объектом файла или сокета) либо целочисленным файловым дескриптором. Аргумент mask — это объединение с помощью OR любых трёх приведённых ниже констант. Функция обратного вызова вызывается следующим образом:callback(file, mask)
-
Widget.tk.deletefilehandler(file) -
Отменяет регистрацию обработчика файла.
-
_tkinter.READABLE -
_tkinter.WRITABLE -
_tkinter.EXCEPTION -
Константы, используемые в аргументах mask.
© 2001–2024 Python Software Foundation
Licensed under the PSF License.
https://docs.python.org/3.12/library/tkinter.html