25.1. tkinter - интерфейс Python к Tcl/Tk

Пакет tkinter ("Tk interface") - это стандартный интерфейс Python к набору инструментов Tk GUI. Оба - Tk и tkinter - доступны на большинстве Unix-платформ, так же как в системах Windows. (Tk сам по себе не является часть Python; он поддерживается ActiveState.)

Выполнение python -m tkinter из командной строки должно открыть окно, демонстрирующее простой интерфейс Tk и давая вам знать, что tkinter правильно установлен в вашей системе, также будет показана установленная версия Tcl/Tk, так что вы будете знать, какую версию документацию Tcl/Tk читать.

Смотрите также: Документация Tkinter:

Ресурсы Python Tkinter (wiki.python.org/moin/TkInter)
Гид темы Python Tkinter предоставляет множество информации по использованию Tk из Python и ссылки на другие информационные ресурсы по Tk.

TKDocs (www.tkdocs.com/)
Обширный учебный материал плюс дружественные страницы для некоторых виджет.

Справочник Tkinter: GUI для Python (infohost.nmt.edu/tcc/help/pubs/tkinter/web/index.html)
Онлайн справочный материал.

Документация Tkinter с effbot (effbot.org/tkinterbook/)
Онлайн справка по tkinter, поддерживаемая effbot.org.

Программирование на Python (learning-python.com/about-pp4e.html)
Книга Марка Лутца, включает превосходное освещение Tkinter.

Современный Tkinter для занятых разработчиков Python (www.amazon.com/Modern-Tkinter-Python-Developers-ebook/dp/B0071QDNLO/)
Книга Марка Розермана о создании привлекательного и современного графического интерфейса пользователя с помощью Python и Tkinter.

Программирование на Python и Tkinter (www.manning.com/books/python-and-tkinter-programming)
Книга Джона Грэйсона (ISBN 1-884777-81-3).

Документация по Tcl/Tk:

