Как изменить вид python

Как настроить IDLE Python под себя для приятной работы

Раздел: Статьи /
Питон /

Все способы изучить Python

Все способы изучить Python

Каждый раз, изучая какую-то новую науку, мы задаёмся вопросом — где взять обучающие материалы. Конечно, сегодня нам помогает в этом Интернет. Но иногда на поиски уходит очень много времени, а нужного результата мы не получаем… Собрал для вас кучу полезных ссылок для изучения Python. не благодарите )))
Подробнее…

Среда разработки IDLE Shell достаточно проста, если сравнивать с другими средствами разработки, такими как Delphi или Visual Studio, или со средствами разработки на Python от сторонних разработчиков. Однако и её тоже не помешает настроить под свои предпочтения.

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

Настройки IDLE выполняются в окне настроек, которое вызывается через меню


OPTIONS - CONFIGURE IDLE

Окно настроек содержит пять вкладок (страниц):

Окно настроек IDLE: вкладка ШРИФТЫ И ТАБУЛЯЦИЯ

Рис. 1-3-1. Окно настроек IDLE: вкладка ШРИФТЫ И ТАБУЛЯЦИЯ

Шрифты и табуляция

На первой вкладке FONTS/TABS (шрифты/табуляция) можно выбрать шрифт и установить размер табуляции.

Для исходных кодов лучше выбирать моноширинный шрифт (шрифт с одинаковой шириной всех символов). Я предпочитаю Courier New.

Ниже (под списком шрифтов) можно выбрать размер шрифта, а также сделать его жирным.

Справа предварительный просмотр выбранного шрифта.

Также вы можете установить размер табуляции (то есть на какое количество пробелов будет перемещаться курсор при нажатии на клавишу ТАВ). Значение по умолчанию равно 4. Но я всегда ставлю 2, чтобы код не расползался в ширину при наличии множества вложенных блоков.

Подсветка синтаксиса

Я работаю в разных средах разработки с разными языками. И практически в каждой среде разработки свои предпочтения по цвету ключевых слов, строк, цифр и т.п. Но мне не нравится, когда подсветка синтаксиса отличается от привычной. Поэтому, когда я устанавливаю какую-то новую IDE, то я первым делом настраиваю цвета текста в редакторе исходного кода.

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

Но если захотите изменить, то переходите на вкладку HIGHLIGHTS (подсветка), и устанавливайте цвета, какие вам больше нравятся:

Окно настроек IDLE: вкладка ПОДСВЕТКА СИНТАКСИСА

Рис. 1-3-2. Окно настроек IDLE: вкладка ПОДСВЕТКА СИНТАКСИСА

Если в группе SELECT вы выберите “a Built-in Theme” (встроенные темы), то установится подсветка по умолчанию. В этом случае можно будет выбрать одну из трёх предустановленных тем:

  • IDLE Classic
  • IDLE Dark
  • IDLE New

Если же вы выберите “a Custom Theme” (пользовательская тема), то можете установить свои цвет текста и цвет фона для любого доступного элемента (для ключевых слов, для чисел, для строк и т.п.). Вы можете создать несколько собственных тем.

После того, как вы вдоволь наиграетесь с выбором цветов, надо щёлкнуть по кнопке APPLY, чтобы изменения вступили в силу. Если вы создали свою тему, то её нужно сохранить с помощью кнопки “Save as New Custom Theme”.

Цвета изменяются отдельно для текста (Foreground) и для фона (Background). Для изменения текста или фона должен быть выбран соответствующий переключатель (см. рис. 1-3-2).

Чтобы установить цвет для элемента — щёлкните по кнопке с надписью “Choose Color For” и в открывшемся окне установите нужный цвет.

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

Чтобы выбрать элемент для изменения цвета, можно также щёлкнуть по элементу в окне предварительного просмотра.

Остальные три вкладки рассматривать не будем — для начинающих они пока не нужны.

Если что-то осталось непонятным, то посмотрите видео:

Учимся программировать на Python

Учимся программировать на Python

Python — один из самых востребованных языков программирования. Подпишитесь на бесплатную рассылку и получайте статьи и видео о программировании на Python.
Подробнее…

Если вы недавно загрузили Python на свой компьютер, то, возможно, вы заметили новую программу на вашем компьютере под названием IDLE . Вы можете спросить: «Что эта программа делает на моем компьютере? Я не скачал это! Хотя вы, возможно, не загружали эту программу самостоятельно, IDLE поставляется в комплекте с каждой установкой Python. Он поможет вам начать работу с языком прямо из коробки. Из этого руководства вы узнаете, как работать в Python IDLE, и несколько интересных приемов, которые вы можете использовать в своем путешествии по Python!

*В этом уроке вы узнаете:*
  • Что такое Python IDLE

  • Как взаимодействовать с Python напрямую, используя IDLE

  • Как редактировать, выполнять и отлаживать файлы Python с помощью IDLE

  • Как настроить Python IDLE на свой вкус

    *Бесплатный бонус:* ссылка: [Нажмите здесь, чтобы получить шпаргалку Python] и изучить основы Python 3, такие как работа с типами данных, словарями, списками и функциями Python.

Что такое Python IDLE?

Каждая установка Python поставляется с Интегрированной средой разработки и обучения , которую вы увидите сокращенной до IDLE или даже IDE. Это класс приложений, которые помогают вам писать код более эффективно. Хотя существует множество IDEs на ваш выбор, Python IDLE очень прост, что делает его идеальным инструментом для начинающего программиста.

Python IDLE входит в состав установки Python на Windows и Mac. Если вы являетесь пользователем Linux, то вы сможете найти и загрузить Python IDLE с помощью вашего менеджера пакетов. После установки вы можете использовать Python IDLE в качестве интерактивного интерпретатора или редактора файлов.

Интерактивный переводчик

Лучшее место для экспериментов с кодом Python — это interactive интерпретатор, иначе известный как shell . Оболочка представляет собой простой Read-Eval-Print Loop (REPL). Он читает инструкцию Python, оценивает результат этой инструкции, а затем выводит результат на экран. Затем он возвращается к следующему оператору.

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

Редактор файлов

Каждый программист должен иметь возможность редактировать и сохранять текстовые файлы. Программы Python — это файлы с расширением + .py +, которые содержат строки кода Python. Python IDLE дает вам возможность создавать и редактировать эти файлы с легкостью.

Python IDLE также предоставляет несколько полезных функций, которые вы увидите в профессиональных IDE, таких как подсветка основного синтаксиса, автозавершение кода и авто-отступ. Профессиональные IDE — более надежные части программного обеспечения, и у них крутая кривая обучения. Если вы только начинаете свое программирование на Python, то Python IDLE — отличная альтернатива!

Как использовать оболочку Python IDLE

Оболочка является режимом работы по умолчанию для Python IDLE. Когда вы нажимаете на значок, чтобы открыть программу, оболочка — это первое, что вы видите:

Blank Python Interpreter в IDLE

Это пустое окно интерпретатора Python. Вы можете использовать его, чтобы сразу начать взаимодействовать с Python. Вы можете проверить это с помощью короткой строки кода:

Hello Мировая программа

Здесь вы использовали + print () +, чтобы вывести строку " Hello, from IDLE! " На ваш экран. Это самый простой способ взаимодействия с Python IDLE. Вы вводите команды по одной за раз, и Python отвечает результатом каждой команды.

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

the строка меню для IDLE с отображенным меню Shell

Вы можете перезапустить оболочку из этого меню. Если вы выберете эту опцию, вы очистите состояние оболочки. Он будет действовать так, как будто вы запустили новый экземпляр Python IDLE. Оболочка забудет обо всем из своего предыдущего состояния:

В результате выполнения некоторый код в оболочке IDLE

На изображении выше вы сначала объявляете переменную + x = 5 +. Когда вы вызываете + print (x) +, оболочка показывает правильный вывод, который является числом + 5 +. Однако, когда вы перезапустите оболочку и попытаетесь снова вызвать + print (x) +, вы увидите, что оболочка печатает traceback. Это сообщение об ошибке, в котором говорится, что переменная + x + не определена. Оболочка забыла обо всем, что было до перезапуска.

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

Отправка прерывания клавиатуры с параметром «Выполнение прерывания» в IDLE строка меню приведет к чему-то похожему на это. При выборе этой опции выполнение этой программы было остановлено.

Сообщение об ошибке + KeyboardInterrupt + отображается красным текстом в нижней части окна. Программа получила прерывание и прекратила выполнение.

Как работать с файлами Python

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

Открытие файла

Чтобы запустить новый файл Python, выберите File → New File в строке меню. Это откроет пустой файл в редакторе, например так:

shows пустой файл после открытия нового файла для редактирования в IDLE

Из этого окна вы можете написать новый файл Python. Вы также можете открыть существующий файл Python, выбрав _File → Open… _ в строке меню. Это откроет браузер файлов вашей операционной системы. Затем вы можете найти файл Python, который хотите открыть.

Если вы заинтересованы в чтении исходного кода для модуля Python, вы можете выбрать File → Path Browser. Это позволит вам просматривать модули, которые может видеть Python IDLE. Если дважды щелкнуть один из них, откроется редактор файлов, и вы сможете его прочитать.

Содержимое этого окна будет таким же, как пути, возвращаемые при вызове + sys.path +. Если вы знаете имя определенного модуля, который хотите просмотреть, вы можете выбрать File → Module Browser и ввести имя модуля в появившемся окне.

Редактирование файла

После того, как вы открыли файл в Python IDLE, вы можете внести в него изменения. Когда вы будете готовы отредактировать файл, вы увидите что-то вроде этого:

an открыл файл Python в IDLE

Содержимое вашего файла отображается в открытом окне. Панель в верхней части окна содержит три важных элемента:

  1. Имя файла, который вы редактируете

  2. Полный путь к папке, где вы можете найти этот файл на вашем компьютере

  3. Версия Python, которую использует IDLE

На изображении выше вы редактируете файл + myFile.py +, который находится в папке + Documents +. Версия Python 3.7.1, которую вы можете увидеть в скобках.

В правом нижнем углу окна также есть две цифры:

  1. Ln: показывает номер строки, на которой находится ваш курсор.

  2. Col: показывает номер столбца, на котором находится ваш курсор.

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

В этом окне есть несколько визуальных подсказок, которые помогут вам не забыть сохранить свою работу. Если вы посмотрите внимательно, то увидите, что Python IDLE использует звездочки, чтобы сообщить вам, что в вашем файле есть несохраненные изменения:

показывает

Имя файла, отображаемое в верхней части окна IDLE, окружено звездочками. Это означает, что в вашем редакторе есть несохраненные изменения. Вы можете сохранить эти изменения с помощью стандартного сочетания клавиш вашей системы или выбрать Файл → Сохранить в строке меню. Убедитесь, что вы сохранили свой файл с расширением + .py +, чтобы подсветка синтаксиса была включена.

Выполнение файла

Если вы хотите выполнить файл, который вы создали в IDLE, вы должны сначала убедиться, что он сохранен. Помните, что вы можете увидеть, правильно ли сохранен ваш файл, посмотрев звездочки вокруг имени файла в верхней части окна редактора файлов. Не беспокойся, если забудешь! Python IDLE будет напоминать вам о необходимости сохранения всякий раз, когда вы пытаетесь выполнить несохраненный файл.

Чтобы выполнить файл в режиме IDLE, просто нажмите клавишу F5 на клавиатуре. Вы также можете выбрать Run → Run Module в строке меню. Любой из вариантов перезапустит интерпретатор Python, а затем запустит код, который вы написали, с новым интерпретатором. Процесс такой же, как когда вы запускаете + python3 -i [имя файла] + в вашем терминале.

Когда ваш код будет выполнен, интерпретатор будет знать все о вашем коде, включая любые глобальные переменные, функции и классы. Это делает Python IDLE отличным местом для проверки ваших данных, если что-то пойдет не так. Если вам когда-нибудь понадобится прервать выполнение вашей программы, вы можете нажать [.keys] # Ctrl + C # в интерпретаторе, который выполняет ваш код.

Как улучшить ваш рабочий процесс

Теперь, когда вы увидели, как писать, редактировать и выполнять файлы в Python IDLE, пришло время ускорить ваш рабочий процесс! Редактор Python IDLE предлагает несколько функций, которые вы увидите в большинстве профессиональных IDE, чтобы помочь вам быстрее кодировать. Эти функции включают в себя автоматическое отступление, завершение кода и советы по вызову, а также контекст кода.

Автоматический отступ

IDLE автоматически сделает отступ для вашего кода, когда ему нужно начать новый блок. Обычно это происходит после ввода двоеточия (+: +). Когда вы нажимаете клавишу ввода после двоеточия, курсор автоматически перемещается на определенное количество пробелов и начинает новый блок кода.

Вы можете настроить, сколько пробелов будет перемещать курсор в настройках, но по умолчанию используются стандартные четыре пробела. Разработчики Python согласовали стандартный стиль для хорошо написанного кода Python, который включает в себя правила для отступов, пробелов и многого другого. Этот стандартный стиль был формализован и теперь известен как PEP 8 . Чтобы узнать больше об этом, ознакомьтесь с Как написать красивый код Python с помощью PEP 8.

Завершение кода и Советы по вызову

Когда вы пишете код для большого проекта или сложной проблемы, вы можете потратить много времени, просто набирая весь необходимый код. Завершение кода помогает вам сэкономить время, пытаясь завершить ваш код для вас. Python IDLE имеет базовую функциональность завершения кода. Это может только автозаполнение имен функций и классов. Чтобы использовать автозаполнение в редакторе, просто нажмите клавишу табуляции после последовательности текста.

Python IDLE также предоставит советы по звонкам. Подсказка вызова — это подсказка для определенной части вашего кода, которая поможет вам вспомнить, что нужно этому элементу. После того, как вы введете левую скобку, чтобы начать вызов функции, появится подсказка о вызове, если вы ничего не наберете в течение нескольких секунд. Например, если вы не совсем помните, как добавить к list, вы можете сделать паузу после открывающей скобки, чтобы вызвать подсказку вызова:

displays простой совет для вызова метода append с питоном список

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

Контекст кода

Функциональность code context — это удобная функция редактора файлов Python IDLE. Он покажет вам область действия функции, класса, цикла или другой конструкции. Это особенно полезно, когда вы просматриваете длинный файл и вам нужно отслеживать, где вы находитесь, просматривая код в редакторе.

Чтобы включить его, выберите Options → Code Context в строке меню. Вы увидите серую полосу в верхней части окна редактора:

show функция контекста кода редактора бездействия

Когда вы прокручиваете свой код вниз, context , содержащий каждую строку кода, будет оставаться внутри этой серой полосы. Это означает, что функции + print () +, которые вы видите на изображении выше, являются частью функции main. Когда вы достигнете линии, выходящей за рамки этой функции, панель исчезнет.

Как отлаживать в IDLE

*Ошибка* - неожиданная проблема в вашей программе. Они могут появляться во многих формах, и некоторые из них труднее исправить, чем другие. Некоторые ошибки достаточно хитры, и вы не сможете их обнаружить, просто прочитав свою программу. К счастью, Python IDLE предоставляет некоторые базовые инструменты, которые помогут вам https://realpython.com/courses/python-debugging-pdb/[debug] ваши программы с легкостью!

Режим интерпретатора DEBUG

Если вы хотите запустить свой код с помощью встроенного отладчика, то вам нужно включить эту функцию. Для этого выберите Debug → Debugger в строке меню Python IDLE. В интерпретаторе вы должны увидеть + [DEBUG ON] + перед запросом (+ >>> +), что означает, что интерпретатор готов и ожидает.

Когда вы запустите ваш файл Python, появится окно отладчика:

shows пустое окно отладчика в режиме ожидания Python

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

Вы также можете нажать следующие кнопки для перемещения по коду:

  • Go: Нажмите эту кнопку, чтобы перейти к следующему breakpoint. Вы узнаете об этом в следующем разделе.

  • Шаг: Нажмите, чтобы выполнить текущую строку и перейти к следующей.

  • Over: Если текущая строка кода содержит вызов функции, нажмите эту кнопку, чтобы перейти на over эту функцию. Другими словами, выполните эту функцию и перейдите к следующей строке, но не делайте паузу во время выполнения функции (если не существует точки останова).

  • Out: Если текущая строка кода находится в функции, нажмите эту кнопку, чтобы перейти к шагу out этой функции. Другими словами, продолжайте выполнение этой функции, пока не вернетесь к ней.

Будьте осторожны, потому что нет кнопки реверса! Вы можете только сделать шаг вперед во время выполнения вашей программы.

Вы также увидите четыре флажка в окне отладки:

  1. Globals: глобальная информация о вашей программе

  2. Locals: локальная информация вашей программы во время выполнения

  3. Стек: функции, которые запускаются во время выполнения

  4. Источник: Ваш файл в редакторе IDLE

Выбрав один из них, вы увидите соответствующую информацию в окне отладки.

Контрольные точки

*Точка останова* - это строка кода, которую вы определили как место, где интерпретатор должен приостановить выполнение кода. Они будут работать только при включенном режиме _DEBUG_, поэтому убедитесь, что вы сделали это в первую очередь.

Чтобы установить точку останова, щелкните правой кнопкой мыши строку кода, которую вы хотите приостановить. Это выделит строку кода желтым цветом как визуальную индикацию установленной точки останова. Вы можете установить столько точек останова в своем коде, сколько захотите. Чтобы отменить точку останова, снова щелкните правой кнопкой мыши на той же строке и выберите Clear Breakpoint.

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

Ошибки и исключения

Когда вы видите сообщение об ошибке в интерпретаторе, Python IDLE позволяет перейти прямо к файлу или строке, вызвавшей сбой, из строки меню. Все, что вам нужно сделать, это выделить номер строки или имя файла указанным курсором и выбрать Debug → Перейти к файлу/строке в строке меню. Это откроет файл-нарушитель и приведет вас к строке, содержащей ошибку. Эта функция работает независимо от того, включен ли режим DEBUG.

Python IDLE также предоставляет инструмент, который называется stack viewer . Вы можете получить к нему доступ через параметр Debug в строке меню. Этот инструмент покажет вам traceback ошибки, как она появляется в стеке последней ошибки, или exception что Python IDLE встретился при запуске вашего кода. Когда происходит неожиданная или интересная ошибка, вам может быть полезно взглянуть на стек. В противном случае эту функцию может быть сложно разобрать, и, вероятно, она вам не пригодится, если вы не пишете очень сложный код.

Как настроить Python IDLE

Существует множество способов придания Python IDLE визуального стиля, который вам подходит. Внешний вид по умолчанию основан на цветах в логотипе Python. Если вам не нравится, как что-то выглядит, то вы почти всегда можете изменить это.

Для доступа к окну настройки выберите Options → Configure IDLE в строке меню. Чтобы просмотреть результат изменения, которое вы хотите внести, нажмите Apply. Когда вы закончите настройку Python IDLE, нажмите OK, чтобы сохранить все ваши изменения. Если вы не хотите сохранять изменения, просто нажмите Cancel.

Существует 5 областей Python IDLE, которые вы можете настроить:

  1. Шрифты/Tabs

  2. Особенности

  3. Keys

  4. генеральный

  5. расширения

Давайте посмотрим на каждого из них сейчас.

Шрифты/Tabs

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

the окно настроек шрифта настройки простоя панель

Вы можете использовать окно прокрутки, чтобы выбрать, какой шрифт вы предпочитаете. (Я рекомендую вам выбрать шрифт фиксированной ширины, например Courier New.) Выберите размер шрифта, который достаточно велик, чтобы вы могли хорошо видеть. Вы также можете установить флажок рядом с Bold, чтобы включить или отключить отображение всего текста жирным шрифтом.

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

Особенности

Вторая вкладка настройки позволит вам изменить основные моменты. Подсветка синтаксиса — важная особенность любой IDE, которая выделяет синтаксис языка, на котором вы работаете. Это помогает вам визуально различать различные конструкции Python и данные, используемые в вашем коде.

Python IDLE позволяет полностью настроить внешний вид вашего кода Python. Он предустановлен с тремя различными темами подсветки:

  1. IDLE Day

  2. IDLE Night

  3. IDLE Новый

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

показывает панель настройки подсветки синтаксиса

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

Затем вам будет предложено сохранить эту тему как новую пользовательскую тему, и вы сможете ввести имя по вашему выбору. Затем вы можете продолжить менять цвета разных предметов, если хотите. Не забудьте нажать Apply, чтобы увидеть ваши изменения в действии!

Keys

Третья вкладка настройки позволяет сопоставить различные нажатия клавиш с действиями, также известными как сочетания клавиш . Это жизненно важный компонент вашей производительности, когда вы используете IDE. Вы можете придумать свои собственные сочетания клавиш или использовать те, которые поставляются с IDLE. Предварительно установленные ярлыки — хорошее место для начала:

python панель настройки сочетаний клавиш для режима ожидания простоя

Сочетания клавиш перечислены в алфавитном порядке по действию. Они перечислены в формате Action — Shortcut, где Action — это то, что произойдет, когда вы нажмете комбинацию клавиш в Shortcut. Если вы хотите использовать встроенный набор ключей, выберите сопоставление, соответствующее вашей операционной системе. Обратите особое внимание на различные клавиши и убедитесь, что они есть на вашей клавиатуре!

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

Настройка сочетаний клавиш очень похожа на настройку цветов подсветки синтаксиса. К сожалению, IDLE не позволяет устанавливать пользовательские сочетания клавиш из файла. Вы должны создать собственный набор ярлыков на вкладке Keys.

