Spec-Zone.ru › Python 3.12

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)))

Как ориентироваться в справочном руководстве Tcl/Tk

Как уже упоминалось, официальное справочное руководство по командам Tk (страницы man) часто содержит наиболее точное описание того, что делают конкретные операции с виджетами. Даже если вы знаете название нужного параметра или метода, возможно, вам придётся искать сведения в нескольких местах.

Хотя в Tkinter все операции реализованы как вызовы методов объектов-виджетов, вы уже видели, что многие операции Tcl/Tk представлены командами, принимающими путевое имя виджета первым параметром, за которым могут следовать необязательные параметры. Например:

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

Другие операции, однако, больше похожи на методы, вызываемые для объекта-виджета (на самом деле при создании виджета в Tcl/Tk создаётся команда Tcl с именем, совпадающим с путевым именем виджета; первым параметром этой команды является имя вызываемого метода).

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

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

Многие распространённые параметры и методы описаны на страницах man options или ttk::widget, а остальные — на страницах man для конкретных классов виджетов.

Вы также заметите, что многие методы Tkinter имеют составные имена, например winfo_x(), winfo_height(), winfo_viewable(). Документацию по всем этим методам можно найти на странице man winfo.

Примечание

Несколько сбивает с толку то, что у всех виджетов Tkinter есть методы, которые фактически не работают с самим виджетом, а действуют глобально, независимо от какого-либо виджета. Например, методы для доступа к буферу обмена или системному звуковому сигналу. (Они реализованы как методы базового класса Widget, от которого наследуются все виджеты Tkinter.)

Модель потоков

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

имя параметра

'relief'

1

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

'relief'

2

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

'Relief'

3

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

'raised'

4

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

'groove'

Пример:

>>> 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

Spec-Zone.ru

Настройки Оффлайн Что нового Помощь О нас
Spec-Zone .ru
спецификации, руководства, описания, API