Команды Tk (https://www.tcl.tk/man/tcl8.6/TkCmd/contents.htm)
Большинство команд доступны как классы tkinter или tkinter.ttk. Измените '8.6' на версию Tcl/Tk, которая у вас установлена.

Свежие man-страницы по Tcl/Tk (www.tcl.tk/doc/)
Последние мануалы по Tcl/Tk на www.tcl.tk.

Домашняя страница Tcl на ActiveState (tcl.activestate.com/)
Развитие Tk/Tcl в основном происходит в ActiveState.

Набор инструментов Tcl и Tk (www.amazon.com/exec/obidos/ASIN/020163337X)
Книга Джона Оустерхаута, изобретателя Tcl.

Практическое программирование в Tcl и Tk (www.beedub.com/book/)
Энциклопедическая книга Брента Велча.

25.1.1. Модули Tkinter

В большинстве случаев tkinter - это все, что вам нужно. Однако также доступен ряд дополнительных модулей. Интерфейс Tk находится в бинарном модуле под именем _tkinter. Этот модуль содержит низкоуровневый интерфейс к Tk, и его не следует никогда использовать напрямую программистами приложений. Обычно это разделяемая библиотека (или DLL), но может в некоторых случаях быть статически связанной с интерпретатором Python.

В добавление к тому, что tkinter является модулем интерфейса к Tk, он включает ряд модулей Python, среди которых самым важным является tkinter.constants. Импорт tkinter автоматически импортирует tkinter.constants, так что для того, чтобы использовать Tkinter, все, что вам нужно, - простое выражение импорта:

import tkinter

Или более часто:

from tkinter import *

class tkinter.Tk(screenName=None, baseName=None, className='Tk', useTk=1)
Класс Tk создается без аргументов. Он создает верхнеуровневый виджет Tk, который обычно является главным окном приложения. У каждого экземпляра есть его собственный связанный с ним интерпретатор Tcl.

tkinter.Tcl(screenName=None, baseName=None, className='Tk', useTk=0)
Функция Tcl() является функцией-фабрикой, которая создает объект во многом подобный тому, который создается классом Tk, за исключением того, что он не инициализирует подсистему Tk. В большинстве случаев это полезно при управлении интерпретатором Tcl в среде, где вы не хотите создавать внешние окна верхнего уровня, или где это невозможно (например, системы Unix/Linux без X-сервера). Объект, созданный объектом Tcl(), может иметь верхнеуровневое окно, созданное (и подсистема Tk инициализирована) вызовом его метода loadtk().

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

tkinter.scrolledtext
Текстовый виджет со встроенным вертикальным скроллером.

tkinter.colorchooser
Диалог, позволяющий пользователю выбирать цвет.

tkinter.commondialog
Здесь перечислены базовые классы для диалоговых окон, определенных в других модулях.

tkinter.filedialog
Общие диалоги, позволяющие пользователю указать файл для открытия или сохранения.

tkinter.font
Утилиты, помогающие работать со шрифтами.

tkinter.messagebox
Доступ к стандартным диалоговым боксам Tk.

tkinter.simpledialog
Функции базовых диалогов и удобств.

tkinter.dnd
Поддержка drag-and-drop для tkinter. Он экспериментальный и должен стать устаревшим, когда будет заменен на Tk DND.

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

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

Этот раздел не создан, чтобы быть исчерпывающим руководством ни по Tk, ни по Tkinter. Скорее он предназначен как промежуточная остановка, обеспечивающая некоторую вводную ориентацию по системе.

Заслуги:

  • Tk был написан Джоном Оустерхаутом пока он работал в Беркли.
  • Tkinter был написан Стином Люмхольтом и Гвидо ван Россумом.
  • Этот Спасательный Круг был написан Мэтом Конвеем в университете Вирджиния.
  • HTML-рендеринг и некоторое вольное редактирование были сделаны из версии FrameMaker Кеном Макхеймером.
  • Фредрик Лунд разработал и пересмотрел описания интерфейса класса, чтобы получить их текущие с Tk 4.2.
  • Марк Кларксон преобразовал эту документацию в LaTex, и скомпилировал главу "Интерфейс пользователя" справочного руководства.

25.1.2.1. Как пользоваться этим разделом

Этот раздел состоит из двух частей: первая часть (приблизительно) касается материала заднего плана, в то время как вторая половина может быть взята на клавиатуру в качестве удобной справки.

Когда вы пытаетесь ответить на вопросы типа "как мне сделать эту чепуху", часто лучше узнать, как сделать "чепуху" непосредственно в Tk, и затем конвертировать это назад в соответствующий вызов tkinter. Программисты на Python часто могут угадать соответствующую команду Python, просматривая документацию Tk. Это означает, что для использования Tkinter вам нужно будет немного узнать о Tk. Этот документ не может выполнить эту роль, поэтому лучшее, что мы можем сделать, - это указать вам лучшую имеющуюся в наличии документацию. Вот некоторые подсказки:

  • Авторы настоятельно рекомендуют получить копию справочных страниц Tk. В частности, страницы man в каталоге manN наиболее полезны. Справочные страницы man3 описывают интерфейс C для библиотеки Tk и, следовательно, не особенно полезны для писателей скриптов.
  • Addison-Wesley публикует книгу "Tcl and the Tk Toolkit" Джона Оустерхаута (ISBN 0-201-63337-X). Она хороша для новичков для знакомства с Tcl и Tk. Книга не является исчерпывающей и за многими деталями отсылает к man-страницам.
  • tkinter/__init__.py - последнее прибежище для большинства, но может быть хорошим местом прийти сюда, когда ничего больше не имеет смыла.

25.1.2.2. Простая программа "Hello World"

import tkinter as tk

class Application(tk.Frame):
    def __init__(self, master=None):
        super().__init__(master)
        self.pack()
        self.create_widgets()

    def create_widgets(self):
        self.hi_there = tk.Button(self)
        self.hi_there["text"] = "Hello World\n(click me)"
        self.hi_there["command"] = self.say_hi
        self.hi_there.pack(side="top")

        self.quit = tk.Button(self, text="QUIT", fg="red",
                              command=root.destroy)
        self.quit.pack(side="bottom")

    def say_hi(self):
        print("hi there, everyone!")

root = tk.Tk()
app = Application(master=root)
app.mainloop()

25.1.3. (Очень) быстрый взгляд на Tcl/Tk

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

Примечания:

  • Эти классы предоставляются с целью организации определенных функций в одно пространство имен. Они не должны вызываться независимо.
  • Класс Tk должен вызываться только единожды в приложении. Прикладные программисты не обязаны делать это явно, система создает его всякий раз, когда создается какой-либо из других классов.
  • Класс Widget не предназначен для создания экземпляра, он предназначен только для подклассификации для создания "реальных" виджетов (в C++ это называется "абстрактный класс").

Чтобы использовать этот справочный материал, будут моменты, когда вам нужно будет знать, как читать короткие фрагменты Tk и как идентифицировать различные части команды Tk. (Смотрите раздел "Отображение базовых Tk в Tkinter" для эквивалентов tkinter).

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

Чтобы создать виджет в Tk, команда всегда имеет форму:

classCommand newPathname options

classCommand
обозначает, какой вид виджета создать (кнопку, метку, меню ...)

newPathname
есть новое имя этого виджета. Все имена в Tk должны быть уникальными. Чтобы обеспечить соблюдение этого, виджеты в Tk именуются с паснеймами (pathnames), подобно файлам в файловой системе. Виджет верхнего уровня, root, вызывается . (точкой), а дочерние разделяются большим количеством точек. Например, именем виджета может быть .myApp.controlPanel.okButton.

options
конфигурируют внешний вид виджета и в некоторых классах - его поведение. Опции представлены в виде списка флагов и значений. Флагам предшествует '-', подобно флагам командной оболочки Unix, значения помещаются в кавычки, если они состоят более чем из одного слова.

Например:

button   .fred   -fg red -text "hi there"
   ^       ^     \______________________/
   |       |                |
 class    new            options
command  widget  (-opt val -opt val ...)

Однажды созданный, pathname к виджету становится новой командой. Эта новая виджетная команда есть ручка управления программиста для получения этого виджета для выполнения некоторого действия. В C вы бы выразили это как someAction(fred, someOptions), в C++ вы бы выразили это как fred.someAction(someOptions), а в Tk вы скажете:

.fred someAction someOptions

Заметьте, что имя объекта, .fred, начинается с точки.

Как вы и ожидаете, правильное значение для someAction будет зависеть от класса виджета: .fred disable работает, если fred - кнопка (fred становится серым), но не работает, если fred является меткой (отключение меток не поддерживается в Tk).

Допустимое значение для someOptions зависит от действия. Некоторые действия, такие как disable, не требуют аргументов, другим, таким как команда delete бокса текстового поля, понадобятся аргументы для указания, какой диапазон текста удалять.

25.1.4. Отображение базового Tk в Tkinter

Команды классов в Tk соответствуют конструкторам классов в Tkinter.

button .fred                =====>  fred = Button()

Хозяин объекта скрыт в новом имени, данном ему в момент создания. В Tkinter родитель указывается явно.

button .panel.fred          =====>  fred = Button(panel)

В Tk конфигурационные опции задаются в виде списка разделенных дефисом тегов, за которыми следуют значения. В Tkinter опции указываются как ключевые слова-аргументы в конструкторе экземпляра, и ключевые слова-аргументы для конфигурационных вызовов или как индексы экземпляров, в стиле словаря, для установленных экземпляров. Смотрите раздел "Установка опций".

button .fred -fg red        =====>  fred = Button(panel, fg="red")
.fred configure -fg red     =====>  fred["fg"] = red
                            OR ==>  fred.config(fg="red")

В Tk, чтобы применить действие к виджету, используют имя виджета как команду, после чего следует имя действия, возможно с аргументами (опциями). В Tkinter вы вызываете методы к экземпляру класса, чтобы привязать действие у виджету. Действия (методы), которые данный виджет может выполнить, перечислены в tkinter/__init__.py.

.fred invoke                =====>  fred.invoke()

Чтобы передать виджет упаковщику (менеджеру геометрии), вы вызываете его с опциональными аргументами. В Tkinter всю эту функциональность содержит класс Pack, и различные формы упаковочных команд реализованы как методы. Все виджеты в tkinter являются подклассами от Packer, также наследуют все упаковочные методы. Смотрите документацию модуля tkinter.tix для дополнительной информации по формам геометрического менеджера.

pack .fred -side left       =====>  fred.pack(side="left")

25.1.5. Как связаны Tk и Tkinter

Сверху вниз:

Ваше приложение здесь (Python)
Приложение Python создает вызовы tkinter.

tkinter (пакет Питона)
Этот вызов (скажем, например, создании виджета кнопки) реализован в пакете tkinter, который написан на Python. Эта функция Python будет разбирать (парсить) команды и аргументы и конвертировать их в форму, которая сделает их выглядящими так, как если бы они поступили из скрипта Tk, а не скрипта Python. 

_tkinter (C)
Эти команды и их аргументы будут парситься к C-функциям в _tkinter - заметьте нижнее подчеркивание - модуль расширения.

Tk Widgets (C и Tcl)
Эта C-функция способна делать вызовы других C-модулей, включая C-функции, которые составляют библиотеку Tk. Tk реализован на C и немного Tcl. Tcl-часть виджет Tk используется для привязывания определенных поведений по-умолчанию к виджетам и выполняется однажды в месте, где импортируется пакет Питона tkinter. (Пользователи никогда не видят этот этап).

Tk (C)
Tk-часть виджет Tk реализует финальное отображение к ...

Xlib (C)
к библиотеке Xlib, чтобы нарисовать графику на экране.

25.1.6. Подручный справочник

25.1.6.1. Настройка опций

Опции (параметры) контролируют такие вещи как цвет и ширина границы виджет. Опции могут быть установлены тремя способами:

Во время создания объекта, используя аргументы с ключевым словом

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-кортеж, а не пятичленный. Этот возвращенный кортеж будет содержать имя синонима и "реальную" опцию (например, ('bg', 'background')).

Индекс Значение Пример
0 имя опции 'relief'
1 имя опции для поиска в базе данных 'relief'
2 класс опции для поиска в базе данных 'Relief'
3 значение по умолчанию 'raised'
4 текущее значение 'groove'

Пример:

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

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

25.1.6.2. Упаковщик

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

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

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

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

fred.pack()                     # по-умолчанию side = "top"
fred.pack(side="left")
fred.pack(expand=1)

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

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

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

expand
Булево значение, 0 или 1.

fill
Допустимые значения: 'x', 'y', 'both', 'none'.

ipadx и ipady
Расстояние, обозначающее внутренний отступ с каждой стороны подчиненного виджета.

padx и pady
Расстояние, обозначающее внешний отступ с каждой стороны подчиненного виджета.

side
Допустимые значения: 'left', 'right', 'top', 'bottom'.

25.1.6.4. Связывающие переменные виджетов

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

Создано