Выберите одну пару из списка и нажмите Получить новые ключи для выбора. Появится новое окно:

idle настройки новых ключей всплывающее окно

Здесь вы можете использовать флажки и меню прокрутки, чтобы выбрать комбинацию клавиш, которые вы хотите использовать для этого ярлыка. Вы можете выбрать _Advanced Key Binding Entry >> _, чтобы ввести команду вручную. Обратите внимание, что это не может подобрать нажатия клавиш. Вы должны буквально ввести команду так, как вы видите ее в списке ярлыков.

генеральный

Четвертая вкладка окна настройки — это место для небольших общих изменений. Вкладка общих настроек выглядит следующим образом:

показывает

Здесь вы можете настроить такие параметры, как размер окна и то, будет ли оболочка или редактор файлов открываться первыми при запуске Python IDLE. Большинство вещей в этом окне не так уж интересно изменить, поэтому вам, вероятно, не нужно много с ними возиться.

расширения

Пятая вкладка окна настройки позволяет добавлять расширения в Python IDLE. Расширения позволяют добавлять новые замечательные функции в редактор и окно интерпретатора. Вы можете скачать их из Интернета и установить прямо в Python IDLE.

Чтобы посмотреть, какие расширения установлены, выберите Options → Configure IDLE → Extensions. В Интернете доступно множество extensions, о которых вы можете прочитать больше. Найдите те, которые вам нравятся, и добавьте их в Python IDLE!

Заключение

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

  • Работа с оболочкой Python IDLE

  • Используйте Python IDLE в качестве редактора файлов

  • Улучшите ваш рабочий процесс с помощью функций, которые помогут вам быстрее писать код

  • Отладка вашего кода и просмотр ошибок и исключений

  • Настройте Python IDLE по своему вкусу

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

For text window backgrounds, go to Options => IDLE Preferences => Highlighting tab. Save the builtin theme (both are the same) as a custom theme, with a new name. Change the background of each element with a white background to the color you want. Hit Apply or OK. Alternatively, copy the following into <HOMEDIR>/.idlerc/config-highlight.cfg (which may or may not exist already) and change #ffffff to your desired color.

[Custom Light]
normal-foreground= #000000
normal-background= #ffffff
keyword-foreground= #ff7700
keyword-background= #ffffff
builtin-foreground= #900090
builtin-background= #ffffff
comment-foreground= #dd0000
comment-background= #ffffff
string-foreground= #00aa00
string-background= #ffffff
definition-foreground= #0000ff
definition-background= #ffffff
hilite-foreground= #000000
hilite-background= gray
break-foreground= black
break-background= #ffff55
hit-foreground= #ffffff
hit-background= #000000
error-foreground= #000000
error-background= #ff7777
#cursor (only foreground can be set, restart IDLE)
cursor-foreground= black
#shell window
stdout-foreground= blue
stdout-background= #ffffff
stderr-foreground= red
stderr-background= #ffffff
console-foreground= #770000
console-background= #ffffff

We just added an IDLE Dark theme with a deep cobalt blue background. For this, leave #002240 as is or change to another dark color.

[Custom Dark]
comment-foreground = #dd0000
console-foreground = #ff4d4d
error-foreground = #FFFFFF
hilite-background = #7e7e7e
string-foreground = #02ff02
stderr-background = #002240
stderr-foreground = #ffb3b3
console-background = #002240
hit-background = #fbfbfb
string-background = #002240
normal-background = #002240
hilite-foreground = #FFFFFF
keyword-foreground = #ff8000
error-background = #c86464
keyword-background = #002240
builtin-background = #002240
break-background = #808000
builtin-foreground = #ff00ff
definition-foreground = #5e5eff
stdout-foreground = #c2d1fa
definition-background = #002240
normal-foreground = #FFFFFF
cursor-foreground = #ffffff
stdout-background = #002240
hit-foreground = #002240
comment-background = #002240
break-foreground = #FFFFFF

We are planning to add a means to change all the normal backgrounds at once. Being able to affect dialogs will be a later project.

В этом уроке мы узнаем, как разрабатывать графические пользовательские интерфейсы, с помощью разбора некоторых примеров графического интерфейса Python с использованием библиотеки Tkinter.

Библиотека Tkinter установлена в Python в качестве стандартного модуля, поэтому нам не нужно устанавливать что-либо для его использования. Tkinter — очень мощная библиотека. Если вы уже установили Python, можете использовать IDLE, который является интегрированной IDE, поставляемой в Python, эта IDE написана с использованием Tkinter. Звучит круто!

Мы будем использовать Python 3.7 поэтому, если вы все еще используете Python 2.x, настоятельно рекомендуем перейти на Python 3.x, если вы не в курсе нюансов изменения языка, с целью, чтобы вы могли настроить код для запуска без ошибок.

Давайте предположим, что у вас уже есть базовые знания по Python, которые помогут понять что мы будем делать.
Мы начнем с создания окна, в котором мы узнаем, как добавлять виджеты, такие, как кнопки, комбинированные поля и т. д. После этого поэкспериментируем со своими свойствами, поэтому предлагаю начать.

Создание своего первого графического интерфейса

Для начала, следует импортировать Tkinter и создать окно, в котором мы зададим его название:

from tkinter import *


window = Tk()
window.title("Добро пожаловать в приложение PythonRu")
window.mainloop()

Результат будет выглядеть следующим образом:
Обучение Python GUI (уроки по Tkinter)Прекрасно! Наше приложение работает.
Последняя строка вызывает функцию mainloop. Эта функция вызывает бесконечный цикл окна, поэтому окно будет ждать любого взаимодействия с пользователем, пока не будет закрыто.

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

Создание виджета Label

Чтобы добавить текст в наш предыдущий пример, мы создадим lbl , с помощью класса Label, например:

lbl = Label(window, text="Привет")

Затем мы установим позицию в окне с помощью функции grid и укажем ее следующим образом:

lbl.grid(column=0, row=0)

Полный код, будет выглядеть следующим образом:

from tkinter import *  
  
  
window = Tk()  
window.title("Добро пожаловать в приложение PythonRu")  
lbl = Label(window, text="Привет")  
lbl.grid(column=0, row=0)  
window.mainloop()

И вот как будет выглядеть результат:
Обучение Python GUI (уроки по Tkinter)Если функция grid не будет вызвана, текст не будет отображаться.

Настройка размера и шрифта текста

Вы можете задать шрифт текста и размер. Также можно изменить стиль шрифта. Для этого передайте параметр font таким образом:

lbl = Label(window, text="Привет", font=("Arial Bold", 50))

Обучение Python GUI (уроки по Tkinter)Обратите внимание, что параметр font может быть передан любому виджету, для того, чтобы поменять его шрифт, он применяется не только к Label.

Отлично, но стандартное окно слишком мало. Как насчет настройки размера окна?

Настройка размеров окна приложения

Мы можем установить размер окна по умолчанию, используя функцию geometry следующим образом:

window.geometry('400x250')

В приведенной выше строке устанавливается окно шириной до 400 пикселей и высотой до 250 пикселей.

Попробуем добавить больше виджетов GUI, например, кнопки и посмотреть, как обрабатывается нажатие кнопок.

Добавление виджета Button

Начнем с добавления кнопки в окно. Кнопка создается и добавляется в окно так же, как и метка:

btn = Button(window, text="Не нажимать!")
btn.grid(column=1, row=0)

Наш код будет выглядеть вот так:

from tkinter import *  
  

window = Tk()  
window.title("Добро пожаловать в приложение PythonRu")  
window.geometry('400x250')  
lbl = Label(window, text="Привет", font=("Arial Bold", 50))  
lbl.grid(column=0, row=0)  
btn = Button(window, text="Не нажимать!")  
btn.grid(column=1, row=0)  
window.mainloop()

Результат будет следующим:
Обучение Python GUI (уроки по Tkinter)Обратите внимание, что мы помещаем кнопку во второй столбец окна, что равно 1. Если вы забудете и поместите кнопку в том же столбце, который равен 0, он покажет только кнопку.

Изменение цвета текста и фона у Button

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

btn = Button(window, text="Не нажимать!", bg="black", fg="red")

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

Кнопка Click

Для начала, мы запишем функцию, которую нужно выполнить при нажатии кнопки:

def clicked():
    lbl.configure(text="Я же просил...")

Затем мы подключим ее с помощью кнопки, указав следующую ​​функцию:

btn = Button(window, text="Не нажимать!", command=clicked)

Обратите внимание: мы пишем clicked, а не clicked()с круглыми скобками. Теперь полный код будет выглядеть так:

from tkinter import *  
  
  
def clicked():  
    lbl.configure(text="Я же просил...")  
  
  
window = Tk()  
window.title("Добро пожаловать в приложение PythonRu")  
window.geometry('400x250')  
lbl = Label(window, text="Привет", font=("Arial Bold", 50))  
lbl.grid(column=0, row=0)  
btn = Button(window, text="Не нажимать!", command=clicked)  
btn.grid(column=1, row=0)  
window.mainloop()

При нажатии на кнопку, результат, как и ожидалось, будет выглядеть следующим образом:
Обучение Python GUI (уроки по Tkinter)Круто!

Получение ввода с использованием класса Entry (текстовое поле Tkinter)

В предыдущих примерах GUI Python мы ознакомились со способами добавления простых виджетов, а теперь попробуем получить пользовательский ввод, используя класс Tkinter Entry (текстовое поле Tkinter).
Вы можете создать текстовое поле с помощью класса Tkinter Entry следующим образом:

txt = Entry(window, width=10)

Затем вы можете добавить его в окно, используя функцию grid.
Наше окно будет выглядеть так:

from tkinter import *  
  
  
def clicked():  
    lbl.configure(text="Я же просил...")  
  
  
window = Tk()  
window.title("Добро пожаловать в приложение PythonRu")  
window.geometry('400x250')  
lbl = Label(window, text="Привет")  
lbl.grid(column=0, row=0)  
txt = Entry(window,width=10)  
txt.grid(column=1, row=0)  
btn = Button(window, text="Не нажимать!", command=clicked)  
btn.grid(column=2, row=0)  
window.mainloop()

Полученный результат будет выглядеть так:
Обучение Python GUI (уроки по Tkinter)Теперь, если вы нажмете кнопку, она покажет то же самое старое сообщение, но что же будет с отображением введенного текста в виджет Entry?

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

def clicked():
    res = "Привет {}".format(txt.get())
    lbl.configure(text=res)

Если вы нажмете на кнопку — появится текст «Привет » вместе с введенным текстом в виджете записи. Вот полный код:

from tkinter import *  
  
  
def clicked():  
    res = "Привет {}".format(txt.get())  
    lbl.configure(text=res)  
  
  
window = Tk()  
window.title("Добро пожаловать в приложение PythonRu")  
window.geometry('400x250')  
lbl = Label(window, text="Привет")  
lbl.grid(column=0, row=0)  
txt = Entry(window,width=10)  
txt.grid(column=1, row=0)  
btn = Button(window, text="Клик!", command=clicked)  
btn.grid(column=2, row=0)  
window.mainloop()

Запустите вышеуказанный код и проверьте результат:
Обучение Python GUI (уроки по Tkinter)Прекрасно!

Каждый раз, когда мы запускаем код, нам нужно нажать на виджет ввода, чтобы настроить фокус на ввод текста, но как насчет автоматической настройки фокуса?

Установка фокуса виджета ввода

Здесь все очень просто, ведь все, что нам нужно сделать, — это вызвать функцию focus:

txt.focus()

Когда вы запустите свой код, вы заметите, что виджет ввода в фокусе, который дает возможность сразу написать текст.

Отключить виджет ввода

Чтобы отключить виджет ввода, отключите свойство состояния:

txt = Entry(window,width=10, state='disabled')

Обучение Python GUI (уроки по Tkinter)Теперь вы не сможете ввести какой-либо текст.

Добавление виджета Combobox

Чтобы добавить виджет поля с выпадающем списком, используйте класс Combobox из ttk следующим образом:

from tkinter.ttk import Combobox


combo = Combobox(window)

Затем добавьте свои значения в поле со списком.

from tkinter import *  
from tkinter.ttk import Combobox  
  
  
window = Tk()  
window.title("Добро пожаловать в приложение PythonRu")  
window.geometry('400x250')  
combo = Combobox(window)  
combo['values'] = (1, 2, 3, 4, 5, "Текст")  
combo.current(1)  # установите вариант по умолчанию  
combo.grid(column=0, row=0)  
window.mainloop()

Обучение Python GUI (уроки по Tkinter)Как видите с примера, мы добавляем элементы combobox, используя значения tuple.
Чтобы установить выбранный элемент, вы можете передать индекс нужного элемента текущей функции.
Чтобы получить элемент select, вы можете использовать функцию get вот таким образом:

combo.get()

Добавление виджета Checkbutton (чекбокса)

С целью создания виджета checkbutton, используйте класс Checkbutton:

from tkinter.ttk import Checkbutton


chk = Checkbutton(window, text='Выбрать')

Кроме того, вы можете задать значение по умолчанию, передав его в параметр var в Checkbutton:

from tkinter import *  
from tkinter.ttk import Checkbutton  
  
  
window = Tk()  
window.title("Добро пожаловать в приложение PythonRu")  
window.geometry('400x250')  
chk_state = BooleanVar()  
chk_state.set(True)  # задайте проверку состояния чекбокса  
chk = Checkbutton(window, text='Выбрать', var=chk_state)  
chk.grid(column=0, row=0)  
window.mainloop()

Посмотрите на результат:
Обучение Python GUI (уроки по Tkinter)

Установка состояния Checkbutton

Здесь мы создаем переменную типа BooleanVar, которая не является стандартной переменной Python, это переменная Tkinter, затем передаем ее классу Checkbutton, чтобы установить состояние чекбокса как True в приведенном выше примере.

Вы можете установить для BooleanVar значение false, что бы чекбокс не был отмечен.
Так же, используйте IntVar вместо BooleanVar и установите значения 0 и 1.

chk_state = IntVar()
chk_state.set(0) # False
chk_state.set(1) # True

Эти примеры дают тот же результат, что и BooleanVar.

Добавление виджетов Radio Button

Чтобы добавить radio кнопки, используйте класс RadioButton:

rad1 = Radiobutton(window,text='Первый', value=1)

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

from tkinter import *  
from tkinter.ttk import Radiobutton  
  
  
window = Tk()  
window.title("Добро пожаловать в приложение PythonRu")  
window.geometry('400x250')  
rad1 = Radiobutton(window, text='Первый', value=1)  
rad2 = Radiobutton(window, text='Второй', value=2)  
rad3 = Radiobutton(window, text='Третий', value=3)  
rad1.grid(column=0, row=0)  
rad2.grid(column=1, row=0)  
rad3.grid(column=2, row=0)  
window.mainloop()

Результатом вышеприведенного кода будет следующий:
Обучение Python GUI (уроки по Tkinter)Кроме того, вы можете задать command любой из этих кнопок для определенной функции. Если пользователь нажимает на такую кнопку, она запустит код функции.
Вот пример:

rad1 = Radiobutton(window,text='Первая', value=1, command=clicked)

def clicked():
    # Делайте, что нужно

Достаточно легко!

Получение значения Radio Button (Избранная Radio Button)

Чтобы получить текущую выбранную radio кнопку или ее значение, вы можете передать параметр переменной и получить его значение.

from tkinter import *  
from tkinter.ttk import Radiobutton  
  
  
def clicked():  
    lbl.configure(text=selected.get())  
  
  
window = Tk()  
window.title("Добро пожаловать в приложение PythonRu")  
window.geometry('400x250')  
selected = IntVar()  
rad1 = Radiobutton(window,text='Первый', value=1, variable=selected)  
rad2 = Radiobutton(window,text='Второй', value=2, variable=selected)  
rad3 = Radiobutton(window,text='Третий', value=3, variable=selected)  
btn = Button(window, text="Клик", command=clicked)  
lbl = Label(window)  
rad1.grid(column=0, row=0)  
rad2.grid(column=1, row=0)  
rad3.grid(column=2, row=0)  
btn.grid(column=3, row=0)  
lbl.grid(column=0, row=1)  
window.mainloop()

Обучение Python GUI (уроки по Tkinter)Каждый раз, когда вы выбираете radio button, значение переменной будет изменено на значение кнопки.

Добавление виджета ScrolledText (текстовая область Tkinter)

Чтобы добавить виджет ScrolledText, используйте класс ScrolledText:

from tkinter import scrolledtext


txt = scrolledtext.ScrolledText(window,width=40,height=10)

Здесь нужно указать ширину и высоту ScrolledText, иначе он заполнит все окно.

from tkinter import *  
from tkinter import scrolledtext  
  
  
window = Tk()  
window.title("Добро пожаловать в приложение PythonRu")  
window.geometry('400x250')  
txt = scrolledtext.ScrolledText(window, width=40, height=10)  
txt.grid(column=0, row=0)  
window.mainloop()

Результат:
Обучение Python GUI (уроки по Tkinter)

Настройка содержимого Scrolledtext

Используйте метод insert, чтобы настроить содержимое Scrolledtext:

txt.insert(INSERT, 'Текстовое поле')

Удаление/Очистка содержимого Scrolledtext

Чтобы очистить содержимое данного виджета, используйте метод delete:

txt.delete(1.0, END)  # мы передали координаты очистки

Отлично!

Создание всплывающего окна с сообщением

Чтобы показать всплывающее окно с помощью Tkinter, используйте messagebox следующим образом:

from tkinter import messagebox


messagebox.showinfo('Заголовок', 'Текст')

Довольно легко! Давайте покажем окно сообщений при нажатии на кнопку пользователем.

from tkinter import *  
from tkinter import messagebox  
  
  
def clicked():  
    messagebox.showinfo('Заголовок', 'Текст')  
  
  
window = Tk()  
window.title("Добро пожаловать в приложение PythonRu")  
window.geometry('400x250')  
btn = Button(window, text='Клик', command=clicked)  
btn.grid(column=0, row=0)  
window.mainloop()

Обучение Python GUI (уроки по Tkinter)Когда вы нажмете на кнопку, появится информационное окно.

Показ сообщений о предупреждениях и ошибках

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

messagebox.showwarning('Заголовок', 'Текст')  # показывает предупреждающее сообщение
messagebox.showerror('Заголовок', 'Текст')  # показывает сообщение об ошибке

Показ диалоговых окон с выбором варианта

Чтобы показать пользователю сообщение “да/нет”, вы можете использовать одну из следующих функций messagebox:

from tkinter import messagebox


res = messagebox.askquestion('Заголовок', 'Текст')
res = messagebox.askyesno('Заголовок', 'Текст')
res = messagebox.askyesnocancel('Заголовок', 'Текст')
res = messagebox.askokcancel('Заголовок', 'Текст')
res = messagebox.askretrycancel('Заголовок', 'Текст')

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

Если вы кликнете OK, yes или retry, значение станет True, а если выберете no или cancel, значение будет False.
Единственной функцией, которая возвращает одно из трех значений, является функция askyesnocancel; она возвращает True/False/None.

Добавление SpinBox (Виджет спинбокс)

Для создания виджета спинбокса, используйте класс Spinbox:

spin = Spinbox(window, from_=0, to=100)

Таким образом, мы создаем виджет Spinbox, и передаем параметры from и to, чтобы указать диапазон номеров.
Кроме того, вы можете указать ширину виджета с помощью параметра width:

spin = Spinbox(window, from_=0, to=100, width=5)

Проверим пример полностью:

from tkinter import *  
  
  
window = Tk()  
window.title("Добро пожаловать в приложение PythonRu")  
window.geometry('400x250')  
spin = Spinbox(window, from_=0, to=100, width=5)  
spin.grid(column=0, row=0)  
window.mainloop()

Обучение Python GUI (уроки по Tkinter)Вы можете указать числа для Spinbox, вместо использования всего диапазона следующим образом:

spin = Spinbox(window, values=(3, 8, 11), width=5)

Виджет покажет только эти 3 числа: 3, 8 и 11.

Задать значение по умолчанию для Spinbox

В случае, если вам нужно задать значение по умолчанию для Spinbox, вы можете передать значение параметру textvariable следующим образом:

var = IntVar()
var.set(36)
spin = Spinbox(window, from_=0, to=100, width=5, textvariable=var)

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

Добавление виджета Progressbar

Чтобы создать данный виджет, используйте класс progressbar :

from tkinter.ttk import Progressbar


bar = Progressbar(window, length=200)

Установите значение progressbar таким образом:

bar['value'] = 70

Вы можете установить это значение на основе любого процесса или при выполнении задачи.

Изменение цвета Progressbar

Изменение цвета Progressbar немного сложно. Сначала нужно создать стиль и задать цвет фона, а затем настроить созданный стиль на Progressbar. Посмотрите следующий пример:

from tkinter import *  
from tkinter.ttk import Progressbar  
from tkinter import ttk  
  
  
window = Tk()  
window.title("Добро пожаловать в приложение PythonRu")  
window.geometry('400x250')  
style = ttk.Style()  
style.theme_use('default')  
style.configure("black.Horizontal.TProgressbar", background='black')  
bar = Progressbar(window, length=200, style='black.Horizontal.TProgressbar')  
bar['value'] = 70  
bar.grid(column=0, row=0)  
window.mainloop()

И в результате вы получите следующее:
Обучение Python GUI (уроки по Tkinter)

Добавление поля загрузки файла

Для добавления поля с файлом, используйте класс filedialog:

from tkinter import filedialog


file = filedialog.askopenfilename()

После того, как вы выберете файл, нажмите “Открыть”; переменная файла будет содержать этот путь к файлу. Кроме того, вы можете запросить несколько файлов:

files = filedialog.askopenfilenames()

Указание типа файлов (расширение фильтра файлов)

Возможность указания типа файлов доступна при использовании параметра filetypes, однако при этом важно указать расширение в tuples.

file = filedialog.askopenfilename(filetypes = (("Text files","*.txt"),("all files","*.*")))

Вы можете запросить каталог, используя метод askdirectory :

dir = filedialog.askdirectory()

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

from os import path
file = filedialog.askopenfilename(initialdir= path.dirname(__file__))

Легко!

Добавление панели меню

Для добавления панели меню, используйте класс menu:

from tkinter import Menu


menu = Menu(window)
menu.add_command(label='Файл')
window.config(menu=menu)

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

menu.add_cascade(label='Автор', menu=new_item)

Наш код будет выглядеть так:

from tkinter import *  
from tkinter import Menu  
  
  
window = Tk()  
window.title("Добро пожаловать в приложение PythonRu")  
window.geometry('400x250')  
menu = Menu(window)  
new_item = Menu(menu)  
new_item.add_command(label='Новый')  
menu.add_cascade(label='Файл', menu=new_item)  
window.config(menu=menu)  
window.mainloop()

Обучение Python GUI (уроки по Tkinter)Таким образом, вы можете добавить столько пунктов меню, сколько захотите.

from tkinter import *  
  
  
window = Tk()  
window.title("Добро пожаловать в приложение PythonRu")  
window.geometry('400x250')  
menu = Menu(window)  
new_item = Menu(menu)  
new_item.add_command(label='Новый')  
new_item.add_separator()  
new_item.add_command(label='Изменить')  
menu.add_cascade(label='Файл', menu=new_item)  
window.config(menu=menu)  
window.mainloop()

Обучение Python GUI (уроки по Tkinter)Теперь мы добавляем еще один пункт меню “Изменить” с разделителем меню. Вы можете заметить пунктирную линию в начале, если вы нажмете на эту строку, она отобразит пункты меню в небольшом отдельном окне.

Можно отключить эту функцию, с помощью tearoff подобным образом:

new_item = Menu(menu, tearoff=0)

Просто отредактируйте new_item, как в приведенном выше примере и он больше не будет отображать пунктирную линию.
Вы так же можете ввести любой код, который работает, при нажатии пользователем на любой элемент меню, задавая свойство команды.

new_item.add_command(label='Новый', command=clicked)

Добавление виджета Notebook (Управление вкладкой)

Для удобного управления вкладками реализуйте следующее:

  • Для начала, создается элемент управления вкладкой, с помощью класса Notebook .
  • Создайте вкладку, используя класс Frame.
  • Добавьте эту вкладку в элемент управления вкладками.
  • Запакуйте элемент управления вкладкой, чтобы он стал видимым в окне.
from tkinter import *  
from tkinter import ttk  
  
  
window = Tk()  
window.title("Добро пожаловать в приложение PythonRu")  
window.geometry('400x250')  
tab_control = ttk.Notebook(window)  
tab1 = ttk.Frame(tab_control)  
tab_control.add(tab1, text='Первая')  
tab_control.pack(expand=1, fill='both')  
window.mainloop()

Обучение Python GUI (уроки по Tkinter)Таким образом, вы можете добавлять столько вкладок, сколько нужно.

Добавление виджетов на вкладку

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

from tkinter import *  
from tkinter import ttk  
  
  
window = Tk()  
window.title("Добро пожаловать в приложение PythonRu")  
window.geometry('400x250')  
tab_control = ttk.Notebook(window)  
tab1 = ttk.Frame(tab_control)  
tab2 = ttk.Frame(tab_control)  
tab_control.add(tab1, text='Первая')  
tab_control.add(tab2, text='Вторая')  
lbl1 = Label(tab1, text='Вкладка 1')  
lbl1.grid(column=0, row=0)  
lbl2 = Label(tab2, text='Вкладка 2')  
lbl2.grid(column=0, row=0)  
tab_control.pack(expand=1, fill='both')  
window.mainloop()

Обучение Python GUI (уроки по Tkinter)

Добавление интервала для виджетов (Заполнение)

Вы можете добавить отступы для элементов управления, чтобы они выглядели хорошо организованными с использованием свойств padx иpady.

Передайте padx и pady любому виджету и задайте значение.

lbl1 = Label(tab1, text= 'label1', padx=5, pady=5)

Это очень просто!

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

How to Get Dark Theme in Python IDLE[3.8]

Dark Theme in Python IDLE – Version 2.7

Python is a high- level, general-purpose, interactive, interpreted and object-oriented programming language. It was developed in 1991. As Python allows the programmer to write programs and instruction using fewer lines of codes, it has caught the attention of Millions of Developers.

If you are a Python Developer and especially a night-owl programmer, this hack is for you which will transform your Python IDLE 3.8 in Dark Theme which will reduce your eye strain in low light conditions. If you want to feel Monokai Theme of Sublime Text, then go ahead and add the Dark theme to your Python IDLE 3.8 and save your eyes.

What is Python IDLE?

Python IDLE which stands for “Integrated Development and Learning Environment” is an integrated development environment (IDE) for Python Programming Language and is by default installed with the Python installer for Windows.

You can open Python IDLE from the Start menu in the Windows Operating System by searching for ‘IDLE’.

idle3.8

In the case of Python distributions for Linux and macOS, Python IDLE is not available by default.

For Ubuntu Linux, You can install the Python IDLE with the help of the following command:

$ sudo apt-get install idle

Python IDLE is used for executing single line python statements. Developers basically use Python IDLE to develop, modify, execute and debug Python scripts. Python IDLE provides a fully-featured and efficient text editor to write Python scripts. It also includes some awesome features like syntax highlighting, autocompletion and smart indent. Developers love IDLE as it provides the debugger with stepping and breakpoints features.

You can download Python from it’s an official site which automatically comes with Python IDLE.

Also Read: Top Free Python Udemy Courses

Why you should add dark theme to your Python IDLE?

wet-eyes

The programmers are the main source of income for eye doctors 🙁

The dark themes are getting more and popular nowadays for night-owl programmers. Some people just like the vibe, while others use dark themes simply to reduce eye strain and save battery.

Pros:

  • Dark themes can reduce eye strain in low-light conditions, more specifically at night time.
  • High contrast between foreground and background reduces eye strain.
  • Syntax highlighting on Python IDLE can be easier to read with dark themes like monokai.

Adopt Dark Theme and Happy Coding while protecting your most precious organ – ‘Eye’!

Python IDLE Dark Theme Code [Monokai Theme]:

Below is the code for adding Dark Theme in Python IDLE which you will require in the next section describing steps for adding a dark theme to your python IDLE.

The Monokai Theme code changes the syntax highlighting and various text editor component’s colors including foreground and background.


[monokai]

normal-foreground= #F8F8F2
normal-background= #272822
keyword-foreground= #F92672
keyword-background= #272822
builtin-foreground= #66D9EF
builtin-background= #272822
comment-foreground= #75715E
comment-background= #272822
string-foreground= #E6DB74
string-background= #272822
definition-foreground= #A6E22E
definition-background= #272822
hilite-foreground= #F8F8F2
hilite-background= gray
break-foreground= black
break-background= #ffff55
hit-foreground= #F8F8F2
hit-background= #171812
error-foreground= #ff3338
error-background= #272822
cursor-foreground= #F8F8F2
stdout-foreground= #DDDDDD
stdout-background= #272822
stderr-foreground= #ff3338
stderr-background= #272822
console-foreground= #75715E
console-background= #272822

Steps to Add Dark Theme to Your Python IDLE:

1). Open Python Folder from the path you selected during installing Python. In this case it is ( C:Python38-32 )

How to Get dark theme in Python IDLE[3.8] - Step 1

2). In Python38-32 Folder, search for Lib and double click on it.

How to Get dark theme in Python IDLE[3.8] - Step 2

3). In the Lib folder, search for idlelib folder and double click on it.

How to Get dark theme in Python IDLE[3.8] - Step 3

4). In idlelib folder, search for CONFIG-HIGHLIGHT.DEF file and open it with any text editor tool like Notepad.

How to Get dark theme in Python IDLE[3.8] - Step 4

5). In the CONFIG-HIGHLIGHT.DEF file, paste the Monokai Code given in the above section. Save and close the file.

How to Get dark theme in Python IDLE[3.8] - Step 5

6). Now Restart your system, Open Python IDLE, From the menu bar select Options -> Configure IDLE -> Highlighting & You will see the monokai theme in Highlighting themes section. Select Monokai theme and Enjoy 🙂

How to Get dark theme in Python IDLE[3.8] - Step 6

7). Do share this Post if your love your new Python IDLE Look <3, DO share this post in your developer circles as sharing is caring.

How to Get dark theme in Python IDLE[3.8] - Step 7

Link to Video Tutorial “How to Get dark theme in Python IDLE[3.8]”: https://www.youtube.com/watch?v=4pTRBH5Pa9g

Conclusion:

Finally concluding this article subjected, How to Get dark theme in Python IDLE and execute python scripts like a pro without spoiling your eyes.

We have included the topics; What is Python IDLE?, How to install Python IDLE on your System?, Why you need to add a dark theme to your python IDLE? and Steps to add a dark theme to your python IDLE.

I hope this piece helped you and satisfies the reason for you being here, and if you have any queries or questions related to this thread, then please make a comment below and let me help you with that concern.

Happy Coding and protect your Eyes!

#статьи

  • 25 июл 2022

  • 0

Знакомимся с библиотекой и пишем кросс-платформенный калькулятор, который рассчитывает вес человека.

Иллюстрация: Merry Mary для Skillbox Media

Антон Яценко

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

Десктопные приложения пишут на разных языках программирования: C++, C#, C, Python и других. Начинающим разработчикам проще всего использовать Python и его библиотеки для работы над графическими интерфейсами.

Одна из таких библиотек — Tkinter. Она входит в стандартный пакет Python и позволяет создавать приложения для Windows, mac OS и Linux. Давайте разберёмся, как устроена эта библиотека, и напишем десктопный калькулятор, помогающий рассчитать вес человека.

GUI (Graphical User Interface) — это графический интерфейс пользователя, оболочка программы, с которой мы взаимодействуем с помощью клавиатуры и мыши. На современных операционных системах почти все программы работают с графическим интерфейсом, и мы каждый день сталкиваемся с GUI: читаем статьи в браузере, набираем текст в редакторе или играем в игры.

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

Для работы с GUI в Python есть четыре библиотеки:

  • Tkinter;
  • Kivy;
  • Python QT;
  • wxPython.

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

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

Схематично работу с Tkinter можно представить в виде четырёх шагов:

Скриншот: Tkinter 

Что здесь происходит:

  • Мы подключаем библиотеку Tkinter с помощью директивы import.
  • Создаём главное окно приложения, в котором будут размещаться все графические элементы.
  • Добавляем виджеты — визуальные элементы, выполняющие определённые действия.
  • Создаём главный цикл событий — он включает в себя все события, происходящие при взаимодействии пользователя с интерфейсом.

Ключевые объекты в работе с Tkinter — виджеты. Это аналоги тегов из HTML, которые позволяют создавать интерактивные и неинтерактивные элементы, например надписи или кнопки. Всего их 18, но чаще всего используют следующие:

  • Button — кнопки;
  • Canvas — «холст», на котором рисуют графические фигуры;
  • Entry — виджет для создания полей ввода;
  • Label — контейнер для размещения текста или изображения;
  • Menu — виджет для создания пунктов меню.

Понять работу с виджетами легче всего на практике. Но прежде чем к ней приступить, обсудим идею нашего первого десктопного приложения.

Мы напишем калькулятор индекса массы тела. ИМТ — это важный медицинский показатель, который позволяет оценить, есть ли у человека избыточный вес или ожирение. Он рассчитывается по следующей формуле: ​​

Результаты расчётов оценивают с помощью специальной таблицы. У врачей она имеет много градаций, мы же воспользуемся упрощённой версией:

Изображение: Skillbox Media

Писать код на Python лучше всего в специальной IDE, например в PyCharm или Visual Studio Code. Они подсвечивают синтаксис и предлагают продолжение кода — это сильно упрощает работу программиста. Весь код из этой статьи мы писали в Visual Studio Code.

Библиотека Tkinter предустановлена в Python. Поэтому её нужно только импортировать:

import tkinter as tk

Теперь мы можем использовать любые модули из этой библиотеки.


Прежде чем писать код, необходимо ответить на несколько вопросов:

  • Какие данные мы хотим получить от пользователя и в каком виде?
  • Какое событие будет запускать расчёт ИМТ: нажатие кнопки, получение приложением всех необходимых данных или что-то другое?
  • Как будем показывать результат?

В нашем случае необходимо получить от пользователя вес и рост в виде целых чисел. При этом вес должен быть введён в килограммах, а рост — в сантиметрах. ИМТ будет рассчитываться по нажатии кнопки, а результат — выводиться во всплывающем окне в виде значения ИМТ и категории, к которой он относится.

Схематично графический интерфейс нашего калькулятора будет выглядеть так:

Скриншот: Tkinter / Skillbox Media

Теперь попробуем реализовать интерфейс и работу калькулятора с помощью Python и Tkinter.


После импорта библиотеки в Python загрузим её методы:

from tkinter import *
from tkinter import messagebox

Первая строка позволяет нам загрузить все методы Tkinter и использовать их в коде без ссылки на их наименование. Второй строкой мы явно импортируем метод messagebox, который будем использовать для вывода всплывающего окна с результатом. Это удобно, так как метод потребуется нам несколько раз.

Теперь создадим окно нашего приложения. Для этого воспользуемся модулем Tk. Приложение назовём «Калькулятор индекса массы тела (ИМТ)»:

window = Tk() #Создаём окно приложения.
window.title("Калькулятор индекса массы тела (ИМТ)") #Добавляем название приложения.

После запуска кода ничего не произойдёт. Это не ошибка. На самом деле код выполнился и окно закрылось. Необходимо явно указать, что окно приложения не должно закрываться до тех пор, пока пользователь сам не сделает этого. Для этого к коду добавим функцию window.mainloop(), указывающую на запуск цикла событий:

window.mainloop()

Запустив код, увидим экран приложения:

Скриншот: Tkinter / Skillbox Media

Мы не указали размер окна, поэтому название приложения не помещается в него полностью. Исправим это с помощью метода geometry:

window.geometry('400x300')

Теперь название приложения видно полностью:

Скриншот: Tkinter / Skillbox Media

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

  • pack — используется, когда мы работаем с контейнерами для элементов. Позволяет позиционировать кнопки, надписи или другие элементы внутри контейнеров.
  • place — позволяет позиционировать элементы, указывая точные координаты.
  • grid — размещает элементы по ячейкам условной сетки, разделяющей окно приложения.

Мы воспользуемся комбинацией методов pack и grid. Для начала создадим виджет Frame для размещения надписей, полей ввода и кнопок. Подробное описание работы виджета есть в документации. Мы же используем только два свойства: padx и pady.

Обозначим отступы по вертикали и горизонтали в 10 пикселей для элементов, которые будут расположены внутри Frame:

frame = Frame(
   window, #Обязательный параметр, который указывает окно для размещения Frame.
   padx = 10, #Задаём отступ по горизонтали.
   pady = 10 #Задаём отступ по вертикали.
)
frame.pack(expand=True) #Не забываем позиционировать виджет в окне. Здесь используется метод pack. С помощью свойства expand=True указываем, что Frame заполняет весь контейнер, созданный для него.


В окне приложения нам необходимо добавить три вида виджетов: поле для ввода информации (Entry), текстовые надписи (Label) и кнопку (Button).

Начнём с надписей. Воспользуемся виджетом Label:

height_lb = Label(
   frame,
   text="Введите свой рост (в см)  "
)
height_lb.grid(row=3, column=1)

Мы передаём виджету Label два параметра:

  • frame — используем заготовку виджета Frame, в которой уже настроены отступы по вертикали и горизонтали.
  • text — текст, который должен быть выведен на экран.

Для позиционирования виджета используем метод grid. Укажем, что текст должен располагаться в ячейке с координатами «3-я строка, 1-й столбец». Если запустим код, то увидим там единственный элемент:

Скриншот: Tkinter / Skillbox Media

Сейчас элемент расположен в центре окна, но он займёт правильное положение, когда мы напишем другие элементы.

Добавим вторую надпись о весе аналогичным образом, но при позиционировании в grid укажем следующую, четвёртую строку:

weight_lb = Label(
   frame,
   text="Введите свой вес (в кг)  ",
)
weight_lb.grid(row=4, column=1)

Запускаем код и смотрим на результат:

Скриншот: Tkinter / Skillbox Media

Теперь добавим поля для ввода пользовательской информации, используя виджет Entry:

height_tf = Entry(
   frame, #Используем нашу заготовку с настроенными отступами.
)
height_tf.grid(row=3, column=2)

Для позиционирования мы также воспользовались методом grid. Обратите внимание, что наш элемент должен быть расположен напротив надписи «Введите свой рост (в см)». Поэтому мы используем ячейку в той же строке, но уже во втором столбце. Запустим код и посмотрим на результат:

Скриншот: Tkinter / Skillbox Media

Всё получилось. Остаётся по аналогии добавить поле ввода веса:

weight_tf = Entry(
   frame,
)
weight_tf.grid(row=4, column=2, pady=5)

Посмотрим на результат:

Скриншот: Tkinter / Skillbox Media

Теперь добавим кнопку, которая будет запускать расчёт ИМТ. Сделаем это с помощью виджета Button:

cal_btn = Button(
   frame, #Заготовка с настроенными отступами.
   text='Рассчитать ИМТ', #Надпись на кнопке.
)
cal_btn.grid(row=5, column=2) #Размещаем кнопку в ячейке, расположенной ниже, чем наши надписи, но во втором столбце, то есть под ячейками для ввода информации.

Посмотрим на результат:

Скриншот: Tkinter / Skillbox Media

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


Напишем простую функцию и разберём её построчно:

def calculate_bmi(): #Объявляем функцию.
   kg = int(weight_tf.get()) #С помощью метода .get получаем из поля ввода с именем weight_tf значение веса, которое ввёл пользователь и конвертируем в целое число с помощью int().
   m = int(height_tf.get())/100 #С помощью метода .get получаем из поля ввода с именем height_tf значение роста и конвертируем в целое число с помощью int(). Обязательно делим его на 100, так как пользователь вводит рост в сантиметрах, а в формуле для расчёта ИМТ используются метры.
   bmi = kg/(m*m)#Рассчитываем значение индекса массы тела.
   bmi = round(bmi, 1) #Округляем результат до одного знака после запятой.

Функция готова. Но теперь нам необходимо оценить полученный результат расчёта и вывести сообщение для пользователя.


Дополним нашу функцию calculate_bmi. Воспользуемся условным оператором if, чтобы учесть полученные значения ИМТ, и методом Tkinter messagebox для отображения сообщения во всплывающем окне:

if bmi < 18.5:
       messagebox.showinfo('bmi-pythonguides', f'ИМТ = {bmi} соответствует недостаточному весу')
   elif (bmi > 18.5) and (bmi < 24.9):
       messagebox.showinfo('bmi-pythonguides', f'ИМТ = {bmi} соответствует нормальному весу')
   elif (bmi > 24.9) and (bmi < 29.9):
       messagebox.showinfo('bmi-pythonguides', f'ИМТ = {bmi} соответствует избыточному весу')
   else:
       messagebox.showinfo('bmi-pythonguides', f'ИМТ = {bmi} соответствует ожирению')

Остаётся последний шаг — наша функция должна запускаться при нажатии на кнопку «Рассчитать ИМТ». Для этого добавим свойство command в виджет Button:

cal_btn = Button(
   frame,
   text='Рассчитать ИМТ',
   command=calculate_bmi #Позволяет запустить событие с функцией при нажатии на кнопку.
)
cal_btn.grid(row=5, column=2)

Запустим код и посмотрим на результат:

Источник: Tkinter / Skillbox Media

Всё работает. Функция получает данные из полей ввода и рассчитывает индекс массы тела, показывая результат на экране.

from tkinter import *
from tkinter import messagebox
 
def calculate_bmi():
   kg = int(weight_tf.get())
   m = int(height_tf.get())/100
   bmi = kg/(m*m)
   bmi = round(bmi, 1)
 
   if bmi < 18.5:
       messagebox.showinfo('bmi-pythonguides', f'ИМТ = {bmi} соответствует недостаточному весу')
   elif (bmi > 18.5) and (bmi < 24.9):
       messagebox.showinfo('bmi-pythonguides', f'ИМТ = {bmi} соответствует нормальному весу')
   elif (bmi > 24.9) and (bmi < 29.9):
       messagebox.showinfo('bmi-pythonguides', f'ИМТ = {bmi} соответствует избыточному весу')
   else:
       messagebox.showinfo('bmi-pythonguides', f'ИМТ = {bmi} соответствует ожирению')  
 
window = Tk()
window.title('Калькулятор индекса массы тела (ИМТ)')
window.geometry('400x300')
 
 
frame = Frame(
   window,
   padx=10,
   pady=10
)
frame.pack(expand=True)
 
 
height_lb = Label(
   frame,
   text="Введите свой рост (в см)  "
)
height_lb.grid(row=3, column=1)
 
weight_lb = Label(
   frame,
   text="Введите свой вес (в кг)  ",
)
weight_lb.grid(row=4, column=1)
 
height_tf = Entry(
   frame,
)
height_tf.grid(row=3, column=2, pady=5)
 
weight_tf = Entry(
   frame,
)
weight_tf.grid(row=4, column=2, pady=5)
 
cal_btn = Button(
   frame,
   text='Рассчитать ИМТ',
   command=calculate_bmi
)
cal_btn.grid(row=5, column=2)
 
window.mainloop()

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

  • Python GUI Programming with Tkinter. Develop responsive and powerful GUI applications with Tkinter, Алан Мур.
  • Tkinter GUI Programming by Example, Дэвид Лав.

Учись бесплатно:
вебинары по программированию, маркетингу и дизайну.

Участвовать

Школа дронов для всех
Учим программировать беспилотники и управлять ими.

Узнать больше

Время прочтения
6 мин

Просмотры 15K

Всем доброго и неумолимо наступающего!

Этот крайне насыщенный год подходит к своему завершению и у нас остался последний курс, который мы запускаем в этом году — «Разработчик full-stack на Python», чему, собственно, и посвящаем заметку, которая хоть и проскочила мимо основной программы, но показалась небезынтересной в целом.

Поехали

На этой неделе я сделал мой первый pull-request в основной проект CPython. Его отклонили :-( Но чтобы не тратить полностью свое время, я поделюсь своими выводами о том, как работает CPython и покажу вам как легко изменить синтаксис Python.

Я собираюсь показать вам как добавить новую фичу в синтаксис Python. Эта фича — оператор инкремента/декремента, стандартный оператор для большинства языков. Чтобы убедиться — откройте REPL и попробуйте:

Уровень 1: PEP

Изменению синтаксиса Python предшествует заявка с описанием причин, дизайна и поведения вносимых изменений. Все изменения языка обсуждаются основной командой Python и одобряются BDFL. Операторы инкремента не утверждены (и, вероятно, никогда не будут), что даёт нам хорошую возможность потренироваться.

Уровень 2: Грамматика

Файл Grammar — это простой текстовый файл, описывающий все элементы языка Python. Его использует не только CPython, но и другие реализации, такие как PyPy, чтобы сохранить последовательность и согласовать типы языковой семантики.

Внутри эти ключи образуют токены, которые разбираются лексером. Когда вы вводите make -j, команда преобразует их в набор перечислений и констант в C-хедерах. Это позволяет ссылаться на них в дальнейшем.

stmt: simple_stmt | compound_stmt
simple_stmt: small_stmt (';' small_stmt)* [';'] NEWLINE
# ...
pass_stmt: 'pass'
flow_stmt: break_stmt | continue_stmt | return_stmt | raise_stmt | yield_stmt
break_stmt: 'break'
continue_stmt: 'continue'
# ..
import_as_name: NAME ['as' NAME]

Таким образом, simple_stmt — это простое выражение, оно может иметь точку с запятой или не иметь, например, когда вы вводите import pdb; pdb.set_trace(), и заканчиваться в новой строке NEWLINE. Pass_stmt — пропуск слова, break_stmt — прерывание работы. Просто, не так ли?

Давайте добавим выражения инкремента и декремента: то, чего не существует в языке. Это был бы еще один вариант структуры выражения, наряду с операторами yield, расширенным и стандартным присвоением, т.е. foo=1.

# Добавляем выражения инкремента и декремента
expr_stmt: testlist_star_expr (annassign | augassign (yield_expr|testlist) |
                     ('=' (yield_expr|testlist_star_expr))* | incr_stmt | decr_stmt)
annassign: ':' test ['=' test]
testlist_star_expr: (test|star_expr) (',' (test|star_expr))* [',']
augassign: ('+=' | '-=' | '*=' | '@=' | '/=' | '%=' | '&=' | '|=' | '^=' |
            '<<=' | '>>=' | '**=' | '//=')
# Для нормальных и аннотированных присвоений, дополнительных ограничений навязываемых интерпретатором
del_stmt: 'del' exprlist

# Новые выражения
incr_stmt: '++'
decr_stmt: '--'

Мы добавляем его в список возможных малых выражений (это станет очевидным в AST). Incr_stmt будет нашим методом инкремента и decr_stmt будет декрементом. Оба следуют за NAME (имя переменной) и образуют малое автономное выражение. Когда мы соберем проект Python, он сгенерирует компоненты для нас (не сейчас).

Если вы запустите Python с опцией -d и попробуете это, вы должны получить:

Token <ERRORTOKEN>/’++’ … Illegal token

Что такое токен? Давайте выясним…

Уровень 3: Лексер

Есть четыре шага, которые делает Python, когда вы вызываете return: лексический анализ, синтаксический анализ, компиляция и интерпретация. Лексический анализ разбивает строку кода, которую вы только что ввели, на токены. Лексер CPython называется tokenizer.c. Он имеет функции, которые читают из файла (например, python file.py) строку (например, REPL). Он также обрабатывает специальный комментарий для кодировки в верхней части файлов и анализирует ваш файл как UTF-8 и т. д. Он обрабатывает вложенность, ключевые слова async и yield, обнаруживает наборы и кортежи присвоений, но только грамматически. Он не знает, что это за вещи или что с ними делать. Его волнует только текст.

Например, код, который позволяет использовать o-нотацию для восьмеричных значений, находится в токенизаторе. Код, который на самом деле создает восьмеричные значения, находится в компиляторе.

Давайте добавим две вещи в Parser/tokenizer.c: новые токены INCREMENT и DECREMENT, — это ключи, которые возвращаются токенизатором для каждой части кода.

/* Имена токенов */

const char *_PyParser_TokenNames[] = {
    "ENDMARKER",
    "NAME",
    "NUMBER",
...
    "INCREMENT",
    "DECREMENT",
...

Затем мы добавляем проверку, чтобы вернуть токен INCREMENT или DECREMENT, каждый раз, когда видим ++ или —. Уже существует функция для двухсимвольных операторов, поэтому мы расширяем ее в соответствии с нашим случаем.

@@ -1175,11 +1177,13 @@ PyToken_TwoChars(int c1, int c2)
         break;
     case '+':
         switch (c2) {
+        case '+':               return INCREMENT;
         case '=':               return PLUSEQUAL;
         }
         break;
     case '-':
         switch (c2) {
+        case '-':               return DECREMENT;
         case '=':               return MINEQUAL;
         case '>':               return RARROW;
         }

Они определены в token.h

#define INCREMENT 58
#define DECREMENT 59

Теперь, когда мы запускаем Python с -d и пытаемся выполнить наш оператор, мы видим:

It’s a token we know - Успех!

Уровень 4: Парсер

Парсер принимает эти токены и генерирует структуру, которая показывает их взаимосвязь друг с другом. Для Python и многих других языков это абстрактное синтаксическое дерево (или AST). Затем компилятор принимает AST и превращает его в один (или более) объект кода. Наконец, интерпретатор принимает каждый объект кода, который выполняет код, представляемый им.

Представьте свой код в виде дерева. Верхний уровень — это корень, функция может быть веткой, класс — тоже ветка и методы класса ответвляются от нее. Выражения — это листья на ветке.
AST определяется в ast.py и ast.c. ast.c — это файл, который нам нужно изменить. Код AST разбит на методы, которые обрабатывают типы токенов, ast_for_stmt обрабатывает операторы, ast_for_expr обрабатывает выражения. Мы помещаем incr_stmt и decr_stmt как возможные выражения. Они почти идентичны расширенным выражениям, например, test += 1, но нет правого выражения (1), оно неявно.

Это код, который нам нужно добавить для инкремента и декремента.

static stmt_ty
ast_for_expr_stmt(struct compiling *c, const node *n)
{
    ...
    else if ((TYPE(CHILD(n, 1)) == incr_stmt) || (TYPE(CHILD(n, 1)) == decr_stmt)) {
        expr_ty expr1, expr2;
        node *ch = CHILD(n, 0);
        operator_ty operator;
        
        switch (TYPE(CHILD(n, 1))){
            case incr_stmt:
                operator = Add; 
                break;
            case decr_stmt:
                operator = Subtract; 
                break;
        }

        expr1 = ast_for_testlist(c, ch);
        if (!expr1) {
            return NULL;
        }
        switch (expr1->kind) {
            case Name_kind:
                if (forbidden_name(c, expr1->v.Name.id, n, 0)) {
                    return NULL;
                }
                expr1->v.Name.ctx = Store;
                break;
            default:
                ast_error(c, ch,
                          "illegal target for increment/decrement");
                return NULL;
        }      
	   // Создаем PyObject для числа 1
        PyObject *pynum = parsenumber(c, "1");

        if (PyArena_AddPyObject(c->c_arena, pynum) < 0) {
            Py_DECREF(pynum);
            return NULL;
        }
        // Создаем это как выражение в той же строке и смещении как ++/--
        expr2 = Num(pynum, LINENO(n), n->n_col_offset, c->c_arena);
        return AugAssign(expr1, operator, expr2, LINENO(n), n->n_col_offset, c->c_arena);

Это возвращает расширенное присваивание — вместо нового типа выражения с постоянным значением 1. Оператором является либо Add, либо Sub(tract) в зависимости от типа токена incr_stmt или decr_stmt. Возвращаясь к Python REPL после компиляции, мы можем увидеть наш новый оператор!

В REPL вы можете попробовать ast.parse ("test=1; test++).body[1], и вы увидите возвращаемый тип AugAssign. AST только что преобразовал оператор в выражение, которое может быть обработано компилятором. Функция AugAssign устанавливает поле Kind, которое используется компилятором.

Уровень 5: Компилятор

Затем компилятор берет дерево синтаксиса и «посещает» каждую ветвь. У компилятора CPython есть метод для посещения оператора, который называется compile_visit_stmt. Это просто большой оператор switch, определяющий вид оператора. У нас был тип AugAssign, поэтому он обращается к compiler_augassign для обработки деталей. Затем эта функция преобразует наше утверждение в набор байт-кодов. Это промежуточный язык между машинным кодом (01010101) и деревом синтаксиса. Последовательность байтового кода — это то, что кэшируется в .pyc-файлах.

static int
compiler_augassign(struct compiler *c, stmt_ty s)
{
    expr_ty e = s->v.AugAssign.target;
    expr_ty auge;

    assert(s->kind == AugAssign_kind);

    switch (e->kind) {
...
    case Name_kind:
        if (!compiler_nameop(c, e->v.Name.id, Load))
            return 0;
        VISIT(c, expr, s->v.AugAssign.value);
        ADDOP(c, inplace_binop(c, s->v.AugAssign.op));
        return compiler_nameop(c, e->v.Name.id, Store);

Результатом будет VISIT (значение нагрузки — для нас 1), ADDOP (добавить операцию двоичного операционного кода в зависимости от оператора (вычесть, добавить)) и STORE_NAME (сохранить результат ADDOP для имени). Эти методы отвечают более конкретными байт-кодами.

Если вы загрузите модуль dis, вы сможете увидеть байт-код:

Уровень 6: Интерпретатор

Финальным уровнем является интерпретатор. Он берет последовательность байт-кодов и преобразует ее в машинные операции. Вот почему Python.exe и Python для Mac и Linux — все отдельные исполняемые файлы. Некоторым байт-кодам нужна конкретная обработка и проверка ОС. API-интерфейс потоковой обработки, например, должен работать с API-интерфейсом GNU/Linux, который очень отличается от потоков Windows.

Вот и все!

Для дальнейшего чтения.

Если вас интересуют интерпретаторы, я рассказал о Pyjion, архитектуре плагина для CPython, которая стала PEP523

Если вы все еще хотите поиграть, я запушил код на GitHub вместе с моими изменениями в токенизаторе ожидания.

THE END

Как всегда ждём вопросы, комментарии, замечания.

В Python есть довольно много GUI фреймворков (graphical user interface), однако только Tkinter встроен в стандартную библиотеку языка. У Tkinter есть несколько преимуществ. Он кроссплатформенный, поэтому один и тот же код можно использовать на Windows, macOS и Linux.

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

Хотя Tkinter является популярным GUI фреймворком на Python, у него есть свои недостатки. Один из них заключается в том, что графические интерфейсы, созданные с использованием Tkinter, выглядят устаревшими. Если вам нужен современный, броский интерфейс, то Tkinter может оказаться не совсем тем, для этого есть PyQt5 который развивается сильнее в данном плане.

Есть вопросы по Python?

На нашем форуме вы можете задать любой вопрос и получить ответ от всего нашего сообщества!

Telegram Чат & Канал

Вступите в наш дружный чат по Python и начните общение с единомышленниками! Станьте частью большого сообщества!

Паблик VK

Одно из самых больших сообществ по Python в социальной сети ВК. Видео уроки и книги для вас!

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

Другие статьи по Tkinter на сайте

  1. Создание окна по центру и кнопка выхода в Tkinter
  2. Разметка виджетов в Tkinter — pack, grid и place
  3. Виджеты Checkbutton, Label, Scale и Listbox в Tkinter
  4. Меню, подменю и панель инструментов в Tkinter
  5. Диалоговые окна в Tkinter
  6. Рисуем линии, прямоугольники, круг и текст в Tkinter
  7. Пишем игру змейка на Tkinter

Основные аспекты руководства

  • Введение и создание простого приложения «Hello, World!» в Tkinter;
  • Работа с виджетами вроде кнопок или текстовых боксов;
  • Управление макетом приложений через геометрические менеджеры;
  • Создание интерактивного приложения через связывание кнопок с функциями Python.

После освоения основных навыков в процессе изучения примеров, данных в руководстве, вы сможете создать два рабочих приложения. Одно будет конвертером температуры, а второе редактором текста. Что ж, приступим!

Создание простого GUI приложения на Tkinter

Главным элементом GUI Tkinter является окно. Окнами называют контейнеры, в которых находятся все GUI элементы. Данные GUI элементы, к числу которых относятся текстовые боксы, ярлыки и кнопки, называются виджетами. Виджеты помещаются внутри окон.

Сперва создадим окно с одним виджетом. Запустим новую сессию оболочки Python, следуя инструкции.

На заметку: Примеры кода, используемые в руководстве, были протестированы на Windows, macOS и Ubuntu Linux 18.04 через версии Python 3.6, 3.7 и 3.8.

В случае, если вы установили Python на Windows или macOS, скачав установщик c официального сайта python.org, проблем с запуском кода из примеров возникнуть не должно. Можете пропустить оставшуюся часть заметки и перейти к самому руководству.

В случае, если ввиду отсутствия официальных дистрибутивов Python для вашей системы, вы установили Python иным образом, тогда обратите внимание на следующие моменты.

Установка Python на macOS используя Homebrew:

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

Ubuntu Linux 16.04:

Последняя версия Python доступна на Ubuntu Linux 16.04, это 3.5. Вы можете установить последнюю версию через deadsnakes PPA. Далее даны команды для установки PPA и загрузки последней версии Python с правильной версией Tcl/Tk:

$ sudo addaptrepository ppa:deadsnakes/ppa

$ sudo aptget update

$ sudo aptget install python3.8 python3tk

Первые две команды добавляют deadsnakes PPA в ваш системный список репозитория, а последняя команда устанавливает Python 3.8 и модуль GUI Tkinter.

Ubuntu Linux 18.04:

Вы можете установить последнюю версию Python с соответствующей версией Tcl/Tk из универсального репозитория через следующую команду:

$ sudo aptget install python3.8 python3tk

Таким образом устанавливается Python 3.8, а также модуль Tkinter.

Прочие версии Linux:

Если на данный момент нет официального рабочего установщика Python для Linux дистрибутива, то можете поставить Python вместе с соответствующей версией Tcl/Tk через исходный код. С пошаговой инструкцией процесса можете ознакомиться на странице: Установка Python 3.8 из исходного кода на Linux

В открытой оболочке IDLE Python первым делом необходимо импортировать модуль Tkinter:

Окно, или window является экземпляром класса Tkinter. Попробуйте создать новое окно, присвоив его переменной окна window:

При выполнении вышеуказанного кода на экране появится новое окно. То, как оно будет выглядеть, зависит от вашей операционной системы:

tkinter os

Далее в руководстве будут представлены примеры из операционной системы Ubuntu и Windows.

Добавление нового виджета в приложении

Теперь, когда у вас есть окно, можно добавить на него виджет. Используем класс tk.Label и добавим какой либо текст на окно.

Создадим виджет ярлыка (label) с текстом "Привет, Tkinter!" и присвоим его переменной под названием greeting:

>>> greeting = tk.Label(text=«Привет, Tkinter!»)

Созданное ранее окно не меняется. Создается виджет ярлыка, однако пока не добавляется на окно. Есть несколько способов добавления виджетов на окно. Сейчас можно использовать метод .pack() от виджета ярлыка:

Теперь окно выглядит следующим образом:

Виджет Label

При использовании метода .pack() для размещения виджета в окне, Tkinter устанавливает размер окна настолько маленьким, насколько возможно, пока в него не влезает виджет. Теперь выполним следующее:

Кажется, будто ничего не случилось, но это не совсем так. window.mainloop() указывает Python, что нужно запустить цикл событий Tkinter. Данный метод требуется для событий вроде нажатий на клавиши или кнопки, он также блокирует запуск любого кода, что следует после, пока окно, на котором оно было вызвано, не будет закрыто. Попробуйте закрыть созданное окно, и вы увидите появившуюся в оболочке подсказку.

Внимание: При работе с Tkinter из Python REPL окна обновляются при выполнении каждой строки. Однако, если программа Tkinter выполняется из запущенного файла, такого не происходит.

Если не добавлять window.mainloop() в конец программы в Python файле, тогда приложение Tkinter не запустится вообще, и ничего не будет отображаться.

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

Выполните небольшое задание, чтобы проверить свои знания.

Напишите полный скрипт для создания окна в Tkinter с текстом «Python рулит!». Окно должно выглядеть следующим образом:

Tkinter примеры

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

Код с решением

import tkinter as tk

window = tk.Tk()

label = tk.Label(text=«Python рулит!»)

label.pack()

window.mainloop()

Работа с виджетами в Tkinter

Виджеты являются основой GUI фреймворка Tkinter в Python. Это элементы, через которые пользователи взаимодействуют с программой. В Tkinter каждый виджет определен классом. Далее представлен список популярных виджетов из Tkinter:

Класс виджета Описание
Label Используется для отображения текста или вставки изображения на окне приложения.
Button Кнопка, на которой может быть текст, совершает определенные действия при нажатии на нее.
Entry Виджет для ввода одной строчки текста. Эквивалент <input type="text"> в HTML.
Text Виджет для ввода большого текста. Эквивалент <textarea> в HTML.
Frame Прямоугольная область, что используется для группировки виджетов или для добавления расстояния между виджетами.

В дальнейшем, мы на практике рассмотрим, как действует каждый из представленных выше виджетов. С более подробными списками виджетов Tkinter можете ознакомиться на страницах Basic Widgets и More Widgets. А пока рассмотрим подробнее виджет ярлыка Label.

Виджет Label — Отображение текста и картинок

Виджеты Label используется для отображения текста или картинок. Текст на виджете Label, не может редактироваться пользователем. Он только показывается. Как было показано в примере в начале данного руководства, виджет Label можно создать через экземпляр класса Label и передачу строки в параметр text:

label = tk.Label(text=«Hello, Tkinter»)

Виджеты Label отображают текст с установленным по умолчанию системным цветом и фоном. Обычно это черный и белый цвета. Следовательно, если в вашей операционной системе указаны иные цвета, именно их вы и увидите.

Изменить цвет текста и фона виджета Label можно через параметры foreground и background:

label = tk.Label(

    text=«Привет, Tkinter!»,

    foreground=«white»,  # Устанавливает белый текст

    background=«black»  # Устанавливает черный фон

)

Некоторые доступные цвета:

  • red — красный;
  • orange — оранжевый;
  • yellow — желтый;
  • green — зеленый;
  • blue — синий;
  • purple — сиреневый.

Многие HTML-цвета имеют такое же название в Tkinter. Со списком доступных названий цветов можете ознакомиться здесь.

Все цвета в Tkinter

Если хотите подробнее разобраться в теме, особенно в системных цветах macOS и Windows, контролируемых текущей темой ОС, ознакомьтесь со страницей значений цветов.

Вы также можете указать цвет, используя шестнадцатеричные значения RGB такое часто используется в CSS для стилизации сайтов:

label = tk.Label(text=«Привет, Tkinter!», background=«#34A2FE»)

Теперь фон стал приятного голубого цвета. Шестнадцатеричные значения RGB, в отличие от названий цветов, закодированы, но это делает их более управляемыми. К счастью, доступны инструменты для простого и быстрого получения шестнадцатеричных кодов цветов.

Выбор HEX для цвета

Если вам не хочется регулярно вводить foreground и background, можете использовать сокращенные версии параметров — fg и bg. Они точно также отвечают за установку цвета текста и цвета фона.

label = tk.Label(text=«Привет, Tkinter!», fg=«white», bg=«black»)

Вы также можете управлять шириной и высотой ярлыка с помощью параметров width и height:

import tkinter as tk

window = tk.Tk()

label = tk.Label(

    text=«Привет, Tkinter!»,

    fg=«white»,

    bg=«black»,

    width=20,

    height=20

)

label.pack()

window.mainloop()

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

Tkinter Label

Может показаться странным, что ярлык в окне не является квадратным, хотя параметр как ширины, так и высоты равен 20. Все оттого, что ширина и высота измеряются в текстовых юнитах.

Горизонтальный текстовый юнит определен шириной символа "0", или цифрой ноль, в шрифте системы по умолчанию. Аналогичным образом один вертикальный текстовый юнит определен высотой символа "0".

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

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

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

Создание кнопки через виджет Button

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

Существует много сходств между виджетами Button и Label. По сути кнопка — это просто ярлык, на который можно кликнуть. Для создания стилей виджетов ярлыка и кнопки также используются одинаковые аргументы.

К примеру, следующий код создает кнопку с синим фоном и желтым текстом. Также устанавливается ширина и высота с показателями в 25 и 5 текстовых юнит:

import tkinter as tk

window = tk.Tk()

button = tk.Button(

    text=«Нажми на меня!»,

    width=25,

    height=5,

    bg=«blue»,

    fg=«yellow»,

)

button.pack()

window.mainloop()

Готовая кнопка будет выглядеть следующим образом:

Tkinter кнопки

Неплохо! Следующие два виджета Entry и Text используются для сбора вводных данных от пользователя.

Виджет Entry — Однострочное текстовое поле

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

Создание виджета Entry практически ничем не отличается от процесса создания ярлыка и кнопки. К примеру, следующий код создает виджет с синим фоном и желтым текстом длиной в 50 текстовых юнит:

entry = tk.Entry(fg=«yellow», bg=«blue», width=50)

В случае виджета однострочного текстового поля (Entry) интересен не процесс создания стиля, а то, как получить эти входные данные от пользователя. Есть три основные операции, что можно провести с виджетом однострочного текстового поля (Entry):

  • Получение всего текста через .get()
  • Удаление текста через .delete()
  • Вставка нового текста через .insert()

Для лучшего понимания принципа работы виджетов Entry создадим один экземпляр элемента и попробуем ввести в него текст. Откройте оболочку Python и выполните следующие действия. Сначала импортируем tkinter и создаем новое окно:

>>> import tkinter as tk

>>> window = tk.Tk()

Теперь создаем виджеты Label и Entry:

>>> label = tk.Label(text=«Имя»)

>>> entry = tk.Entry()

Здесь ярлык указывает, что именно пользователь должен записать в виджете Entry. Нет никаких ограничений для вводимых данных, это просто подсказка, что ввести нужно «Имя». Виджеты станут видимыми на окне после выполнения метода .pack() для каждого из них:

>>> label.pack()

>>> entry.pack()

Результат выглядит следующим образом:

Tkinter виджет Entry

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

На созданном в программе виджете мы ввели текст «Иван Иванов»:

Tkinter текстовое поле

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

>>> name = entry.get()

>>> name

‘Иван Иванов’

Текст также можно удалить, для этого используется метод .delete(). Данный метод принимает аргумент, который является целым числом и сообщает Python, какой символ нужно удалить. К примеру, во фрагменте кода ниже показано, как через метод .delete(0) можно удалить первый символ из текстового поля:

Теперь в виджете остался текст "ван Иванов":

Tkinter текстовое поле

Обратите внимание, что как и строки в Python, текст в виджете однострочного текстового поля индексируется,  и начинается индексирование с 0.

При необходимости удалить несколько символов из текстового поля нужно передать второй целочисленный аргумент в .delete(), указав индекс символа, на котором процесс удаления должен завершиться. К примеру, следующий код удаляет первые четыре буквы из текстового поля:

Теперь остался только текст "Иванов":

Tkinter удаление из Entry

Метод .delete() работает по аналогии с методом строк slice() для удаления части символов из строки. Первый аргумент определяет начальный индекс удаления, последний индекс указывает где именно процесс удаления должен остановиться.

Для удаления всего текста из текстового поля во втором аргументе метода .delete() используется специальная константа tk.END:

>>> entry.delete(0, tk.END)

Теперь остался пустой текстовый бокс:

Tkinter виджет Entry

Вы также можете вставить текст в виджете однострочного текстового поля с помощью метода .insert():

>>> entry.insert(0, «Иванов»)

Теперь окно стало таким:

Tkinter удаление из Entry

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

К примеру, при вызове .insert() с первым аргументом 100, а не 0, как было сделано выше, вывод будет тем же.

В том случае, если текстовое поле уже содержит какой-то текст, тогда .insert() вставить новый текст в указанную позицию и сдвинет существующий текст вправо:

>>> entry.insert(0, «Иван «)

В виджете с текстом теперь значится "Иван Иванов":

Tkinter текстовое поле

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

Виджет Text — ввод большого текста в Tkinter

Виджеты Text используются для ввода текста, как и виджеты Entry. Разница в том, что Text может содержать несколько строчек текста. С виджетом Text пользователь может вводить целые параграфы или страницы текста. Как и в случае с виджетами Entry, над виджетами Text можно провести три основные операции:

  • Получение текста через метод .get()
  • Удаление текста через метод .delete()
  • Вставка текста через метод .insert()

Несмотря на то, что названия методов совпадают с теми, что используются в Entry, процесс реализации несколько различен. Разберем пример создания виджета Text и посмотрим на деле, что он может делать.

На заметку: У вас все еще открыто предыдущее окно? Если это так, тогда закройте его, выполнив следующую команду:

Это также можно сделать вручную, просто нажав на кнопку «Закрыть».

В оболочке Python нужно создать новое пустое окно, а внутри нее с помощью метода .pack() разместить текстовой виджет:

>>> import tkinter as tk

>>> window = tk.Tk()

>>> text_box = tk.Text()

>>> text_box.pack()

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

Форма для ввода текста в Tkinter

Для активации текстового бокса нажмите на любую точку внутри окна. Введите слово "Hello". Нажмите на клавиатуре кнопку Enter, после чего введите на второй строке слово "World". Окно будет выглядеть следующим образом:

text tkinter

Как и в случае с виджетами Entry, вы можете получить текст их виджета Text с помощью метода .get(). Однако, вызов .get() без аргументов не возвращает весь текст как это происходит с виджетами однострочного ввода текста Entry. Появится исключение TypeError:

>>> text_box.get()

Traceback (most recent call last):

  File «<pyshell#4>», line 1, in <module>

    text_box.get()

TypeError: get() missing 1 required positional argument: ‘index1’

Метод .get() для текстового виджета запрашивает хотя бы один аргумент. Вызов .get() с единственным индексом возвращает один символ. Для получения нескольких символов требуется передать начальный и конечный индексы.

Индексы в виджетах Text действуют иначе, чем в виджетах Entry. Так как виджеты Text могут получить несколько строк текста, индекс должен содержать следующие два пункта:

  • Номер строки где находится символа;
  • Позиция символа в строке.

Номера строк начинаются с 1, а позиция символа с 0. Для получения индекса создается строка формата "<line>.<char>", где <line> заменяется номером строки, а <char> номером символа. К примеру, "1.0" означает первый символ на первой строке, а "2.3" представляет четвертый символ на второй строке.

Используем индекс "1.0" для получения первой буквы созданного ранее текстового бокса:

>>> text_box.get(«1.0»)

‘H’

В слове "Hello" 5 букв, буква o стоит под индексом 4, так как отсчет символов начинается с 0, и слово "Hello" начинается с первой строки в текстовом боксе.

Как при слайсинге строк в Python, для получения целого слова "Hello" из текстового бокса, конечный индекс должен быть на один больше последнего читаемого символа.

Таким образом, для получения слова "Hello" из текстового бокса используется "1.0" для первого индекса, и "1.5" для второго индекса:

>>> text_box.get(«1.0», «1.5»)

‘Hello’

Для получения "World" на второй строке текстового бокса, измените номера строк каждого индекса на 2:

>>> text_box.get(«2.0», «2.5»)

‘World’

Для получения всего текста из текстового виджета установите индекс на "1.0" и используйте специальную константу tk.END для второго индекса:

>>> text_box.get(«1.0», tk.END)

‘HellonWorldn’

Обратите внимание, что текст, возвращаемый через метод .get(), включает символы перехода на новую строку n. Вы также можете увидеть в данном примере, что каждая строка в виджете Text содержит в конце символ новой строки, включая последнюю строку текста в текстовом боксе.

Метод .delete() используется для удаления символов из текстового виджета. Работает точно так же, как и метод .delete() для виджетов Entry. Есть два способа использования .delete():

  • С одним аргументом;
  • С двумя аргументами.

Используя вариант с одним аргументом, вы передаете индекс символа для удаления в .delete(). К примеру, следующий код удаляет первый символ H из текстового бокса:

>>> text_box.delete(«1.0»)

Теперь в первой строке текста значится "ello":

delete tkinter

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

К примеру, для удаления оставшейся части "ello" из первой строки текстового бокса используются индексы "1.0" и "1.4":

>>> text_box.delete(«1.0», «1.4»)

Обратите внимание, что текст из первой строки удалился, но осталась пустая строка, за которой следует слово World на второй строке:

delete tkinter

Хотя вам этого не видно, но на первой строке остался один символ — это символ новой строки n. Вы можете сами убедиться в этом, вызвав метод .get():

>>> text_box.get(«1.0»)

‘n’

При удалении данного символа оставшаяся часть содержимого текстового виджета сдвинется на строку вверх:

>>> text_box.delete(«1.0»)

Теперь слово "World" переместилось на первую строку текстового виджета:

delete tkinter

Попробуем очистить оставшуюся часть из текстового виджета. Установим "1.0" в качестве стартового индекса и tk.END в качестве второго индекса:

>>> text_box.delete(«1.0», tk.END)

Теперь наш текстовый виджет совершенно пуст:

empty textbox tkinter

Вы также можете вставить текст в текстовый виджет с помощью метода  .insert():

>>> text_box.insert(«1.0», «Hello»)

Метод вставляет слово "Hello" в начало текстового виджета. Используется уже знакомый формат "<line>.<column>" как и у метода .get() для уточнения позиции вставки текста:

insert tkinter

Проверьте, что произойдет при попытке вставить слово "World" во вторую строчку:

>>> text_box.insert(«2.0», «World»)

Вместо вставки слова на вторую строку текст ставится в конце первой строки:

insert tkinter

Если вы хотите поставить текст на новую строку, тогда понадобится вставить символ новой строки n вручную:

>>> text_box.insert(«2.0», «nWorld»)

Теперь слово "World" находится на второй строке текстового виджета:

insert tkinter new line

Метод .insert() делает следующие две вещи:

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

Обычно нецелесообразно пытаться отследить индекс последнего символа. Лучший способ вставить текст в конец виджета Text — передать tk.END как первый параметр в методе .insert():

text_box.insert(tk.END, «Вставь меня в самом конце!»)

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

text_box.insert(tk.END, «nВставь меня в новую строку!»)

Виджеты Label, Button, Entry и Text являются только небольшой частью виджетов, доступных в Tkinter. Среди прочих виджетов есть чекбоксы, радио кнопки, скролл бары и прогресс бары.

Использование виджета Frame в Tkinter

В данном руководстве мы рассмотрим только пять виджетов. Это описанные ранее четыре виджета плюс виджет рамки Frame. Виджеты рамок важны для организации макета виджетов в приложении.

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

import tkinter as tk

window = tk.Tk()

frame = tk.Frame()

frame.pack()

window.mainloop()

Метод frame.pack() помещает рамку в окно, таким образом размер окна становится таким маленьким, каким он может быть для того, чтобы поместился рамку. При запуске скрипта выше будет получен крайне скучный вывод:

frame tkinter

Пустой виджет рамки практически невидим.

Рамки лучше всего рассматривать как контейнеры для других виджетов.

Вы можете вставить любой виджет в рамку, установив атрибут master данному виджету:

frame = tk.Frame()

label = tk.Label(master=frame)

Чтобы посмотреть, как это работает, напишем скрипт для создания двух виджетов Frame под названиями frame_a и frame_b. В данном скрипте frame_a содержит ярлык с текстом "I'm in Frame A", а frame_b содержит ярлык с текстом "I'm in Frame B". Вот как это можно сделать:

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

import tkinter as tk

window = tk.Tk()

frame_a = tk.Frame()

frame_b = tk.Frame()

label_a = tk.Label(master=frame_a, text=«I’m in Frame A»)

label_a.pack()

label_b = tk.Label(master=frame_b, text=«I’m in Frame B»)

label_b.pack()

frame_a.pack()

frame_b.pack()

window.mainloop()

Обратите внимание, что рамка frame_a помещается в окно перед рамкой frame_b. Открывающееся окно показывает ярлык в рамке frame_a над ярлыком в рамке frame_b:

frame tkinter

Теперь посмотрим, что произойдет при изменении порядка вставки frame_a.pack() и frame_b.pack():

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

import tkinter as tk

window = tk.Tk()

frame_a = tk.Frame()

label_a = tk.Label(master=frame_a, text=«I’m in Frame A»)

label_a.pack()

frame_b = tk.Frame()

label_b = tk.Label(master=frame_b, text=«I’m in Frame B»)

label_b.pack()

# Вставка рамок в окне поменялись местами.

frame_b.pack()

frame_a.pack()

window.mainloop()

Вывод выглядит следующим образом:

frame tkinter

Теперь ярлык label_b сверху. Так как ярлык label_b назначен к рамке frame_b, он перемещается, куда позиционируется рамка  frame_b.

У всех четырех рассмотренных типов виджетов — Label, Button, Entry и Text — есть атрибут master, который устанавливается при их создании. Таким образом, вы можете управлять тем, к какой именно рамки назначен виджет.

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

В дополнение к логической группировке ваших виджетов, рамки могут  немного улучшить внешний вид вашего приложения. Дальше будет показано, как менять стиль рамок.

Атрибут relief в Tkinter — Меняем стиль рамки

Рамки могут менять свой стиль с помощью атрибута relief, который создает границу вокруг рамки. Можно присвоить relief любое из следующих значений:

  • tk.FLAT: Никакого эффекта рамки (по умолчанию);
  • tk.SUNKEN: Создается эффект углубления элемента;
  • tk.RAISED: Создается эффект выпуклости элемента;
  • tk.GROOVE: Создается эффект врезанной в текстуру рамки, своего рода выемки;
  • tk.RIDGE: Создается эффект выпуклой выемки.

Для применения эффекта рамки нужно установить значение атрибута borderwidth выше, чем 1. Данный атрибут корректирует ширину рамки в пикселях. Лучший способ понять, как выглядит каждый эффект — проверить на практике.

Вот скрипт, который помещает пять рамок в окно, где каждая из которых имеет свое значение аргумента relief:

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

19

import tkinter as tk

border_effects = {

    «flat»: tk.FLAT,

    «sunken»: tk.SUNKEN,

    «raised»: tk.RAISED,

    «groove»: tk.GROOVE,

    «ridge»: tk.RIDGE,

}

window = tk.Tk()

for relief_name, relief in border_effects.items():

    frame = tk.Frame(master=window, relief=relief, borderwidth=5)

    frame.pack(side=tk.LEFT)

    label = tk.Label(master=frame, text=relief_name)

    label.pack()

window.mainloop()

Разбор скрипта по строкам кода:

  • Строки с 3 по 9 создают словарь, ключами которого являются названия различных эффектов от relief, доступных в Tkinter. Значения являются соответствующими объектами Tkinter. Этот словарь назначен переменной border_effects
  • Строка 13 запускает цикл for для каждого элемента в словаре border_effects
  • Строка 14 создает новый виджет Frame и назначает его объекту window. Атрибут relief установлен на соответствующий элемент рельефа в словаре border_effects, а атрибут border установлен на 5 пикселей, чтобы эффект был видимым
  • Строка 15 помещает виджет рамки в окно с помощью метода .pack(). Ключевое слово side указывает Tkinter, где поместить поместить рамку. Подробнее о том, как это работает, вы узнаете в следующем разделе.
  • Строки 16 и 17 создаем виджет текстового ярлыка для отображения названия рельефа и помещаем его в только что созданную рамку.

Окно, созданное вышеуказанным скриптом, выглядит следующим образом:

frame tkinter

На данной картинке представлены следующие эффекты:

  • tk.FLAT создает простую рамку без видимой границы;
  • tk.SUNKEN добавляет границу, которая создает эффект, будто элемент провалился в окне;
  • tk.RAISED создает рамке границу в виде эффекта выпуклости;
  • tk.GROOVE добавляет эффект врезанной, будто утопающей в текстуру, рамки;
  • tk.RIDGE создает эффект, будто врезанной с другой стороны выпуклой рамки.

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

Правила именования виджетов в Tkinter

При создании виджета можно дать ему любое имя при условии, что данное имя уже не зарегистрировано самим Python, вроде with, for, range и т.д.

Обычно хорошей идеей является включение имени класса виджета в имя переменной, которую вы назначаете экземпляру виджета. Например, если виджет Label используется для отображения имени пользователя, вы можете назвать виджет label_user_name. Виджет Entry, используемый для определения возраста пользователя, может называться entry_age.

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

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

Класс виджета Префикс названия переменной Пример
Label lbl lbl_name
Button btn btn_submit
Entry ent ent_age
Text txt txt_notes
Frame frm frm_address

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

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

Задание #2 — Создать текстовое поле и вставить в нее текст

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

Задание: Создать однострочное текстовое поле и вставить на нее какой-то текст.

  1. Напишите скрипт для отображения виджета однострочного текстового поля Entry шириной в 40 текстовых юнитов с белым фоном и черным текстом;
  2. Используйте метод .insert() для вставки текста: "What is your name?".

Результат должен выглядеть следующим образом:

tkinter entry

Попробуйте выполнить задание самостоятельно.

Ниже представлен вариант кода для выполнения данного задания. В следующем варианте для установки фона и цвета шрифта текстового виджета, используются параметры bg и fg. Помните, что ваша программа может отличаться от нашей, у каждого разработчика свой стиль программирования.

Код с решением задачи #2

import tkinter as tk

window = tk.Tk()

entry = tk.Entry(width=40, bg=«white», fg=«black»)

entry.pack()

entry.insert(0, «What is your name?»)

window.mainloop()

Это хорошее решение, цвет фона и цвет шрифта для виджета однострочного текстового поля Entry указываются довольно просто.

В большинстве систем по умолчанию цвет фона для виджета Entry — белый, а цвет содержимого — черный. Таким образом, вы можете создать то же самое окно, не уточняя при этом параметры bg и fg:

Измененный код с решением задачи #2

import tkinter as tk

window = tk.Tk()

entry = tk.Entry(width=40)

entry.pack()

entry.insert(0, «What is your name?»)

window.mainloop()

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

Настройка макета приложения через менеджеры геометрии

До данного момента мы добавляли виджеты на окно с помощью метода  .pack(), однако что именно делает данный метод нам пока неизвестно.

Давайте все проясним. Макет приложения в Tkinter управляется через менеджеры геометрии. Одним из менеджеров геометрии является .pack(). Помимо него в Tkinter есть еще двое таких менеджеров:

  • .place()
  • .grid()

Каждое окно и рамка в приложении может использовать только один менеджер геометрии. Однако разные рамки могут использовать разные менеджеры геометрии, даже если они назначены окну или рамики, что использует другой менеджер геометрии. Начнем с более подробного разбора менеджера .pack().

Менеджер геометрии pack() в Tkinter

Менеджер .pack() используется для размещения виджетов на рамку или на окне приложения в определенном порядке использует алгоритм упаковки. Для заданного виджета у алгоритма упаковки есть два основных этапа:

  • Расчет прямоугольной области, называемой участком. Размер области подходит для вмещения виджета, а оставшаяся ширина (или высота) окна заполняется пустым пространством;
  • Центрирование виджета в участке, если не указано другое местоположение в окне.

Менеджер геометрии .pack() является мощным инструментом, но его может быть трудно визуализировать. Лучший способ понять .pack() — это разобрать примеры.

Посмотрите, что происходит при размещении трех виджетов ярлыков с текстом в рамку через менеджер .pack():

import tkinter as tk

window = tk.Tk()

frame1 = tk.Frame(master=window, width=100, height=100, bg=«red»)

frame1.pack()

frame2 = tk.Frame(master=window, width=50, height=50, bg=«yellow»)

frame2.pack()

frame3 = tk.Frame(master=window, width=25, height=25, bg=«blue»)

frame3.pack()

window.mainloop()

По умолчанию .pack() помещает каждую рамку друг под другом в том порядке, в котором они добавлены на окно приложения:

pack tkinter

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

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

Менеджер .pack() принимает некоторые ключевые аргументы для более точной настройки размещения виджетов. К примеру, можно установить ключевой аргумент fill для уточнения в какое направление рамки будут пополняться. Доступная опция tk.X для горизонтального направления, tk.Y для вертикального направления и tk.BOTH для обоих. Далее представлен код для горизонтального заполнения окна тремя рамками:

import tkinter as tk

window = tk.Tk()

frame1 = tk.Frame(master=window, height=100, bg=«red»)

frame1.pack(fill=tk.X)

frame2 = tk.Frame(master=window, height=50, bg=«yellow»)

frame2.pack(fill=tk.X)

frame3 = tk.Frame(master=window, height=25, bg=«blue»)

frame3.pack(fill=tk.X)

window.mainloop()

Обратите внимание, что для виджета рамки ширина width не установлена. Аргумент width больше не требуется, так как каждая рамка задействует .pack() для горизонтального заполнения, переписывая любой индивидуальный параметр ширины.

Результат вышеуказанного скрипта будет выглядеть следующим образом:

frame tkinter

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

tkinter response

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

Аргумент side от метода .pack() уточняет, на какую сторону окна виджет должен размещаться. Доступные варианты:

  • tk.TOP сверху;
  • tk.BOTTOM снизу;
  • tk.LEFT слева;
  • tk.RIGHT  справа.

В случае, если аргумент side не указан, тогда метод .pack() автоматически использует tk.TOP и ставит новые виджеты в верхнюю часть окна, или в самую верхнюю часть окна, которая еще не занята виджетом. К примеру, следующий скрипт размещает три рамки рядом друг с другом слева направо и расширяет каждую рамку, чтобы заполнить окно по вертикали:

import tkinter as tk

window = tk.Tk()

frame1 = tk.Frame(master=window, width=200, height=100, bg=«red»)

frame1.pack(fill=tk.Y, side=tk.LEFT)

frame2 = tk.Frame(master=window, width=100, bg=«yellow»)

frame2.pack(fill=tk.Y, side=tk.LEFT)

frame3 = tk.Frame(master=window, width=50, bg=«blue»)

frame3.pack(fill=tk.Y, side=tk.LEFT)

window.mainloop()

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

Полученное окно выглядит следующим образом:

tkinter frames

При установке аргумента fill=tk.X рамки адаптируются при горизонтальном изменении размера окна, а при указании аргумента fill=tk.Y они адаптируются при изменении размера окна по вертикали:

tkinter vertical

Для того чтобы сделать макет по-настоящему адаптированным, можно установить начальный размер фреймов, используя атрибуты width и height. Затем нужно установить значение аргумента fill от метода .pack() на tk.BOTH, а также установить значение аргумента expand на True:

import tkinter as tk

window = tk.Tk()

frame1 = tk.Frame(master=window, width=200, height=100, bg=«red»)

frame1.pack(fill=tk.BOTH, side=tk.LEFT, expand=True)

frame2 = tk.Frame(master=window, width=100, bg=«yellow»)

frame2.pack(fill=tk.BOTH, side=tk.LEFT, expand=True)

frame3 = tk.Frame(master=window, width=50, bg=«blue»)

frame3.pack(fill=tk.BOTH, side=tk.LEFT, expand=True)

window.mainloop()

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

tk full responsive

Вышло неплохо!

Менеджер геометрии place() в Tkinter

Для управления точным местом расположения виджета в окне или в рамке используется менеджер .place(). Вы должны указать два ключевых аргумента x и y, которые определяют координаты x и y для верхнего левого угла виджета. Аргументы x и y измеряются в пикселях, а не в текстовых юнитах.

Имейте в виду, что начало координат (где x и y равны 0) — это верхний левый угол рамки или окна. Таким образом, вы можете рассматривать аргумент y в методе .place() как количество пикселей в верхней части окна, а аргумент x — в качестве количества пикселей в левой части окна.

Вот пример того, как работает менеджер геометрии .place():

import tkinter as tk

window = tk.Tk()

frame = tk.Frame(master=window, width=150, height=150)

frame.pack()

label1 = tk.Label(master=frame, text=«I’m at (0, 0)», bg=«red»)

label1.place(x=0, y=0)

label2 = tk.Label(master=frame, text=«I’m at (75, 75)», bg=«yellow»)

label2.place(x=75, y=75)

window.mainloop()

Разберем код:

  • Строки 5 и 6 создают новый виджет рамки Frame под названием frame1, его ширина 150 пикселей и высота также 150 пикселей, и упаковывают его в окно с помощью .pack();
  • Строки 8 и 9 создают новый ярлык с текстом под названием label1 с желтым фоном и помещает его в рамку frame1 на позицию (0, 0);
  • Строки 11 и 12 создают второй ярлык с текстом под названием label2 на красном фоне и помещают его в рамку frame1 на позицию (75, 75).

Вот окно, которое создалась при выполнении данного кода:

tk place

Менеджер геометрии .place() используется не очень часто. У него есть два значимых недостатка:

  • Через метод .place() макет сложно настраивать, особенно в тех случаях, когда у приложений много виджетов;
  • Макеты, созданные при помощи менеджера .place(), не адаптируются. Они не меняются вместе с изменением размера главного окна.

Одной из основных проблем при разработке кроссплатформенного графического интерфейса является создание макетов, которые хорошо выглядят независимо от того, на какой платформе они просматриваются.

В таком случае менеджер геометрии .place() — плохой выбор для создания адаптивных и кроссплатформенных макетов.

Однако это не значит, что нужно отказаться от использования менеджера  .place()!

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

Как правило, лучше использовать менеджер .pack(), а не .place(). Тем не менее, и у .pack() есть определенные недостатки. Расположение виджетов зависит от порядка, в котором вызывается метод .pack(), поэтому может быть сложно модифицировать существующие приложения без полного понимания кода, управляющего макетом. Менеджер геометрии .grid() решает многие из этих проблем.

Поговорим об этом в следующем разделе.

Менеджер геометрии grid() в Tkinter

Самым популярным менеджером геометрии в Tkinter является .grid(). Он обладает всей мощностью .pack(), будучи намного более простым в использовании.

Менеджер .grid() работает путем разделения окна или рамки на строки и столбцы (на сетку). Вы указываете местоположение виджета, вызывая метод .grid() и передавая индексы row и column (строки и столбца) в ключевые аргументы строки и столбца соответственно.

Индексы строк и столбцов начинаются с 0, поэтому индекс строки 1 и индекс столбца 2 указывают методу .grid(), что виджет нужно разместить в третьем столбце второй строки.

Следующий скрипт создает сетку из рамок 3 × 3 с находящимися в них ярлыками с текстом:

import tkinter as tk

window = tk.Tk()

for i in range(3):

    for j in range(3):

        frame = tk.Frame(

            master=window,

            relief=tk.RAISED,

            borderwidth=1

        )

        frame.grid(row=i, column=j)

        label = tk.Label(master=frame, text=f«Row {i}nColumn {j}»)

        label.pack()

window.mainloop()

Результат выглядит следующим образом:

tk grid

В данном примере использовались два менеджера геометрии. Каждая рамка привязана к определенному окну через менеджер геометрии grid():

import tkinter as tk

window = tk.Tk()

for i in range(3):

    for j in range(3):

        frame = tk.Frame(

            master=window,

            relief=tk.RAISED,

            borderwidth=1

        )

        frame.grid(row=i, column=j)

        label = tk.Label(master=frame, text=f«Row {i}nColumn {j}»)

        label.pack()

window.mainloop()

Каждый ярлык с текстом привязан к определенной рамки через менеджер .pack():

import tkinter as tk

window = tk.Tk()

for i in range(3):

    for j in range(3):

        frame = tk.Frame(

            master=window,

            relief=tk.RAISED,

            borderwidth=1

        )

        frame.grid(row=i, column=j)

        label = tk.Label(master=frame, text=f«Row {i}nColumn {j}»)

        label.pack()

window.mainloop()

Важно понимать, что метод .grid() вызывается для каждого объекта рамки, но менеджер геометрии применяется к окну. Аналогично, расположение каждой рамки контролируется менеджером геометрии .pack().

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

Отступ, или padding — это просто пустое пространство, которое окружает виджет и визуально отделяет его от его содержимого.

Есть два вида отступов — внешние и внутренние. Внешнее отступы добавляют пространство вокруг ячейки сетки. Управление осуществляется через два ключевые аргумента метода .grid():

  • padx добавляет отступ в горизонтальном направлении;
  • pady добавляет отступы в вертикальном направлении.

Аргументы padx и pady измеряются в пикселях, а не в текстовых юнитах, поэтому установка их обоих на одно и то же значение создаст одинаковое количество отступов в обоих направлениях. Попробуем добавить отступы вокруг рамок из предыдущего примера:

import tkinter as tk

window = tk.Tk()

for i in range(3):

    for j in range(3):

        frame = tk.Frame(

            master=window,

            relief=tk.RAISED,

            borderwidth=1

        )

        frame.grid(row=i, column=j, padx=5, pady=5)

        label = tk.Label(master=frame, text=f«Row {i}nColumn {j}»)

        label.pack()

window.mainloop()

Вот результат:

padding tkinter

У менеджера геометрии .pack() также есть параметры padx и pady. Следующий код почти идентичен предыдущему коду, за исключением того, что добавляется 5 пикселей дополнительного отступа вокруг каждого ярлыка с текстом в направлениях x и y:

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

import tkinter as tk

window = tk.Tk()

for i in range(3):

    for j in range(3):

        frame = tk.Frame(

            master=window,

            relief=tk.RAISED,

            borderwidth=1

        )

        frame.grid(row=i, column=j, padx=5, pady=5)

        label = tk.Label(master=frame, text=f«Row {i}nColumn {j}»)

        label.pack(padx=5, pady=5)

window.mainloop()

Дополнительные отступы вокруг ярлыков с текстом немного расширяют место для каждой ячейки в сетке между рамкой Frame и текстом на ярлыке Label:

padding tkinter

Выглядит неплохо! Однако при попытке расширить окно в каком бы то ни было направлении можно заметить, что макет не адаптируется:

tk grid unresponsive

При расширении окна сетка с виджетами остается в верхнем левом углу.

Можно настроить так, чтобы строки и столбы сетки будут реагировать на изменение размера окна с помощью метода .columnconfigure() и .rowconfigure() для объекта окна приложения. Помните, что сетка привязана к окну, даже если вы вызываете метод .grid() для каждой рамки. Метод .columnconfigure() и .rowconfigure() принимают три важных аргумента:

  1. Индекс столбца или строки сетки, которого нужно настроить (или список индексов для настройки нескольких строк или столбцов одновременно);
  2. Ключевой аргумент под названием weight, который определяет, как столбец или строка должны реагировать на изменение размера окна относительно других столбцов и строк;
  3. Ключевой аргумент под названием minsize, который устанавливает минимальный размер высоты строки или ширины столбца в пикселях.

Аргумент weight по умолчанию равен 0 . Это означает, что столбец или строка не расширяются при изменении размера окна. Если каждому столбцу и строке присвоен weight=1, то все они будут меняться одинаково. Если вес (weight) одного столбца 1, а у другого 2, то второй столбец расширяется вдвое быстрее первого. Настроим предыдущий скрипт для лучшей обработки изменения размера окна:

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

19

20

import tkinter as tk

window = tk.Tk()

for i in range(3):

    window.columnconfigure(i, weight=1, minsize=75)

    window.rowconfigure(i, weight=1, minsize=50)

    for j in range(0, 3):

        frame = tk.Frame(

            master=window,

            relief=tk.RAISED,

            borderwidth=1

        )

        frame.grid(row=i, column=j, padx=5, pady=5)

        label = tk.Label(master=frame, text=f«Row {i}nColumn {j}»)

        label.pack(padx=5, pady=5)

window.mainloop()

Метод .columnconfigure() и .rowconfigure() помещаются в тело внешнего цикла for. Можно точно настроить каждый столбец и строку за пределами цикла for, однако для этого нужно будет написать дополнительные шесть строк кода.

В каждой итерации цикла i-ые столбцы и строки настраиваются таким образом, чтобы значение их weight было равно 1. Это является гарантией того, что каждая строка и столбец расширяются с одинаковой скоростью при изменении размера окна. Аргумент minsize имеет значение 75 для каждого столбца и 50 для каждой строки. Это гарантирует, что ярлык с текстом всегда отображает свой текст без обрезания каких-либо символов, даже если размер окна очень мал.

Результатом является макет сетки, который плавно расширяется и сжимается при изменении размера окна:

tk grid resize

Попробуйте самим изменить размер окна. Поэкспериментируйте с параметрами weight и minsize, чтобы посмотреть, как они влияют на сетку.

По умолчанию виджеты центрируются в своих ячейках сетки. К примеру, следующий код создает два ярлыка с текстом и помещает их в сетку с одним столбцом и двумя строками:

import tkinter as tk

window = tk.Tk()

window.columnconfigure(0, minsize=250)

window.rowconfigure([0, 1], minsize=100)

label1 = tk.Label(text=«A»)

label1.grid(row=0, column=0)

label2 = tk.Label(text=«B»)

label2.grid(row=1, column=0)

window.mainloop()

Ширина каждой ячейка сетки 250 пикселей, высота 100 пикселей. Ярлыки с текстом помещаются в центре каждой ячейки, как показано в следующей фигуре:

tk grid

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

  • «n» или «N»Север — выравнивает по верхней центральной части ячейки;
  • «e» или «E»Запад — выравнивает по правой центральной части ячейки;
  • «s» или «S»Юг — выравнивает по нижней центральной части ячейки;
  • «w» или «W»Восток — выравнивает по левой центральной части ячейки.

Буквы «n», «s», «e» и «w» идут по траектории с севера, на юг, затем восток и запад. Установка параметра sticky со значением «n» для обоих ярлыков из предыдущего кода позиционируют каждый ярлык с текстом в верхнюю центральную ячейку сетки:

import tkinter as tk

window = tk.Tk()

window.columnconfigure(0, minsize=250)

window.rowconfigure([0, 1], minsize=100)

label1 = tk.Label(text=«A»)

label1.grid(row=0, column=0, sticky=«n»)

label2 = tk.Label(text=«B»)

label2.grid(row=1, column=0, sticky=«n»)

window.mainloop()

Результат:

tk grid

Можно комбинировать несколько букв в одной строке для позиционирования каждого ярлыка в углу его ячейки из сетки:

import tkinter as tk

window = tk.Tk()

window.columnconfigure(0, minsize=250)

window.rowconfigure([0, 1], minsize=100)

label1 = tk.Label(text=«A»)

label1.grid(row=0, column=0, sticky=«ne»)

label2 = tk.Label(text=«B»)

label2.grid(row=1, column=0, sticky=«sw»)

window.mainloop()

В данном примере параметр sticky ярлыка label1 настроен на "ne", который позиционируется ярлык в верхний правый угол ячейки сетки. Ярлык label2 позиционируется в нижнем левом углу, указывая "sw" в аргументе sticky.

Вот как будет выглядеть окно:

tk grid

Когда виджет позиционируется через sticky, размера самого виджета достаточно для размещения любого текста и другого содержимого внутри него. Он не заполнить всю ячейку сетки. Для заполнения всей сетки можно указать "ns", заставив виджет заполнить ячейку в вертикальном направлении, или "ew" для заполнения ячейки в горизонтальном направлении. Для заполнения всей ячейки в sticky требуется указать "nsew".

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

import tkinter as tk

window = tk.Tk()

window.rowconfigure(0, minsize=50)

window.columnconfigure([0, 1, 2, 3], minsize=50)

label1 = tk.Label(text=«1», bg=«black», fg=«white»)

label2 = tk.Label(text=«2», bg=«black», fg=«white»)

label3 = tk.Label(text=«3», bg=«black», fg=«white»)

label4 = tk.Label(text=«4», bg=«black», fg=«white»)

label1.grid(row=0, column=0)

label2.grid(row=0, column=1, sticky=«ew»)

label3.grid(row=0, column=2, sticky=«ns»)

label4.grid(row=0, column=3, sticky=«nsew»)

window.mainloop()

Результат выглядит следующим образом:

tk grid

Приведенный выше пример демонстрирует то, что параметр sticky от менеджера геометрии .grid() может использоваться для достижения тех же эффектов, что и параметр fill от менеджера геометрии .pack(). Параллели между параметрами sticky и fill представлены в следующей таблице:

Метод grid() Метод pack()
sticky="ns" fill=tk.Y
sticky="ew" fill=tk.X
sticky="nsew" fill=tk.BOTH

Метод .grid() является довольно мощным менеджером геометрии. Зачастую его проще понять, чем менеджер .pack(). Он также универсальнее, нежели менеджер .place(). При создании новых приложений в Tkinter, в качестве основного менеджера геометрии лучше рассматривать .grid().

На заметку: .grid() очень гибок в плане управления. Например, вы можете настроить ячейки на несколько строк и столбцов. Для получения дополнительной информации просмотрите раздел Grid Geometry Manager.

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

Задание #3 Создайте анкету с контактными данными клиента

Ниже дано еще одно задание для проверки понимания всего изученного.

Задание: Создать форму для ввода полного адреса клиента.

Ниже представлено изображение формы для ввода полного домашнего адреса клиента, которая была создана через Tkinter.

Форма ввода адреса в Tkinter

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

Ниже представлен наш вариант кода. Есть много разных способов выполнить данное задание. Если ваш вариант воспроизводит такое же окно как на картинке, то поздравляем! Вы справились! Ниже можете также ознакомиться с двумя вариантами кода, где используется менеджер .grid().

В следующем варианте создаются виджеты ярлыка с текстом и однострочное поле для ввода текста для каждого поля с желаемыми данными:

Полный код с решением задачи #3

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

19

20

21

22

23

24

25

26

27

28

29

30

31

32

33

34

35

36

37

38

39

40

41

42

43

44

45

46

47

48

49

50

51

52

53

54

55

56

57

58

59

60

61

62

63

64

65

66

67

68

69

70

71

72

73

74

75

76

77

78

79

80

81

82

83

84

85

86

87

88

89

import tkinter as tk

# Создается новое окно с заголовком «Введите домашний адрес»

window = tk.Tk()

window.title(«Введите домашний адрес»)

# Создается новая рамка `frm_form` для ярлыков с текстом и

# Однострочных полей для ввода информации об адресе.

frm_form = tk.Frame(relief=tk.SUNKEN, borderwidth=3)

# Помещает рамку в окно приложения.

frm_form.pack()

# Создает ярлык и текстовок поле для ввода имени.

lbl_first_name = tk.Label(master=frm_form, text=«Имя:»)

ent_first_name = tk.Entry(master=frm_form, width=50)

# Использует менеджер геометрии grid для размещения ярлыка и

# однострочного поля для ввода текста в первый и второй столбец

# первой строки сетки.

lbl_first_name.grid(row=0, column=0, sticky=«e»)

ent_first_name.grid(row=0, column=1)

# Создает ярлык и текстовок поле для ввода фамилии.

lbl_last_name = tk.Label(master=frm_form, text=«Фамилия:»)

ent_last_name = tk.Entry(master=frm_form, width=50)

# Размещает виджеты на вторую строку сетки

lbl_last_name.grid(row=1, column=0, sticky=«e»)

ent_last_name.grid(row=1, column=1)

# Создает ярлык и текстовок поле для ввода первого адреса.

lbl_address1 = tk.Label(master=frm_form, text=«Адрес 1:»)

ent_address1 = tk.Entry(master=frm_form, width=50)

# Размещает виджеты на третьей строке сетки.

lbl_address1.grid(row=2, column=0, sticky=«e»)

ent_address1.grid(row=2, column=1)

# Создает ярлык и текстовок поле для ввода второго адреса.

lbl_address2 = tk.Label(master=frm_form, text=«Адрес 2:»)

ent_address2 = tk.Entry(master=frm_form, width=50)

# Размещает виджеты на четвертой строке сетки.

lbl_address2.grid(row=3, column=0, sticky=tk.E)

ent_address2.grid(row=3, column=1)

# Создает ярлык и текстовок поле для ввода города.

lbl_city = tk.Label(master=frm_form, text=«Город:»)

ent_city = tk.Entry(master=frm_form, width=50)

# Размещает виджеты на пятой строке сетки.

lbl_city.grid(row=4, column=0, sticky=tk.E)

ent_city.grid(row=4, column=1)

# Создает ярлык и текстовок поле для ввода региона.

lbl_state = tk.Label(master=frm_form, text=«Регион:»)

ent_state = tk.Entry(master=frm_form, width=50)

# Размещает виджеты на шестой строке сетки.

lbl_state.grid(row=5, column=0, sticky=tk.E)

ent_state.grid(row=5, column=1)

# Создает ярлык и текстовок поле для ввода почтового индекса

lbl_postal_code = tk.Label(master=frm_form, text=«Почтовый индекс:»)

ent_postal_code = tk.Entry(master=frm_form, width=50)

# Размещает виджеты на седьмой строке сетки.

lbl_postal_code.grid(row=6, column=0, sticky=tk.E)

ent_postal_code.grid(row=6, column=1)

# Создает ярлык и текстовок поле для ввода страны.

lbl_country = tk.Label(master=frm_form, text=«Страна:»)

ent_country = tk.Entry(master=frm_form, width=50)

# Размещает виджеты на восьмой строке сетки.

lbl_country.grid(row=7, column=0, sticky=tk.E)

ent_country.grid(row=7, column=1)

# Создает новую рамку `frm_buttons` для размещения

# кнопок «Отправить» и «Очистить». Данная рамка заполняет

# все окно в горизонтальном направлении с

# отступами в 5 пикселей горизонтально и вертикально.

frm_buttons = tk.Frame()

frm_buttons.pack(fill=tk.X, ipadx=5, ipady=5)

# Создает кнопку «Отправить» и размещает ее

# справа от рамки `frm_buttons`.

btn_submit = tk.Button(master=frm_buttons, text=«Отправить»)

btn_submit.pack(side=tk.RIGHT, padx=10, ipadx=10)

# Создает кнопку «Очистить» и размещает ее

# справа от рамки `frm_buttons`.

btn_clear = tk.Button(master=frm_buttons, text=«Очистить»)

btn_clear.pack(side=tk.RIGHT, ipadx=10)

# Запуск приложения.

window.mainloop()

Это довольно неплохое решение. Оно немного длинное, зато понятное. При желании что-то изменить сразу ясно, где это можно сделать.

Есть и более короткий вариант решения. Учитывая, что у каждого текстового поля одинаковая ширина width, понадобится только указать текст для ярлыков:

Обновленный код с решением задачи #3

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

19

20

21

22

23

24

25

26

27

28

29

30

31

32

33

34

35

36

37

38

39

40

41

42

43

44

45

46

47

48

49

50

51

52

53

54

import tkinter as tk

# Создается новое окно с заголовком «Введите домашний адрес».

window = tk.Tk()

window.title(«Address Entry Form»)

# Создается новая рамка `frm_form` для ярлыков с текстом и

# Однострочных полей для ввода информации об адресе.

frm_form = tk.Frame(relief=tk.SUNKEN, borderwidth=3)

# Помещает рамку на окно приложения.

frm_form.pack()

# Список ярлыков полей.

labels = [

    «Имя:»,

    «Фамилия:»,

    «Адрес 1:»,

    «Адрес 2:»,

    «Город:»,

    «Регион:»,

    «Почтовый индекс:»,

    «Страна:»,

]

# Цикл для списка ярлыков полей.

for idx, text in enumerate(labels):

    # Создает ярлык с текстом из списка ярлыков.

    label = tk.Label(master=frm_form, text=text)

    # Создает текстовое поле которая соответствует ярлыку.

    entry = tk.Entry(master=frm_form, width=50)

    # Использует менеджер геометрии grid для размещения ярлыков и

    # текстовых полей в строку, чей индекс равен idx.

    label.grid(row=idx, column=0, sticky=«e»)

    entry.grid(row=idx, column=1)

# Создает новую рамку `frm_buttons` для размещения в ней

# кнопок «Отправить» и «Очистить». Данная рамка заполняет

# все окно в горизонтальном направлении с

# отступами в 5 пикселей горизонтально и вертикально.

frm_buttons = tk.Frame()

frm_buttons.pack(fill=tk.X, ipadx=5, ipady=5)

# Создает кнопку «Отправить» и размещает ее

# справа от рамки `frm_buttons`.

btn_submit = tk.Button(master=frm_buttons, text=«Submit»)

btn_submit.pack(side=tk.RIGHT, padx=10, ipadx=10)

# Создает кнопку «Очистить» и размещает ее

# справа от рамки `frm_buttons`.

btn_clear = tk.Button(master=frm_buttons, text=«Clear»)

btn_clear.pack(side=tk.RIGHT, ipadx=10)

# Запуск приложения.

window.mainloop()

В данном варианте список используется для хранения текста для каждого ярлыка формы. Они хранятся в том порядке, в котором поля формы должно появляться. После этого функция enumerate() возвращает индекс и строку каждого значения из списка labels.

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

Создание интерактивного приложения  в Tkinter

Теперь у вас есть довольно хорошее представление о том, как создать окно с Tkinter, мы уже можем добавлять некоторые виджеты и управлять макетом приложения. Это здорово, но приложения должны не просто хорошо выглядеть — им нужно что-то делать! В этом разделе вы узнаете, как создать интерактивное приложение, которая будет выполнять какие-то действия при возникновении определенных событий.

Обработчика событий в Tkinter

При создании приложения в Tkinter, для старта цикла событий требуется вызвать метод window.mainloop(). Во время цикла событий приложение проверяет, произошло ли какое либо событие. Если это так, то в ответ может быть выполнен какой-то метод или функция.

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

На заметку: Событие — это любое действие, которое происходит во время цикла событий. Оно может вызвать некоторое поведение в приложении. Например, при нажатии клавиши с клавиатуры или кнопки мышки.

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

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

Предположим, что есть список с названием events_list, который содержит объекты событий. Новый объект события автоматически добавляется в список events_list каждый раз, когда в программе происходит событие. Вам не нужно реализовывать механизм обновления. Это просто происходит автоматически в этом концептуальном примере. Используя бесконечный цикл, вы можете постоянно проверять, есть ли какие-либо объекты событий в events_list:

# Предположим, что список автоматически обновляется

events_list = []

# Запускаем цикл событий

while True:

    # Если events_list пуст, тогда никаких событий не происходит

    # и можно пропустить следующую итерацию цикла.

    if events_list == []:

        continue

    # Если выполнение доходит до данной точки, значит,

    # есть по крайней мере одно событие в events_list.

    event = events_list[0]

Прямо сейчас созданный цикл событий с самим событием event ничего не делает. Давайте изменим это. Предположим, приложение должно реагировать на нажатия клавиш. Вам нужно проверить, что событие event было создано пользователем при нажатии клавиши на клавиатуре, и, если это так, передать event в функцию обработчика событий для нажатия клавиш.

Предположим, что event имеет атрибут .type, установленный на строку "keypress", если событие является объектом события нажатия клавиши, а также атрибут .char, содержащий символ нажатой клавиши. Создадим новую функцию handle_keypress() и обновим код цикла событий:

events_list = []

# Создает обработчик событий

def handle_keypress(event):

    «»»Выводит символ, связанный с нажатой клавишей»»»

    print(event.char)

while True:

    if events_list == []:

        continue

    event = events_list[0]

    # Если событие event является объектом нажатия клавиши keypress

    if event.type == «keypress»:

        # Вызывает обработчик события нажатия клавиши

        handle_keypress(event)

При вызове метода window.mainloop() запускается похожий цикл. Данный метод отвечает за две части цикла:

  • Он поддерживает список событий, которые произошли в приложении;
  • Он запускает обработчик событий каждый раз, когда новое событие добавляется в список.

Обновим цикл событий, чтобы использовать window.mainloop() вместо вашего собственного цикла событий:

import tkinter as tk

# Создает объект окна.

window = tk.Tk()

# Создает обработчик событий.

def handle_keypress(event):

    «»»Выводит символ, связанный с нажатой клавишей»»»

    print(event.char)

# Запускает обработчик событий.

window.mainloop()

Метод .mainloop() отвечает за многое, но в вышеуказанном коде все-таки кое-что отсутствует. Как Tkinter узнает, когда использовать handle_keypress()? У виджетов в Tkinter есть метод под названием .bind(), предназначенный только для этой цели.

Метод .bind() для виджетов в Tkinter

Для вызова обработчика событий во время возникновения события, связанного с виджетом, используется метод .bind(). Обработчик событий напрямую связан с событием. Продолжим использовать предыдущий пример с нажатием клавиши и задействуем метод .bind(), чтобы связать handle_keypress() с событием нажатия клавиши:

import tkinter as tk

window = tk.Tk()

def handle_keypress(event):

    «»»Выводит символ, связанный с нажатой клавишей»»»

    print(event.char)

# Связывает событие нажатия клавиши с handle_keypress()

window.bind(«<Key>», handle_keypress)

window.mainloop()

Здесь обработчик событий handle_keypress() связывается с событием "<Key>", используя window.bind(). Если во время работы приложения нажата определенная клавиша, тогда программа выведет символ этой нажатой клавиши.

На заметку: Результат вышеуказанной программы не выводится в окне приложения Tkinter. Он выводится в stdout (терминал).

Если вы запускаете программу в IDLE, вывод будет в интерактивном окне. При запуске программы из терминала результат выведется в терминале.

Метод .bind() всегда принимает по крайней мере два аргумента:

  1. Событие, представленное строкой в форме "<event_name>", где event_name может быть любым событием;
  2. Обработчик событий, что является названием функции, вызываемой во время срабатывания события.

Обработчик события связан с виджетом, для которого вызывается метод  .bind(). Когда вызывается обработчик события, объект события передается в функцию обработчика события.

В приведенном выше примере обработчик событий привязан к самому окну, но вы можете привязать обработчик событий к любому виджету в приложении. Например, вы можете привязать обработчик событий к виджету кнопки Button, который будет выполнять некоторые действия при каждом нажатии на данную кнопку:

def handle_click(event):

    print(«Нажата кнопка!»)

button = tk.Button(text=«Кликни!»)

button.bind(«<Button-1>», handle_click)

В данном примере событие "<Button-1>" над виджетом кнопки связано с обработчиком handle_click. Событие  "<Button-1>", происходит когда при направлении курсора на виджет нажимается левая кнопка мыши.

Есть и другие события для кнопок мыши, включая "<Button-2>" для средней кнопки мыши (в современных мышках это нажатая колесо для скролла) и "<Button-3>" и правой кнопки мыши.

При помощи метода .bind() с виджетом можно связать любой обработчик событий. Однако есть более простой способ связать обработчики событий с нажатием кнопки при помощи использования атрибута command от виджета кнопки.

Атрибут command для виджета кнопки в Tkinter

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

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

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

import tkinter as tk

window = tk.Tk()

window.rowconfigure(0, minsize=50, weight=1)

window.columnconfigure([0, 1, 2], minsize=50, weight=1)

btn_decrease = tk.Button(master=window, text=«-«)

btn_decrease.grid(row=0, column=0, sticky=«nsew»)

lbl_value = tk.Label(master=window, text=«0»)

lbl_value.grid(row=0, column=1)

btn_increase = tk.Button(master=window, text=«+»)

btn_increase.grid(row=0, column=2, sticky=«nsew»)

window.mainloop()

Окно выглядит следующим образом:

tk counter

Макет приложения определен, можно вдохнуть в него жизнь, назначив кнопкам определенные команды. Начнем с левой кнопки. При нажатии на нее значение должно увеличиваться на 1. Для этого нам нужно знать две вещи:

  • Как получить текст из ярлыка?
  • Как обновить текст в ярлыке?

У виджетов ярлыка нет метода .get() в отличие от виджетов в возможностью ввода текста. Однако можно получить текста из ярлыка, через ключ text как при работе с обычным словарем:

label = Tk.Label(text=«Hello»)

# Получение текста из ярлыка

text = label[«text»]

# Установка нового текста для ярлыка

label[«text»] = «Good bye»

Теперь, когда мы знаем, как получить и установить текст ярлыка, напишем функцию increase(), которая увеличивает значение ярлыка lbl_value на 1:

def increase():

    value = int(lbl_value[«text»])

    lbl_value[«text»] = f«{value + 1}»

Функция increase() получает текст из ярлыка lbl_value и конвертирует его в целое число через int(). Затем его значение увеличивает на 1, присваивая атрибуту text из ярлыка это новое значение. В примере выше, мы использовали f-строки для форматирование строки.

Функция decrease() нужна для уменьшения значения value_label на 1:

def decrease():

    value = int(lbl_value[«text»])

    lbl_value[«text»] = f«{value — 1}»

Функции increase() и decrease() помещаются в код сразу после оператора import.

Для связи кнопки с функцией нужно назначить атрибуту command определенную функцию. Вы можете сделать это, когда создаете экземпляр этой кнопки. Например, чтобы назначить функцию increase() для кнопки increase_button, обновите код, в котором создается кнопка, следующим образом:

btn_increase = tk.Button(

    master=window,

    text=«+»,

    command=increase

)

Теперь присваиваем функцию decrease() для кнопки decrease_button:

btn_decrease = tk.Button(

    master=window,

    text=«-«,

    command=decrease

)

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

tk counter

Ниже представлен код данного приложения:

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

19

20

21

22

23

24

25

26

27

28

29

30

31

32

33

34

35

36

import tkinter as tk

def increase():

    value = int(lbl_value[«text»])

    lbl_value[«text»] = f«{value + 1}»

def decrease():

    value = int(lbl_value[«text»])

    lbl_value[«text»] = f«{value — 1}»

window = tk.Tk()

window.rowconfigure(0, minsize=50, weight=1)

window.columnconfigure([0, 1, 2], minsize=50, weight=1)

btn_decrease = tk.Button(

    master=window,

    text=«-«,

    command=decrease

)

btn_decrease.grid(row=0, column=0, sticky=«nsew»)

lbl_value = tk.Label(master=window, text=«0»)

lbl_value.grid(row=0, column=1)

btn_increase = tk.Button(

    master=window,

    text=«+»,

    command=increase

)

btn_increase.grid(row=0, column=2, sticky=«nsew»)

window.mainloop()

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

  • Использование виджетов для создания компонентов пользовательского интерфейса;
  • Использование менеджеров геометрии для управления макетом приложения;
  • Создание функций для взаимодействия с различными компонентами для принятия и трансформирования пользовательского ввода.

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

Задание #4 — Бросаем игровые кости в Tkinter

Игра в кости на Tkinter

Ниже дано еще одно задание для проверки понимания всего изученного.

Задание: Создать симулятор броска игральных костей.

Напишите программу, которая является симулятором результата броска шестигранной игральной кости. В приложении должна быть кнопка с текстом «Бросить». При нажатии на эту кнопку должно генерироваться и выводиться на экран случайное число от 1 до 6.

Подсказка: Случайное число можно сгенерировать с помощью randint() из модуля random.

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

Бросаем кости в Tkinter

Попробуйте сделать все сами. В конце можете ознакомиться с еще одним вариантом кода который мы приготовили. Помните, что у каждого разработчика свой стиль, и ваша программа можете выглядеть по-другому.

Решение задачи #4 — Бросаем кости

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

19

import random

import tkinter as tk

def roll():

    lbl_result[«text»] = str(random.randint(1, 6))

window = tk.Tk()

window.columnconfigure(0, minsize=150)

window.rowconfigure([0, 1], minsize=50)

btn_roll = tk.Button(text=«Бросить», command=roll)

lbl_result = tk.Label()

btn_roll.grid(row=0, column=0, sticky=«nsew»)

lbl_result.grid(row=1, column=0)

window.mainloop()

Когда разберетесь с заданием, переходите к следующей части.

Приложение по конвертированию температуры в Tkinter

В этом разделе вы создадите приложение для конвертирования температуры, которое позволит пользователю вводить температуру в градусах Фаренгейта и нажимать кнопку, чтобы преобразовать эту температуру в градусы Цельсия. Мы разберем код шаг за шагом. Полный код программы будет дан в конце раздела.

Перед написанием кода нужно задуматься о дизайне приложения. Нам потребуются следующие элементы:

  1. Виджет однострочного поля для ввода текста под названием ent_temperature для ввода значения температуры по Фаренгейту;
  2. Виджет ярлыка под названием lbl_result для отображения итогового значения температуры по Цельсию;
  3. Виджет кнопки под названием btn_convert, что читает значение текстового поля и конвертирует его из Фаренгейта в Цельсий, и после нажатия помещает результат в виде текста в ярлыке.

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

Ярлык помещается справа от текстового поля ent_temperature с символом Фаренгейта (℉), чтобы пользователь знал, что значением в текстовом поле ent_temperature нужно ввести в градусы Фаренгейта. Устанавливаем для ярлыка данный текст "N{DEGREE FAHRENHEIT}", это именованный Unicode символ в Python для отображения символа Фаренгейта.

Можно вставить кнопку btn_convert немного изящества, установив для нее значение "N{RIGHTWARDS BLACK ARROW}", которое отображает черную стрелку, указывающую вправо. Также нужно, чтобы у ярлыка с результатом lbl_result был символ Цельсия (℃), ярлык будет иметь следующее значение "N{DEGREE CELSIUS}" для указания того, что результат в градусах Цельсия. Вот как будет выглядеть итоговое окно:

app converter

Теперь, когда перечень виджетов и внешний вид финального результата известны, можно приступить к делу. Для начала импортирует tkinter и создаем новое окно.

import tkinter as tk

window = tk.Tk()

window.title(«Конвертер температуры»)

Метод window.title() устанавливает заголовок для существующего окна. При запуске приложения у окна будет заголовок «Конвертер температуры». Далее создаем виджет однострочного текстового поля ent_temperature с ярлыком lbl_temp, вставляем их в рамку под названием frm_entry:

frm_entry = tk.Frame(master=window)

ent_temperature = tk.Entry(master=frm_entry, width=10)

lbl_temp = tk.Label(master=frm_entry, text=«N{DEGREE FAHRENHEIT}»)

Однострочное текстовое поле ent_temperature является местом, куда пользователь вводит значение по Фаренгейту. Перемнная lbl_temp содержит ярлык для текстового поля ent_temperature с символом Фаренгейта. Рамка frm_entry является контейнером, что группирует текстовое поле ent_temperature и ярлык lbl_temp вместе.

Нам нужно, чтобы ярлык lbl_temp находился справа от тектсового поля ent_temperature. Их можно поместить в рамку frm_entry, используя менеджер геометрии .grid() с одной строкой и двумя столбцами:

ent_temperature.grid(row=0, column=0, sticky=«e»)

lbl_temp.grid(row=0, column=1, sticky=«w»)

Мы установили параметр sticky на "e" для текстового поля ent_temperature таким образом, чтобы она всегда будет с правой стороны ячейки сетки. Также установили sticky на "w" для ярлыка  lbl_temp для закрепления с левой стороны его ячейки сетки.

Теперь ярлык lbl_temp будет находиться сразу справа от текстового поля ent_temperature.

Теперь заставим кнопку btn_convert и ярлык с результатом lbl_result конвертировать введенную в текстовом поле ent_temperature температуру, после чего отобразить результат на экране:

btn_convert = tk.Button(

    master=window,

    text=«N{RIGHTWARDS BLACK ARROW}»

)

lbl_result = tk.Label(master=window, text=«N{DEGREE CELSIUS}»)

Как и в случае с рамкой frm_entry, виджеты кнопки btn_convert и ярлык с результатом lbl_result назначаются окну.

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

frm_entry.grid(row=0, column=0, padx=10)

btn_convert.grid(row=0, column=1, pady=10)

lbl_result.grid(row=0, column=2, padx=10)

Теперь запускаем приложение:

Выглядит неплохо. Однако кнопки пока ничего не делают. В верхней части скрипта, прямо под строкой import, добавим функцию под названием fahrenheit_to_celsius():

def fahrenheit_to_celsius():

    «»»

    Конвертирует значение Фаренгейта в Цельсий и вставляет

    результат в ярлык lbl_result.

    «»»

    fahrenheit = ent_temperature.get()

    celsius = (5/9) * (float(fahrenheit) 32)

    lbl_result[«text»] = f«{round(celsius, 2)} N{DEGREE CELSIUS}»

Данная функция читает значение из текстового поля ent_temperature, конвертирует его из Фаренгейтов в Цельсий, после чего отображает результат в ярлыке lbl_result.

Вернемся к строке создания кнопки btn_convert и назначим параметр command на функцию fahrenheit_to_celsius:

btn_convert = tk.Button(

    master=window,

    text=«N{RIGHTWARDS BLACK ARROW}»,

    command=fahrenheit_to_celsius  # <— Добавим его тут

)

Вот и все! Мы создали полностью функционирующий конвертер температуры длиной всего в 26 строк кода. Неплохо, правда?

Ниже дан полный код программы конвертера температуры:

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

19

20

21

22

23

24

25

26

27

28

29

30

31

32

33

34

35

36

37

38

39

40

41

42

43

44

import tkinter as tk

def fahrenheit_to_celsius():

    «»»

    Конвертирует значение из градусов по Фаренгейту в градусы

    по Цельсию и выводит результат в ярлык lbl_result.

    «»»

    fahrenheit = ent_temperature.get()

    celsius = (5/9) * (float(fahrenheit) 32)

    lbl_result[«text»] = f«{round(celsius, 2)} N{DEGREE CELSIUS}»

# Создание окна.

window = tk.Tk()

window.title(«Конвертер температуры»)

window.resizable(width=False, height=False)

# Создание рамки для ввода значения по Фаренгейту через виджет

# однострочного текстового поля вместе с ярлыком.

frm_entry = tk.Frame(master=window)

ent_temperature = tk.Entry(master=frm_entry, width=10)

lbl_temp = tk.Label(master=frm_entry, text=«N{DEGREE FAHRENHEIT}»)

# Макет для рамки ввода температуры и ярлыка с символом Фаренгейта

# использует менеджер геометрии .grid().

ent_temperature.grid(row=0, column=0, sticky=«e»)

lbl_temp.grid(row=0, column=1, sticky=«w»)

# Создание кнопки-конвертера и ярлыка для вывода результата.

btn_convert = tk.Button(

    master=window,

    text=«N{RIGHTWARDS BLACK ARROW}»,

    command=fahrenheit_to_celsius

)

lbl_result = tk.Label(master=window, text=«N{DEGREE CELSIUS}»)

# Настройка макета через менеджер геометрии .grid().

frm_entry.grid(row=0, column=0, padx=10)

btn_convert.grid(row=0, column=1, pady=10)

lbl_result.grid(row=0, column=2, padx=10)

# Запуск приложения.

window.mainloop()

В следующем разделе рассмотрим процесс создания текстового редактора для файлов.

Создание текстового редактора на Tkinter

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

  • Виджет кнопки под названием btn_open для открытия файла, которого нужно отредактировать;
  • Виджет кнопки под названием btn_save для сохранения изменений;
  • Виджет для ввода большого текста под названием txt_edit для создания и редактирования текстового файла.

Три виджета будут расположены таким образом, чтобы две кнопки находились с левой стороны окна, а текстовое поле — с правой стороны.

Все окно должно быть высотой минимум в 800 пикселей, и ширина текстового поля txt_edit также должна быть минимум 800 пикселей. Весь макет должен быть адаптивным, так что если размер окна изменяется, то также изменяется размер текстового поля txt_edit. Однако ширина рамки с кнопками не должна меняться.

Вот примерный набросок того, как будет выглядеть окно:

Python Text Editor

Добиться желаемого макета можно через менеджер геометрии .grid(). В макете одна строка и два столбца:

  1. Узкий столбец слева от кнопок;
  2. Широкий столбец справа от текстового поля.

Чтобы установить минимальные размеры для окна и текстового поля txt_edit, вы можете установить параметры minsize используя методы окна .rowconfigure() и .columnconfigure() указав значение в 800 пикселей. Для обработки изменения размера окна, можно установить параметр weight для выше перечисленных методов на 1.

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

Теперь, когда у нас есть план, можно приступить к написанию приложения. Первый шаг — создать все нужные виджеты:

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

19

20

import tkinter as tk

window = tk.Tk()

window.title(«Простой текстовый редактор»)

window.rowconfigure(0, minsize=800, weight=1)

window.columnconfigure(1, minsize=800, weight=1)

txt_edit = tk.Text(window)

fr_buttons = tk.Frame(window)

btn_open = tk.Button(fr_buttons, text=«Открыть»)

btn_save = tk.Button(fr_buttons, text=«Сохранить как…»)

btn_open.grid(row=0, column=0, sticky=«ew», padx=5, pady=5)

btn_save.grid(row=1, column=0, sticky=«ew», padx=5)

fr_buttons.grid(row=0, column=0, sticky=«ns»)

txt_edit.grid(row=0, column=1, sticky=«nsew»)

window.mainloop()

Разберем код поэтапно:

  • Строка 1 импортирует библиотеку tkinter;
  • Строки 3 и 4 создают новое окно с заголовком «Простой текстовый редактор»;
  • Строки 6 и 7 устанавливают конфигурацию строк и столбцов;
  • Строки 9 и 12 создают четыре виджета — текстовый бокс, рамку, кнопка для открытия и кнопка для сохранения файла.

Подробнее рассмотрим строку 6. Параметр minsize для метода .rowconfigure() ставится на 800 пикселей, weight имеет значение 1:

window.rowconfigure(0, minsize=800, weight=1)

Первый аргумент — 0, устанавливает высоту первой строки на 800 пикселей, гарантируя, что высота строки увеличивается пропорционально высоте окна. В макете приложения только одна строка, поэтому эти параметры применяются ко всему окну.

Давайте также подробнее рассмотрим строку 7. Здесь используется метод .columnconfigure(), чтобы установить атрибуты width и weight столбца с индексами от 1 до 800 и 1 соответственно:

window.columnconfigure(1, minsize=800, weight=1)

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

Теперь можно работать над макетом приложения. Сначала назначим две кнопки в рамку fr_buttons с помощью менеджера геометрии .grid():

btn_open.grid(row=0, column=0, sticky=«ew», padx=5, pady=5)

btn_save.grid(row=1, column=0, sticky=«ew», padx=5)

Эти две строки кода создают сетку с двумя строками и одним столбцом в рамке fr_buttons, поскольку для кнопки btn_open и кнопки btn_save атрибут master указывает на рамку fr_buttons. Кнопка btn_open помещается в первый ряд, а кнопка btn_save — во второй ряд, так что кнопка btn_open отображается над кнопкой btn_save в макете, как и было запланировано в изначальном макете.

Для кнопок btn_open и btn_save атрибуты sticky установлены на "ew", что заставляет кнопки расширяться горизонтально в обоих направлениях и заполнять всю рамку. Это гарантирует, что обе кнопки имеют одинаковый размер.

Указывается 5 пикселей отступа вокруг каждой кнопки, устанавливая параметры padx и pady на 5. Только у кнопки btn_open есть вертикальный отступ. Поскольку он находится сверху, вертикальный отступ немного смещает кнопку вниз от верхней части окна и обеспечивает небольшой зазор между ним и кнопкой btn_save.

Теперь, когда рамка fr_buttons разложена и готова к работе, вы можете настроить макет сетки для остальной части окна:

fr_buttons.grid(row=0, column=0, sticky=«ns»)

txt_edit.grid(row=0, column=1, sticky=«nsew»)

Эти две строки кода создают сетку с одной строкой и двумя столбцами для окна. Вы помещаете рамку fr_buttons в первый столбец и текстовое поле txt_edit во второй столбец, так что рамка с кнопками  fr_buttons появляется слева от тектсового поля txt_edit в макете окна приложения.

Параметр sticky для рамки с кнопками fr_buttons имеет значение "ns", что заставляет всю рамку расширяться по вертикали и заполнять всю высоту его столбца. Текстовое поле txt_edit заполняет всю ячейку сетки, потому что вы установили для ее параметра sticky значение "nsew", что заставляет его расширяться во всех направлениях.

Теперь, когда макет приложения готов, добавьте метод  window.mainloop() в конец программы, сохраните и запустите скрипт. Появится следующее окно:

Tkinter текстовой редактор

Выглядит неплохо! Но приложение пока ничего не делает, поэтому нужно создать команды для кнопок. Кнопка btn_open должена показать диалоговое окно выбора файла и позволить пользователю выбрать файл с компьютера. Затем он должен открыть файл и вставить его содержимое в текстом поле txt_edit. Для этого используем функцию open_file():

def open_file():

    «»»Открывает файл для редактирования»»»

    filepath = askopenfilename(

        filetypes=[(«Text Files», «*.txt»), («All Files», «*.*»)]

    )

    if not filepath:

        return

    txt_edit.delete(«1.0», tk.END)

    with open(filepath, «r») as input_file:

        text = input_file.read()

        txt_edit.insert(tk.END, text)

    window.title(f«Simple Text Editor — {filepath}»)

Разберем данную функцию поэтапно:

  • Строки с 3 по 5 используют диалоговое окно askopenfilename из модуля tkinter.filedialog, чтобы отобразить диалоговое окно открытия файла и сохранить выбранный путь к файлу в переменную filepath;
  • Строки 6 и 7 проверяют, закрывает ли пользователь диалоговое окно или нажимает кнопку отмены. Если это так, то filepath будет иметь значение None, и функция вернется без выполнения какого-либо кода для чтения содержимого файла и вставки текста в текстовом поле txt_edit;
  • Строка 8 очищает текущее содержимое из текстового поля txt_edit, используя метод .delete();
  • Строки 9 и 10 открывают выбранный файл и читают через .read() его содержимое перед сохранением текста в виде строки;
  • Строка 11 вставляем текст в текстовом поле txt_edit, используя метод .insert();
  • Строка 12 устанавливает заголовок окна так, чтобы он содержал путь к открытому файлу.

Теперь вы можете обновить программу так, чтобы кнопка btn_open вызывала функцию open_file() при каждом нажатии. Есть несколько вещей, которые нужно сделать, чтобы обновить программу.

Сначала импортируйте askopenfilename из модуля  tkinter.filedialog, добавив следующий импорт в начало вашей программы:

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

19

20

21

22

import tkinter as tk

from tkinter.filedialog import askopenfilename

window = tk.Tk()

window.title(«Простой текстовый редактор»)

window.rowconfigure(0, minsize=800, weight=1)

window.columnconfigure(1, minsize=800, weight=1)

txt_edit = tk.Text(window)

fr_buttons = tk.Frame(window)

btn_open = tk.Button(fr_buttons, text=«Открыть»)

btn_save = tk.Button(fr_buttons, text=«Сохранить как…»)

btn_open.grid(row=0, column=0, sticky=«ew», padx=5, pady=5)

btn_save.grid(row=1, column=0, sticky=«ew», padx=5)

fr_buttons.grid(row=0, column=0, sticky=«ns»)

txt_edit.grid(row=0, column=1, sticky=«nsew»)

window.mainloop()

Затем добавляется тело функции open_file() прямо под оператором импорта:

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

19

20

21

22

23

24

25

26

27

28

29

30

31

32

33

34

35

36

import tkinter as tk

from tkinter.filedialog import askopenfilename

def open_file():

    «»»Открываем файл для редактирования»»»

    filepath = askopenfilename(

        filetypes=[(«Текстовые файлы», «*.txt»), («Все файлы», «*.*»)]

    )

    if not filepath:

        return

    txt_edit.delete(«1.0», tk.END)

    with open(filepath, «r») as input_file:

        text = input_file.read()

        txt_edit.insert(tk.END, text)

    window.title(f«Простой текстовый редактор — {filepath}»)

window = tk.Tk()

window.title(«Простой текстовый редактор»)

window.rowconfigure(0, minsize=800, weight=1)

window.columnconfigure(1, minsize=800, weight=1)

txt_edit = tk.Text(window)

fr_buttons = tk.Frame(window)

btn_open = tk.Button(fr_buttons, text=«Открыть»)

btn_save = tk.Button(fr_buttons, text=«Сохранить как…»)

btn_open.grid(row=0, column=0, sticky=«ew», padx=5, pady=5)

btn_save.grid(row=1, column=0, sticky=«ew», padx=5)

fr_buttons.grid(row=0, column=0, sticky=«ns»)

txt_edit.grid(row=0, column=1, sticky=«nsew»)

window.mainloop()

Теперь указываем атрибуту command от кнопки btn_open на функцию  open_file:

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

19

20

21

22

23

24

25

26

27

28

29

30

31

32

33

34

35

36

import tkinter as tk

from tkinter.filedialog import askopenfilename

def open_file():

    «»»Открываем файл для редактирования»»»

    filepath = askopenfilename(

        filetypes=[(«Текстовые файлы», «*.txt»), («Все файлы», «*.*»)]

    )

    if not filepath:

        return

    txt_edit.delete(«1.0», tk.END)

    with open(filepath, «r») as input_file:

        text = input_file.read()

        txt_edit.insert(tk.END, text)

    window.title(f«Простой текстовый редактор — {filepath}»)

window = tk.Tk()

window.title(«Простой текстовый редактор»)

window.rowconfigure(0, minsize=800, weight=1)

window.columnconfigure(1, minsize=800, weight=1)

txt_edit = tk.Text(window)

fr_buttons = tk.Frame(window)

btn_open = tk.Button(fr_buttons, text=«Открыть», command=open_file)

btn_save = tk.Button(fr_buttons, text=«Сохранить как…»)

btn_open.grid(row=0, column=0, sticky=«ew», padx=5, pady=5)

btn_save.grid(row=1, column=0, sticky=«ew», padx=5)

fr_buttons.grid(row=0, column=0, sticky=«ns»)

txt_edit.grid(row=0, column=1, sticky=«nsew»)

window.mainloop()

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

Теперь, наша кнопка btn_open работает и успешно открывает текстовые файлы, можно уже заняться функцией для кнопки btn_save. Для этого необходимо открыть диалоговое окно сохранения файла, чтобы пользователь мог выбрать, куда он хотел бы сохранить файл.

Для этого вы будете использовать диалог asksaveasfilename из модуля tkinter.filedialog. Эта функция также должна извлечь все содержимое из текстового поля txt_edit и записать его в файл в выбранном месте. Вот функция, которая делает именно это:

def save_file():

    «»»Сохраняем текущий файл как новый файл.»»»

    filepath = asksaveasfilename(

        defaultextension=«txt»,

        filetypes=[(«Текстовые файлы», «*.txt»), («Все файлы», «*.*»)],

    )

    if not filepath:

        return

    with open(filepath, «w») as output_file:

        text = txt_edit.get(«1.0», tk.END)

        output_file.write(text)

    window.title(f«Простой текстовый редактор — {filepath}»)

Разберем код:

  • Строки с 3 по 6 используют диалоговое окно asksaveasfilename, чтобы выбрать желаемое место сохранения файла. Выбранный путь к файлу сохраняется в переменную filepath;
  • Строки 7 и 8 проверяют, закрывает ли пользователь диалоговое окно или нажимает кнопку отмены. Если это так, то переменная filepath будет иметь значение None, и функция завершиться без выполнения какого-либо кода для сохранения текста в файле;
  • Строка 9 создает новый файл по выбранному пути;
  • Строка 10 извлекает текст из текстового поля txt_edit с помощью метода .get() и присваивает его переменной text;
  • Строка 11 записывает содержимое из переменной text в выбранном файле;
  • Строка 12 обновляет заголовок окна приложения, чтобы новый путь к файлу отображался в заголовке окна.

Теперь вы можете обновить программу, чтобы кнопка btn_save вызывала функцию save_file() при нажатии. Опять же, есть несколько вещей, которые вам нужно сделать, чтобы обновить программу.

Сначала импортируйте asksaveasfilename из модуля tkinter.filedialog, обновив импорт в верхней части вашего скрипта, например так:

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

19

20

21

22

23

24

25

26

27

28

29

30

31

32

33

34

35

import tkinter as tk

from tkinter.filedialog import askopenfilename, asksaveasfilename

def open_file():

    «»»Открываем файл для редактирования»»»

    filepath = askopenfilename(

        filetypes=[(«Текстовые файлы», «*.txt»), («Все файлы», «*.*»)]

    )

    if not filepath:

        return

    txt_edit.delete(«1.0», tk.END)

    with open(filepath, «r») as input_file:

        text = input_file.read()

        txt_edit.insert(tk.END, text)

    window.title(f«Простой текстовый редактор — {filepath}»)

window = tk.Tk()

window.title(«Простой текстовый редактор»)

window.rowconfigure(0, minsize=800, weight=1)

window.columnconfigure(1, minsize=800, weight=1)

txt_edit = tk.Text(window)

fr_buttons = tk.Frame(window, relief=tk.RAISED, bd=2)

btn_open = tk.Button(fr_buttons, text=«Открыть», command=open_file)

btn_save = tk.Button(fr_buttons, text=«Сохранить как…»)

btn_open.grid(row=0, column=0, sticky=«ew», padx=5, pady=5)

btn_save.grid(row=1, column=0, sticky=«ew», padx=5)

fr_buttons.grid(row=0, column=0, sticky=«ns»)

txt_edit.grid(row=0, column=1, sticky=«nsew»)

window.mainloop()

Затем добавляем функцию save_file() прямо под функцию open_file():

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

19

20

21

22

23

24

25

26

27

28

29

30

31

32

33

34

35

36

37

38

39

40

41

42

43

44

45

46

47

48

import tkinter as tk

from tkinter.filedialog import askopenfilename, asksaveasfilename

def open_file():

    «»»Открываем файл для редактирования»»»

    filepath = askopenfilename(

        filetypes=[(«Текстовые файлы», «*.txt»), («Все файлы», «*.*»)]

    )

    if not filepath:

        return

    txt_edit.delete(«1.0», tk.END)

    with open(filepath, «r») as input_file:

        text = input_file.read()

        txt_edit.insert(tk.END, text)

    window.title(f«Простой текстовый редактор — {filepath}»)

def save_file():

    «»»Сохраняем текущий файл как новый файл.»»»

    filepath = asksaveasfilename(

        defaultextension=«txt»,

        filetypes=[(«Текстовые файлы», «*.txt»), («Все файлы», «*.*»)],

    )

    if not filepath:

        return

    with open(filepath, «w») as output_file:

        text = txt_edit.get(«1.0», tk.END)

        output_file.write(text)

    window.title(f«Простой текстовый редактор — {filepath}»)

window = tk.Tk()

window.title(«Простой текстовый редактор»)

window.rowconfigure(0, minsize=800, weight=1)

window.columnconfigure(1, minsize=800, weight=1)

txt_edit = tk.Text(window)

fr_buttons = tk.Frame(window, relief=tk.RAISED, bd=2)

btn_open = tk.Button(fr_buttons, text=«Открыть», command=open_file)

btn_save = tk.Button(fr_buttons, text=«Сохранить как…»)

btn_open.grid(row=0, column=0, sticky=«ew», padx=5, pady=5)

btn_save.grid(row=1, column=0, sticky=«ew», padx=5)

fr_buttons.grid(row=0, column=0, sticky=«ns»)

txt_edit.grid(row=0, column=1, sticky=«nsew»)

window.mainloop()

Наконец, указываем атрибуту command от кнопки btn_save на функцию save_file:

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

19

20

21

22

23

24

25

26

27

28

29

30

31

32

33

34

35

36

37

38

39

40

41

42

43

44

45

46

47

48

import tkinter as tk

from tkinter.filedialog import askopenfilename, asksaveasfilename

def open_file():

    «»»Открываем файл для редактирования»»»

    filepath = askopenfilename(

        filetypes=[(«Текстовые файлы», «*.txt»), («Все файлы», «*.*»)]

    )

    if not filepath:

        return

    txt_edit.delete(«1.0», tk.END)

    with open(filepath, «r») as input_file:

        text = input_file.read()

        txt_edit.insert(tk.END, text)

    window.title(f«Простой текстовый редактор — {filepath}»)

def save_file():

    «»»Сохраняем текущий файл как новый файл.»»»

    filepath = asksaveasfilename(

        defaultextension=«txt»,

        filetypes=[(«Текстовые файлы», «*.txt»), («Все файлы», «*.*»)],

    )

    if not filepath:

        return

    with open(filepath, «w») as output_file:

        text = txt_edit.get(«1.0», tk.END)

        output_file.write(text)

    window.title(f«Простой текстовый редактор — {filepath}»)

window = tk.Tk()

window.title(«Простой текстовый редактор»)

window.rowconfigure(0, minsize=800, weight=1)

window.columnconfigure(1, minsize=800, weight=1)

txt_edit = tk.Text(window)

fr_buttons = tk.Frame(window, relief=tk.RAISED, bd=2)

btn_open = tk.Button(fr_buttons, text=«Открыть», command=open_file)

btn_save = tk.Button(fr_buttons, text=«Сохранить как…», command=save_file)

btn_open.grid(row=0, column=0, sticky=«ew», padx=5, pady=5)

btn_save.grid(row=1, column=0, sticky=«ew», padx=5)

fr_buttons.grid(row=0, column=0, sticky=«ns»)

txt_edit.grid(row=0, column=1, sticky=«nsew»)

window.mainloop()

Сохраните файл и запустите его. Теперь у вас есть небольшой, но полностью функциональный текстовый редактор написанный на Python используя библиотеку Tkinter.

Tkinter текстовой редактор

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

Заключение

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

В этом руководстве вы узнали несколько важных концепций от Tkinter:

  • Как работать с виджетами;
  • Как управлять макетом приложения с помощью менеджеров геометрии;
  • Как сделать ваши приложения интерактивными;
  • Как использовать пять основных виджетов из Tkinter (Label, Button, Entry, Text и Frame).

Теперь, когда вы освоили основы программирования на Python используя графический интерфейс при помощью Tkinter, следующим шагом будет создание ваших собственных приложений. Что это будет? Поделитесь идеями для своих проектов в комментариях ниже.

Дополнительные материалы для изучения Tkinter

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

Вот некоторые официальные ресурсы, которые можно просмотреть:

  • Официальное руководство Python Tkinter, в котором подробно описан данный модуль. Текст предназначен для более продвинутых пользователей, новичкам будет сложновато;
  • Справочник по Tkinter 8.5: GUI для Python — это обширный справочник, охватывающий большинство модулей от Tkinter. Он исчерпывающий, но написан кратко и без комментариев и примеров.
  • Справочник по Tk — это полное руководство по командам в библиотеке Tk. Он написан для языка Tcl, но отвечает на множество вопросов о том, почему все работает так, как они работают в Tkinter. В официальной документации по Python есть раздел, посвященный отображению базового Tk в Tkinter, который необходим при чтении документации по командам Tk.

Дополнительные виджеты

В этом руководстве вы узнали о виджетах Label, Button, Entry, Text и Frame . В Tkinter есть несколько других виджетов, каждый из которых необходим для создания реальных приложений. Вот несколько ресурсов, чтобы продолжить изучение виджетов:

  • TkDocs Tkinter Tutorial — это достаточно обширное руководство для Tk, базовой библиотеки кода, используемой Tkinter. Примеры представлены на ткаих языка программирования как Python, Ruby, Perl и Tcl. Вы можете найти несколько примеров виджетов, помимо описанных в данной статье;
  • Базовые виджеты включают те же виджеты, что и в этом руководстве, а также некоторые другие;
  • Раздел Больше виджетов охватывает несколько дополнительных виджетов.

В официальной документации Python есть три раздела, охватывающих дополнительные виджеты:

  • Тематические виджеты ttk набор тематических виджетов Tk;
  • Расширение виджетов для Tk охватывает виджеты в наборе расширений интерфейса Tk;
  • Виджет прокрутки текста расширяет возможности виджета Text в сочетании с вертикальной полосой прокрутки.

Поделиться приложением на Tkinter

Создав приложение с помощью Tkinter, вы, вероятно, захотите распространить его среди своих коллег и друзей. Вот несколько уроков, которые помогут вам в этом процессе:

  • Использование PyInstaller для компиляции приложений
  • 4 попытки упаковки Python как исполняемого файла
  • Создание автономных приложений Python с помощью PyOxidizer 

Другие GUI фреймворки 

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

  • Полный курс уроков по wxPython
  • Python и PyQt5: создание калькулятора на PyQt5
  • Создание мобильного приложения с Kivy Python Framework

Являюсь администратором нескольких порталов по обучению языков программирования Python, Golang и Kotlin. В составе небольшой команды единомышленников, мы занимаемся популяризацией языков программирования на русскоязычную аудиторию. Большая часть статей была адаптирована нами на русский язык и распространяется бесплатно.

E-mail: vasile.buldumac@ati.utm.md

Образование
Universitatea Tehnică a Moldovei (utm.md)

  • 2014 — 2018 Технический Университет Молдовы, ИТ-Инженер. Тема дипломной работы «Автоматизация покупки и продажи криптовалюты используя технический анализ»
  • 2018 — 2020 Технический Университет Молдовы, Магистр, Магистерская диссертация «Идентификация человека в киберпространстве по фотографии лица»

Понравилась статья? Поделить с друзьями:
  • Как изменить вид input type file
  • Как изменить вес документа pdf
  • Как изменить вес джипег файла
  • Как изменить вес анимации
  • Как изменить вес jpeg файла