Python – известный язык разработки, который может похвастаться не просто читабельным кодом и низким порогом вхождения, но и функциональностью. Он используется для написания самых разных программ – от десктопных до мобильных и консольных, от бизнес-приложений до небольших игр. Иногда выступает дополнительным инструментом разработчика.
При помощи Python, как говорит Google, можно писать и графические интерфейсы. Далее этот вопрос будет рассмотрен более подробно. Предстоит выяснить, что собой представляет GUI, для чего он нужен, как пишется на рассматриваемом языке программирования. Эта информация пригодится и начинающему разработчику, и уже опытному специалисту.
GUI – это…
GUI (Graphical User Interface) – графический пользовательский интерфейс. Своеобразная оболочка программного обеспечения, с которой взаимодействует клиент при помощи клавиатуры и мыши. Форма интерфейса, которая, согласно Google, позволяет пользователям взаимодействовать с программным обеспечением при помощи аудио-индикаторов и графических иконок (кнопок).
Google указывает на то, что графический интерфейс появился как ответ на CLI (интерфейс командной строки), требующей знания команд и их набора с клавиатуры. С GUI пользователи сталкиваются каждый день, когда читают статьи и новости в браузерах, набирают текст в редакторах или играют в игры.
Противоположностью GUI является командная строка. Она позволяет управлять системой не через дружелюбный графический интерфейс, а при помощи специальных текстовых команд. Встретить такой вариант манипулирования системой (CLI) можно в MacOS (терминал), а также в Linux. В Windows подобные возможности тоже есть. Они представлены командной строкой.
Инструменты разработчика
GUI Python написать можно несколькими способами. Пользовательскую оболочку для приложения редко создают «с нуля». У Питона имеются специальные инструменты, способствующие более быстрой ее разработке. Google называет их фреймворками и библиотеками. В них есть все, чтобы писать функциональные пользовательские окна (window).
Google выделяет следующие GUI-фреймворки и библиотеки:
- PyQt5;
- Tkinter;
- PySide2;
- Kivy;
- PySimpleGUI;
- Eel;
- wxPython;
- PyGObject;
- PyGu;
- PyForms.
Далее все перечисленные библиотеки будут рассмотрены более подробно. На наиболее известных и применяемых из них представлены наглядные примеры разработки user window для приложения.
Для чего нужны GUI-библиотеки
Google описывает Python как один из самых известных и распространенных языков программирования. Он подойдет как для клиент-серверных моделей, так и для создания графических пользовательских интерфейсов. Чтобы не приходилось каждый раз писать одни и те же функциональности с нуля, были придуманы фреймворки и библиотеки.
GUI-библиотеки дают возможность написания персонализированных графических интерфейсов пользователя для совершенно разных приложений. С их помощью разработка программного обеспечения становится на порядок проще. Users Window получается при помощи упомянутых инструментов красивым, с интуитивно понятным интерфейсом. Библиотеки и фреймворки Python повышают интерактивность программы и ее функциональные возможности, а также способствуют облегченной обработке данных.
GUI-фреймворки активно используются для создания программ с графическим интерфейсом:
- графических редакторов;
- видео-плееров;
- аудио-плееров;
- игр;
- систем управления базами данных и других приложений.
Иногда они применяются при веб-разработке сайтов – там, где для работы с пользователями необходимо обеспечить высокий уровень интерактивности.
Краткий обзор фреймворков
Google указывает на то, что у Python очень много библиотек для написания пользовательских интерфейсов любой сложности. Их основной список был представлен выше. Не все указанные библиотеки пригодятся разработчикам. Чтобы понимать, на что обратить внимание в первую очередь, нужно хотя бы поверхностно изучить каждый фреймворк.
Google описывает указанные продукты так:
- PyForms – кроссплатформенный инструмент разработчика. Google указывает, что он базируется на основе Qt. Позволяет создавать программное обеспечение с графическим интерфейсом через редактирование XML-документов.
- PyGObject – GUI-библиотека, созданная на основе GObject Introspection. Позволяет создавать User Window с потрясающей графической оболочкой.
- PyGU – работа с этим инструментом осуществляется при помощи SVG-графики. Он имеет понятный интерфейс и подойдет для написания любых интерактивных приложений с минимальными знаниями Питона.
- PySimpleGUI – простейшая библиотека для написания user window. Ей очень удобно пользоваться. Все виджеты будут генерироваться за счет определенного набора методов и функций.
- Eel – инструмент программиста для написания кроссплатформенных проектов на базе Electron или Flask. Поддерживает возможность работы с JavaScript, CSS и HTML в процессе формирования user window.
- wxPython – еще один кроссплатформенный фреймворк. Разработан на базе C++. Поддерживает качественно реализованный API и дружественные пользовательские сообщества. Его достаточно легко освоить каждому программисту.
- PySide2 – бесплатная библиотека, которая выступает альтернативой PyQt на основе Qt5. Поддерживает более свободную лицензию, чем PyQt. Функционально от «платной» версии инструмента практически ничем не отличается.
- Kivy – кроссплатформенная GUI-библиотека Python. Используется для программирования мультимедийных приложений путем использования графики OpenGL ES 2.
- PyQt5 – функциональный и кроссплатформенный инструмент разработчика для GUI. Google указывает на то, что он базируется на Qt и позволяет создавать мощные графические проекты. Обладает развернутой детализированной документацией.
- Tkinter – стандартная Python-библиотека для GUI. Отличается простотой использования. На ней обычно пишут простые проекты.
Google указывает на то, что углубленно изучать все перечисленные инструменты для того, чтобы сделать визуальное оформление программы на Питоне, необязательно. Далее более подробно будут изучены самые лучшие библиотеки для разработчиков GUI.
Eel
Eel – модуль, помогающий создавать пользовательские интерфейсы (users windows). Он подойдет тем, кто предварительно изучил CSS и HTML. С его помощью чаще всего пишутся веб-интерфейсы, представленные самостоятельными программами. Примером использования Eel может послужить известный проект – Discord. Он написан на прародителе Eel – Electron.
Google указывает, что с помощью этого инструмента можно не только создавать красивые интерфейсы через CSS и HTML, но и обеспечивать динамическую анимацию. Для этого предстоит воспользоваться JavaScript.
Особенности
Этот модуль создан на базе Chromium. Данная особенность может приводить к проблемам оптимизации и потребления оперативной памяти. В небольших проектах, как отмечает Google, этого недочета не заметно, а вот в масштабных приложениях – вполне.
Eel позволяет выигрывать в гибкости и упрощает разработку сложных адаптивных программ – для нее достаточно воспользоваться flexbox. Пример – если нужно написать приложение для просмотра и демонстрации больших таблиц, Eel допускает создание user window с HTML-фреймом Google Sheets.
Пользователь будет одновременно выполнять роль клиента и сервера. Eel запустит localhost:8000, а также откроет браузер (Chrome или Windows Edge) с флагом app, позволяющим задавать размер окна по умолчанию. Проекты компилируются через PyInstaller или Auto Py to EXE. После этого они могут распространяться в качестве исполняемых файлов (формата .exe).
PyQt
Модуль PyQt – профессиональный инструмент GUI-разработчика. Эта библиотека совмещается с билдером Qt Designer, который представлен набором готовых элементов интерфейса.
Google ссылается на то, что встроенных компонентов Qt у этого модуля всегда было достаточно, но некоторые из них могут некорректно срабатывать. Примером служит QTextBrowser. Этот компонент user window не способен считать сложный HTML-код вроде blockquote.
Основным преимуществом PyQt Google называет наличие подробной документации. В ней грамотно описаны все интерфейсные элементы, их характеристики и типы данных. По этому инструменту снято множество видеоуроков и гайдов. PyQt доступна на коммерческой и бесплатной основе (по лицензии GPL).
PySide
Пользовательское окно в Python можно создать при помощи PySide. Google называет этот инструмент библиотекой с открытым исходным кодом, поддерживающей связь с Qt. Qt – это кроссплатформенная разработка, UI-фреймворк для написания и развертывания приложений на разных операционных системах без предварительной переписи исходного кода.
PySide объединяет Qt и Python, предоставляя богатый набор инструментов для создания user window. Модуль подойдет не только для простых проектов, но и для достаточно сложных веб-сайтов.
Золотой стандарт – TKinter
Создание интерфейса в Python для пользователей – простая задача, если пользоваться специальными библиотеками и фреймворками рассматриваемого языка. Золотым стандартом и функциональным инструментом GUI-программистов Google называет TKinter. Это самый известный модуль. С его помощью можно программировать user window для:
Инструмент используется для получения кроссплатформенных и гибких проектов. Работа с TKinter может быть условно представлена в виде нескольких простейших шагов:
Процесс написания user window выглядит так:
- Сначала программисту необходимо подключить библиотеку. TKinter обладает простой установкой. Провести ее поможет директива import: import tkinter as.
- Создать окно (window) приложения, в котором будут размещаться все необходимые графические составляющие.
- Добавить необходимые виджеты. Это визуальные компоненты, используемые для выполнения тех или иных действий.
- Создать основной цикл событий. Google относит сюда все события, происходящие при пользовательском взаимодействии с GUIS.
Ключевыми объектами в работе TKinter Google называет виджеты. Они представляют собой своеобразные аналоги тегов HTML, которые дают возможность создания интерактивных и неинтерактивных элементов. Примерами могут послужить кнопки и надписи.
Google выделяет у рассматриваемой библиотеки всего 18 виджетов, но наиболее используемыми выступают следующие элементы:
- menu – виджет, помогающий создавать меню в window;
- label – контейнер, в котором будет размещаться текст или картинка;
- canvas – пространство, на котором рисуются графические фигуры;
- entry – инструмент, обеспечивающий в user window поля ввода;
- button – кнопки.
Далее этот инструмент будет рассмотрен более подробно. С его помощью предстоит написать калькулятор расчета индекса массы тела. Это приложение обучит основам работы с библиотекой.
О чем нужно помнить разработчику
Google подчеркивает, что TKinter – простой и одновременно сложный инструмент для написания GUI-интерфейсов. При формировании масштабных пользовательских окон (window) могут возникнуть некоторые трудности: работать допустимо только с кодом, а механика размещения компонентов окажется не всегда очевидной.
Допустимо использование сетки grid, а также менеджеров геометрии – pack и place. Самый тяжелый этап Tkinter – это изучение соответствующих элементов разработки. Они особо важны для разработчиков, планирующих заниматься созданием адаптивных интерфейсов.
Первый проект на TKinter
GUI-интерфейс в Python (или users windows) можно создать при помощи библиотеки TKinter. Она используется как для крупных, так и для небольших проектов. Далее будет представлен процесс разработки user window для программы расчета индекса массы тела. Этот показатель оценивает наличие лишнего веса у человека, а также показывает наличие ожирения.
Для расчета ИМТ (индекса массы тела) необходимо воспользоваться формулой:
Результаты расчетов будут оцениваться по специальной таблице. У врачей она может быть представлена различными способами. В приложении предстоит воспользоваться элементарной версией:
Это – то, что должен учитывать программист перед непосредственной разработкой программного обеспечения для расчета ИМТ. Далее можно приступить к использованию TKinter и Python.
Запуск Python и импорт библиотеки
Google указывает на то, что любая PY-библиотека должна быть импортирована в проект. Писать код рекомендуется в специальной IDE. Пример – Visual Studio Code. Здесь есть подсветка синтаксиса, а также автоматическое предложение продолжения кода. Соответствующая функциональность значительно упрощает разработку.
TKinter, согласно Google, уже предустановлена в Python. Для ее использования предстоит лишь импортировать этот инструмент в проект:
Теперь можно заняться разработкой приложения и его user window.
Создание эскиза и логики
User Window нуждается в тщательной проработке перед реализацией в виде кода. Сначала разработчику нужно решить:
- какие данные и в каком виде требуется получить от пользователя;
- какое событие в приложении отвечает за расчет индекса массы тел: нажатие на кнопку, получение приложением определенных данных или что-нибудь другое;
- каким способом демонстрировать конечный результат.
User Window в рассматриваемом проекте позволяет получить от пользователя рост и вес в виде простых чисел. Вес вводится в килограммах, рост – в сантиметрах. Индекс массы тела рассчитывается при нажатии на специальную кнопку. Результат произведенных расчетов выводится во всплывающем window в качестве значения индекса массы тела и категории, к которой он имеет непосредственное отношение.
Выше – наглядный пример того, как будет выглядеть app window. Это элементарный пример интерфейса.
Создание основного окна
Создание GUI на Python начинается с импорта библиотеки и загрузки ее методов:
Здесь первая строка дает возможность загрузки методов TKinter, а затем пользоваться ими в процессе написания исходного кода без ссылки на их именования. Вторая строка поддерживает явный импорт метода messagebox. Он используется для вывода всплывающего окна (result window) в качестве ответа на пользовательские действия. Этот прием является удобным, потому что упомянутый метод в исходном приложении потребуется несколько раз.
Теперь можно создать окно приложения (app window). Для этой цели рекомендуется использовать модуль TK. Программа будет называться «Калькулятор индекса массы тела (ИМТ)»:
После запуска предложенного фрагмента ничего не произойдет. Такое поведение Google не называет ошибочным. На самом деле код будет выполнен, а app window после этого закроется. Для устранения ситуации нужно явно указать, что окно программы не должно закрываться до тех пор, пока пользователь сам не инициирует соответствующий процесс. Google говорит о том, что к исходному коду нужно добавить функцию window.mainloop, указывающую на запуск цикла событий:
Чтобы окно поместилось на экране, рекомендуется воспользоваться методом geometry. Он используется для задания размера окна программы:
Теперь можно заняться контролем расположения компонентов программного обеспечения.
Frame и контроль расположения компонентов
В app window нужно разместить несколько элементов с получившегося ранее эскиза: два поля ввода данных с характерными подписями, а также одну кнопку. Требуется следить, чтобы эти компоненты не накладывались друг на друга и не уходили за пределы app window. Google указывает, что в TKinter для контроля за элементами есть разные методы:
- Pack – применяется при работе с контейнерами для элементов. Дает возможность позиционировать кнопки, надписи и друг��е графические компоненты внутри контейнеров.
- Place – используется для позиционирования по точным координатам.
- Grid – применяется для размещения элементов по ячейкам словной сетки. Она будет служить разделителем окна программы.
Далее будут использованы grid и pack. Для начала нужно создать виджет Frame – в нем размещаются надписи, поля ввода и кнопки. Отступы по горизонтали и вертикали будут 10 пикселей:
Выше – фрагмент программного кода, который нужно добавить в свой проект.
Поля и кнопки
Следующий этап разработки – это добавление в окне приложения (app window) трех видов виджетов:
- поле ввода данных (Entry);
- текстовые надписи (Label);
- кнопку (Button).
Google указывает на то, что надписи создаются через Label-виджет:
Ему передаются два параметра:
- Frame – используется заготовка виджета Frame. В нем уже имеются настройки для отступов по вертикали и горизонтали.
- Text – текст, который выводится на экран app window.
Для позиционирования Google рекомендует использовать grid-метод. Предстоит указать, что текст должен располагаться в ячейке с координатами «третья строка и первый столбец». При запуске программы надпись отобразится по центру. Нужное положение будет принято после добавления других компонентов.
Теперь можно добавить вторую надпись, но при позиционировании в grid указывается 4-я строка:
Поля ввода пользовательской информации добавляются, согласно Google, через Entry:
Для позиционирования здесь тоже используется метод grid. Entry должен быть расположен около надписи «Введите свой рост». Это приводит к тому, что нужно использовать ячейку в той же строке, но в другом столбце. Остается добавить поле ввода веса:
А вот принцип добавления кнопки, которая отвечает за расчет индекса массы тела:
Графическое приложение на Python почти готово. Остается написать код, который будет отвечать за получение данных из Entry и рассчитывать ИМТ.
Программирование функций
Google указывает на то, что для расчетов используется функция calculate:
Для вывода результата пользователю на экран эта команда дополняется условным оператором if. Он поможет учесть полученные значения индекса массы тела. В TKinter есть messagebox, который используется для отображения сообщения о всплывающем окне:
Завершающий этап – привязка расчетов к нажатию по кнопке «Рассчитать ИМТ». Для этого Google требует использования свойства command в виджете Button:
Графический интерфейс на Python и простейшее первое приложение на TKinter готовы.
Интересует Python? Добро пожаловать на курс в Otus!
<!DOCTYPE html>
<html dir="ltr" lang="ru-RU">
<head>
<meta charset="UTF-8" />
<meta http-equiv="x-ua-compatible" content="ie=edge" />
<meta name="viewport" content="width=device-width, initial-scale=1" />
<link rel="profile" href="http://gmpg.org/xfn/11" />
<title>Питон и графический интерфейс OTUS</title>
<!-- All in One SEO 4.5.2.1 - aioseo.com -->
<meta name="description" content="Python – известный язык разработки, который может похвастаться не просто читабельным кодом и низким порогом вхождения, но и функциональностью. Он используется для написания самых разных программ – от десктопных до мобильных и консольных, от бизнес-приложений до небольших игр. Иногда выступает дополнительным инструментом разработчика. При помощи Python, как говорит Google, можно писать и графические интерфейсы. Далее" />
<meta name="robots" content="max-image-preview:large" />
<link rel="canonical" href="https://otus.ru/journal/piton-i-graficheskij-interfejs/" />
<meta name="generator" content="All in One SEO (AIOSEO) 4.5.2.1" />
<script type="application/ld+json" class="aioseo-schema">
{"@context":"https:\/\/schema.org","@graph":[{"@type":"Article","@id":"https:\/\/otus.ru\/journal\/piton-i-graficheskij-interfejs\/#article","name":"\u041f\u0438\u0442\u043e\u043d \u0438 \u0433\u0440\u0430\u0444\u0438\u0447\u0435\u0441\u043a\u0438\u0439 \u0438\u043d\u0442\u0435\u0440\u0444\u0435\u0439\u0441 OTUS","headline":"\u041f\u0438\u0442\u043e\u043d \u0438 \u0433\u0440\u0430\u0444\u0438\u0447\u0435\u0441\u043a\u0438\u0439 \u0438\u043d\u0442\u0435\u0440\u0444\u0435\u0439\u0441","author":{"@id":"https:\/\/otus.ru\/journal\/author\/a-pavlenko\/#author"},"publisher":{"@id":"https:\/\/otus.ru\/journal\/#organization"},"image":{"@type":"ImageObject","url":"https:\/\/otus.ru\/journal\/wp-content\/uploads\/2023\/11\/oj-1080x72038-1.jpg","width":2245,"height":1587},"datePublished":"2023-11-15T20:59:05+00:00","dateModified":"2023-12-19T18:55:41+00:00","inLanguage":"ru-RU","mainEntityOfPage":{"@id":"https:\/\/otus.ru\/journal\/piton-i-graficheskij-interfejs\/#webpage"},"isPartOf":{"@id":"https:\/\/otus.ru\/journal\/piton-i-graficheskij-interfejs\/#webpage"},"articleSection":"\u041f\u043e\u043b\u0435\u0437\u043d\u043e\u0435, Python"},{"@type":"BreadcrumbList","@id":"https:\/\/otus.ru\/journal\/piton-i-graficheskij-interfejs\/#breadcrumblist","itemListElement":[{"@type":"ListItem","@id":"https:\/\/otus.ru\/journal\/#listItem","position":1,"name":"\u0413\u043b\u0430\u0432\u043d\u0430\u044f \u0441\u0442\u0440\u0430\u043d\u0438\u0446\u0430","item":"https:\/\/otus.ru\/journal\/","nextItem":"https:\/\/otus.ru\/journal\/piton-i-graficheskij-interfejs\/#listItem"},{"@type":"ListItem","@id":"https:\/\/otus.ru\/journal\/piton-i-graficheskij-interfejs\/#listItem","position":2,"name":"\u041f\u0438\u0442\u043e\u043d \u0438 \u0433\u0440\u0430\u0444\u0438\u0447\u0435\u0441\u043a\u0438\u0439 \u0438\u043d\u0442\u0435\u0440\u0444\u0435\u0439\u0441","previousItem":"https:\/\/otus.ru\/journal\/#listItem"}]},{"@type":"Organization","@id":"https:\/\/otus.ru\/journal\/#organization","name":"\u041e\u0442\u0443\u0441 \u043e\u043d\u043b\u0430\u0439\u043d-\u043e\u0431\u0440\u0430\u0437\u043e\u0432\u0430\u043d\u0438\u0435","url":"https:\/\/otus.ru\/journal\/","sameAs":["https:\/\/www.youtube.com\/channel\/UCetgtvy93o3i3CvyGXKFU3g"],"contactPoint":{"@type":"ContactPoint","telephone":"+74999389202","contactType":"Customer Support"}},{"@type":"Person","@id":"https:\/\/otus.ru\/journal\/author\/a-pavlenko\/#author","url":"https:\/\/otus.ru\/journal\/author\/a-pavlenko\/","name":"A. Pavlenko","image":{"@type":"ImageObject","@id":"https:\/\/otus.ru\/journal\/piton-i-graficheskij-interfejs\/#authorImage","url":"https:\/\/secure.gravatar.com\/avatar\/d4c499a104d7c2522fa41f89e6819499?s=96&d=mm&r=g","width":96,"height":96,"caption":"A. Pavlenko"}},{"@type":"WebPage","@id":"https:\/\/otus.ru\/journal\/piton-i-graficheskij-interfejs\/#webpage","url":"https:\/\/otus.ru\/journal\/piton-i-graficheskij-interfejs\/","name":"\u041f\u0438\u0442\u043e\u043d \u0438 \u0433\u0440\u0430\u0444\u0438\u0447\u0435\u0441\u043a\u0438\u0439 \u0438\u043d\u0442\u0435\u0440\u0444\u0435\u0439\u0441 OTUS","description":"Python \u2013 \u0438\u0437\u0432\u0435\u0441\u0442\u043d\u044b\u0439 \u044f\u0437\u044b\u043a \u0440\u0430\u0437\u0440\u0430\u0431\u043e\u0442\u043a\u0438, \u043a\u043e\u0442\u043e\u0440\u044b\u0439 \u043c\u043e\u0436\u0435\u0442 \u043f\u043e\u0445\u0432\u0430\u0441\u0442\u0430\u0442\u044c\u0441\u044f \u043d\u0435 \u043f\u0440\u043e\u0441\u0442\u043e \u0447\u0438\u0442\u0430\u0431\u0435\u043b\u044c\u043d\u044b\u043c \u043a\u043e\u0434\u043e\u043c \u0438 \u043d\u0438\u0437\u043a\u0438\u043c \u043f\u043e\u0440\u043e\u0433\u043e\u043c \u0432\u0445\u043e\u0436\u0434\u0435\u043d\u0438\u044f, \u043d\u043e \u0438 \u0444\u0443\u043d\u043a\u0446\u0438\u043e\u043d\u0430\u043b\u044c\u043d\u043e\u0441\u0442\u044c\u044e. \u041e\u043d \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u0443\u0435\u0442\u0441\u044f \u0434\u043b\u044f \u043d\u0430\u043f\u0438\u0441\u0430\u043d\u0438\u044f \u0441\u0430\u043c\u044b\u0445 \u0440\u0430\u0437\u043d\u044b\u0445 \u043f\u0440\u043e\u0433\u0440\u0430\u043c\u043c \u2013 \u043e\u0442 \u0434\u0435\u0441\u043a\u0442\u043e\u043f\u043d\u044b\u0445 \u0434\u043e \u043c\u043e\u0431\u0438\u043b\u044c\u043d\u044b\u0445 \u0438 \u043a\u043e\u043d\u0441\u043e\u043b\u044c\u043d\u044b\u0445, \u043e\u0442 \u0431\u0438\u0437\u043d\u0435\u0441-\u043f\u0440\u0438\u043b\u043e\u0436\u0435\u043d\u0438\u0439 \u0434\u043e \u043d\u0435\u0431\u043e\u043b\u044c\u0448\u0438\u0445 \u0438\u0433\u0440. \u0418\u043d\u043e\u0433\u0434\u0430 \u0432\u044b\u0441\u0442\u0443\u043f\u0430\u0435\u0442 \u0434\u043e\u043f\u043e\u043b\u043d\u0438\u0442\u0435\u043b\u044c\u043d\u044b\u043c \u0438\u043d\u0441\u0442\u0440\u0443\u043c\u0435\u043d\u0442\u043e\u043c \u0440\u0430\u0437\u0440\u0430\u0431\u043e\u0442\u0447\u0438\u043a\u0430. \u041f\u0440\u0438 \u043f\u043e\u043c\u043e\u0449\u0438 Python, \u043a\u0430\u043a \u0433\u043e\u0432\u043e\u0440\u0438\u0442 Google, \u043c\u043e\u0436\u043d\u043e \u043f\u0438\u0441\u0430\u0442\u044c \u0438 \u0433\u0440\u0430\u0444\u0438\u0447\u0435\u0441\u043a\u0438\u0435 \u0438\u043d\u0442\u0435\u0440\u0444\u0435\u0439\u0441\u044b. \u0414\u0430\u043b\u0435\u0435","inLanguage":"ru-RU","isPartOf":{"@id":"https:\/\/otus.ru\/journal\/#website"},"breadcrumb":{"@id":"https:\/\/otus.ru\/journal\/piton-i-graficheskij-interfejs\/#breadcrumblist"},"author":{"@id":"https:\/\/otus.ru\/journal\/author\/a-pavlenko\/#author"},"creator":{"@id":"https:\/\/otus.ru\/journal\/author\/a-pavlenko\/#author"},"image":{"@type":"ImageObject","url":"https:\/\/otus.ru\/journal\/wp-content\/uploads\/2023\/11\/oj-1080x72038-1.jpg","@id":"https:\/\/otus.ru\/journal\/piton-i-graficheskij-interfejs\/#mainImage","width":2245,"height":1587},"primaryImageOfPage":{"@id":"https:\/\/otus.ru\/journal\/piton-i-graficheskij-interfejs\/#mainImage"},"datePublished":"2023-11-15T20:59:05+00:00","dateModified":"2023-12-19T18:55:41+00:00"},{"@type":"WebSite","@id":"https:\/\/otus.ru\/journal\/#website","url":"https:\/\/otus.ru\/journal\/","name":"OTUS JOURNAL","description":"Blog about IT","inLanguage":"ru-RU","publisher":{"@id":"https:\/\/otus.ru\/journal\/#organization"}}]}
</script>
<!-- All in One SEO -->
<link rel='dns-prefetch' href='//otus.ru' />
<link rel='dns-prefetch' href='//fonts.googleapis.com' />
<link rel='stylesheet' id='wp-block-library-css' href='https://otus.ru/journal/wp-includes/css/dist/block-library/style.min.css?ver=6.4.7' type='text/css' media='all' />
<style id='classic-theme-styles-inline-css' type='text/css'>
/*! This file is auto-generated */
.wp-block-button__link{color:#fff;background-color:#32373c;border-radius:9999px;box-shadow:none;text-decoration:none;padding:calc(.667em + 2px) calc(1.333em + 2px);font-size:1.125em}.wp-block-file__button{background:#32373c;color:#fff;text-decoration:none}
</style>
<style id='global-styles-inline-css' type='text/css'>
body{--wp--preset--color--black: #000000;--wp--preset--color--cyan-bluish-gray: #abb8c3;--wp--preset--color--white: #ffffff;--wp--preset--color--pale-pink: #f78da7;--wp--preset--color--vivid-red: #cf2e2e;--wp--preset--color--luminous-vivid-orange: #ff6900;--wp--preset--color--luminous-vivid-amber: #fcb900;--wp--preset--color--light-green-cyan: #7bdcb5;--wp--preset--color--vivid-green-cyan: #00d084;--wp--preset--color--pale-cyan-blue: #8ed1fc;--wp--preset--color--vivid-cyan-blue: #0693e3;--wp--preset--color--vivid-purple: #9b51e0;--wp--preset--gradient--vivid-cyan-blue-to-vivid-purple: linear-gradient(135deg,rgba(6,147,227,1) 0%,rgb(155,81,224) 100%);--wp--preset--gradient--light-green-cyan-to-vivid-green-cyan: linear-gradient(135deg,rgb(122,220,180) 0%,rgb(0,208,130) 100%);--wp--preset--gradient--luminous-vivid-amber-to-luminous-vivid-orange: linear-gradient(135deg,rgba(252,185,0,1) 0%,rgba(255,105,0,1) 100%);--wp--preset--gradient--luminous-vivid-orange-to-vivid-red: linear-gradient(135deg,rgba(255,105,0,1) 0%,rgb(207,46,46) 100%);--wp--preset--gradient--very-light-gray-to-cyan-bluish-gray: linear-gradient(135deg,rgb(238,238,238) 0%,rgb(169,184,195) 100%);--wp--preset--gradient--cool-to-warm-spectrum: linear-gradient(135deg,rgb(74,234,220) 0%,rgb(151,120,209) 20%,rgb(207,42,186) 40%,rgb(238,44,130) 60%,rgb(251,105,98) 80%,rgb(254,248,76) 100%);--wp--preset--gradient--blush-light-purple: linear-gradient(135deg,rgb(255,206,236) 0%,rgb(152,150,240) 100%);--wp--preset--gradient--blush-bordeaux: linear-gradient(135deg,rgb(254,205,165) 0%,rgb(254,45,45) 50%,rgb(107,0,62) 100%);--wp--preset--gradient--luminous-dusk: linear-gradient(135deg,rgb(255,203,112) 0%,rgb(199,81,192) 50%,rgb(65,88,208) 100%);--wp--preset--gradient--pale-ocean: linear-gradient(135deg,rgb(255,245,203) 0%,rgb(182,227,212) 50%,rgb(51,167,181) 100%);--wp--preset--gradient--electric-grass: linear-gradient(135deg,rgb(202,248,128) 0%,rgb(113,206,126) 100%);--wp--preset--gradient--midnight: linear-gradient(135deg,rgb(2,3,129) 0%,rgb(40,116,252) 100%);--wp--preset--font-size--small: 13px;--wp--preset--font-size--medium: 20px;--wp--preset--font-size--large: 36px;--wp--preset--font-size--x-large: 42px;--wp--preset--spacing--20: 0.44rem;--wp--preset--spacing--30: 0.67rem;--wp--preset--spacing--40: 1rem;--wp--preset--spacing--50: 1.5rem;--wp--preset--spacing--60: 2.25rem;--wp--preset--spacing--70: 3.38rem;--wp--preset--spacing--80: 5.06rem;--wp--preset--shadow--natural: 6px 6px 9px rgba(0, 0, 0, 0.2);--wp--preset--shadow--deep: 12px 12px 50px rgba(0, 0, 0, 0.4);--wp--preset--shadow--sharp: 6px 6px 0px rgba(0, 0, 0, 0.2);--wp--preset--shadow--outlined: 6px 6px 0px -3px rgba(255, 255, 255, 1), 6px 6px rgba(0, 0, 0, 1);--wp--preset--shadow--crisp: 6px 6px 0px rgba(0, 0, 0, 1);}:where(.is-layout-flex){gap: 0.5em;}:where(.is-layout-grid){gap: 0.5em;}body .is-layout-flow > .alignleft{float: left;margin-inline-start: 0;margin-inline-end: 2em;}body .is-layout-flow > .alignright{float: right;margin-inline-start: 2em;margin-inline-end: 0;}body .is-layout-flow > .aligncenter{margin-left: auto !important;margin-right: auto !important;}body .is-layout-constrained > .alignleft{float: left;margin-inline-start: 0;margin-inline-end: 2em;}body .is-layout-constrained > .alignright{float: right;margin-inline-start: 2em;margin-inline-end: 0;}body .is-layout-constrained > .aligncenter{margin-left: auto !important;margin-right: auto !important;}body .is-layout-constrained > :where(:not(.alignleft):not(.alignright):not(.alignfull)){max-width: var(--wp--style--global--content-size);margin-left: auto !important;margin-right: auto !important;}body .is-layout-constrained > .alignwide{max-width: var(--wp--style--global--wide-size);}body .is-layout-flex{display: flex;}body .is-layout-flex{flex-wrap: wrap;align-items: center;}body .is-layout-flex > *{margin: 0;}body .is-layout-grid{display: grid;}body .is-layout-grid > *{margin: 0;}:where(.wp-block-columns.is-layout-flex){gap: 2em;}:where(.wp-block-columns.is-layout-grid){gap: 2em;}:where(.wp-block-post-template.is-layout-flex){gap: 1.25em;}:where(.wp-block-post-template.is-layout-grid){gap: 1.25em;}.has-black-color{color: var(--wp--preset--color--black) !important;}.has-cyan-bluish-gray-color{color: var(--wp--preset--color--cyan-bluish-gray) !important;}.has-white-color{color: var(--wp--preset--color--white) !important;}.has-pale-pink-color{color: var(--wp--preset--color--pale-pink) !important;}.has-vivid-red-color{color: var(--wp--preset--color--vivid-red) !important;}.has-luminous-vivid-orange-color{color: var(--wp--preset--color--luminous-vivid-orange) !important;}.has-luminous-vivid-amber-color{color: var(--wp--preset--color--luminous-vivid-amber) !important;}.has-light-green-cyan-color{color: var(--wp--preset--color--light-green-cyan) !important;}.has-vivid-green-cyan-color{color: var(--wp--preset--color--vivid-green-cyan) !important;}.has-pale-cyan-blue-color{color: var(--wp--preset--color--pale-cyan-blue) !important;}.has-vivid-cyan-blue-color{color: var(--wp--preset--color--vivid-cyan-blue) !important;}.has-vivid-purple-color{color: var(--wp--preset--color--vivid-purple) !important;}.has-black-background-color{background-color: var(--wp--preset--color--black) !important;}.has-cyan-bluish-gray-background-color{background-color: var(--wp--preset--color--cyan-bluish-gray) !important;}.has-white-background-color{background-color: var(--wp--preset--color--white) !important;}.has-pale-pink-background-color{background-color: var(--wp--preset--color--pale-pink) !important;}.has-vivid-red-background-color{background-color: var(--wp--preset--color--vivid-red) !important;}.has-luminous-vivid-orange-background-color{background-color: var(--wp--preset--color--luminous-vivid-orange) !important;}.has-luminous-vivid-amber-background-color{background-color: var(--wp--preset--color--luminous-vivid-amber) !important;}.has-light-green-cyan-background-color{background-color: var(--wp--preset--color--light-green-cyan) !important;}.has-vivid-green-cyan-background-color{background-color: var(--wp--preset--color--vivid-green-cyan) !important;}.has-pale-cyan-blue-background-color{background-color: var(--wp--preset--color--pale-cyan-blue) !important;}.has-vivid-cyan-blue-background-color{background-color: var(--wp--preset--color--vivid-cyan-blue) !important;}.has-vivid-purple-background-color{background-color: var(--wp--preset--color--vivid-purple) !important;}.has-black-border-color{border-color: var(--wp--preset--color--black) !important;}.has-cyan-bluish-gray-border-color{border-color: var(--wp--preset--color--cyan-bluish-gray) !important;}.has-white-border-color{border-color: var(--wp--preset--color--white) !important;}.has-pale-pink-border-color{border-color: var(--wp--preset--color--pale-pink) !important;}.has-vivid-red-border-color{border-color: var(--wp--preset--color--vivid-red) !important;}.has-luminous-vivid-orange-border-color{border-color: var(--wp--preset--color--luminous-vivid-orange) !important;}.has-luminous-vivid-amber-border-color{border-color: var(--wp--preset--color--luminous-vivid-amber) !important;}.has-light-green-cyan-border-color{border-color: var(--wp--preset--color--light-green-cyan) !important;}.has-vivid-green-cyan-border-color{border-color: var(--wp--preset--color--vivid-green-cyan) !important;}.has-pale-cyan-blue-border-color{border-color: var(--wp--preset--color--pale-cyan-blue) !important;}.has-vivid-cyan-blue-border-color{border-color: var(--wp--preset--color--vivid-cyan-blue) !important;}.has-vivid-purple-border-color{border-color: var(--wp--preset--color--vivid-purple) !important;}.has-vivid-cyan-blue-to-vivid-purple-gradient-background{background: var(--wp--preset--gradient--vivid-cyan-blue-to-vivid-purple) !important;}.has-light-green-cyan-to-vivid-green-cyan-gradient-background{background: var(--wp--preset--gradient--light-green-cyan-to-vivid-green-cyan) !important;}.has-luminous-vivid-amber-to-luminous-vivid-orange-gradient-background{background: var(--wp--preset--gradient--luminous-vivid-amber-to-luminous-vivid-orange) !important;}.has-luminous-vivid-orange-to-vivid-red-gradient-background{background: var(--wp--preset--gradient--luminous-vivid-orange-to-vivid-red) !important;}.has-very-light-gray-to-cyan-bluish-gray-gradient-background{background: var(--wp--preset--gradient--very-light-gray-to-cyan-bluish-gray) !important;}.has-cool-to-warm-spectrum-gradient-background{background: var(--wp--preset--gradient--cool-to-warm-spectrum) !important;}.has-blush-light-purple-gradient-background{background: var(--wp--preset--gradient--blush-light-purple) !important;}.has-blush-bordeaux-gradient-background{background: var(--wp--preset--gradient--blush-bordeaux) !important;}.has-luminous-dusk-gradient-background{background: var(--wp--preset--gradient--luminous-dusk) !important;}.has-pale-ocean-gradient-background{background: var(--wp--preset--gradient--pale-ocean) !important;}.has-electric-grass-gradient-background{background: var(--wp--preset--gradient--electric-grass) !important;}.has-midnight-gradient-background{background: var(--wp--preset--gradient--midnight) !important;}.has-small-font-size{font-size: var(--wp--preset--font-size--small) !important;}.has-medium-font-size{font-size: var(--wp--preset--font-size--medium) !important;}.has-large-font-size{font-size: var(--wp--preset--font-size--large) !important;}.has-x-large-font-size{font-size: var(--wp--preset--font-size--x-large) !important;}
.wp-block-navigation a:where(:not(.wp-element-button)){color: inherit;}
:where(.wp-block-post-template.is-layout-flex){gap: 1.25em;}:where(.wp-block-post-template.is-layout-grid){gap: 1.25em;}
:where(.wp-block-columns.is-layout-flex){gap: 2em;}:where(.wp-block-columns.is-layout-grid){gap: 2em;}
.wp-block-pullquote{font-size: 1.5em;line-height: 1.6;}
</style>
<link rel='stylesheet' id='wbcr-comments-plus-url-span-css' href='https://otus.ru/journal/wp-content/plugins/clearfy/components/comments-plus/assets/css/url-span.css?ver=2.2.0' type='text/css' media='all' />
<link rel='stylesheet' id='wpel-style-css' href='https://otus.ru/journal/wp-content/plugins/wp-external-links/public/css/wpel.css?ver=2.59' type='text/css' media='all' />
<link rel='stylesheet' id='ez-toc-css' href='https://otus.ru/journal/wp-content/plugins/easy-table-of-contents/assets/css/screen.min.css?ver=2.0.61' type='text/css' media='all' />
<style id='ez-toc-inline-css' type='text/css'>
div#ez-toc-container .ez-toc-title {font-size: 120%;}div#ez-toc-container .ez-toc-title {font-weight: 500;}div#ez-toc-container ul li {font-size: 95%;}div#ez-toc-container nav ul ul li {font-size: 90%;}
.ez-toc-container-direction {direction: ltr;}.ez-toc-counter ul{counter-reset: item ;}.ez-toc-counter nav ul li a::before {content: counters(item, ".", decimal) ". ";display: inline-block;counter-increment: item;flex-grow: 0;flex-shrink: 0;margin-right: .2em; float: left; }.ez-toc-widget-direction {direction: ltr;}.ez-toc-widget-container ul{counter-reset: item ;}.ez-toc-widget-container nav ul li a::before {content: counters(item, ".", decimal) ". ";display: inline-block;counter-increment: item;flex-grow: 0;flex-shrink: 0;margin-right: .2em; float: left; }
</style>
<link rel='stylesheet' id='contentberg-fonts-css' href='https://fonts.googleapis.com/css?family=Roboto%3A400%2C500%2C700%7CPT+Serif%3A400%2C400i%2C600%7CIBM+Plex+Serif%3A500' type='text/css' media='all' />
<link rel='stylesheet' id='contentberg-core-css' href='https://otus.ru/journal/wp-content/themes/contentberg/style.css?ver=1.8.3' type='text/css' media='all' />
<link rel='stylesheet' id='contentberg-lightbox-css' href='https://otus.ru/journal/wp-content/themes/contentberg/css/lightbox.css?ver=1.8.3' type='text/css' media='all' />
<link rel='stylesheet' id='font-awesome-css' href='https://otus.ru/journal/wp-content/themes/contentberg/css/fontawesome/css/font-awesome.min.css?ver=1.8.3' type='text/css' media='all' />
<script type="text/javascript" id="breeze-prefetch-js-extra">
/* <![CDATA[ */
var breeze_prefetch = {"local_url":"https:\/\/otus.ru\/journal","ignore_remote_prefetch":"1","ignore_list":["\/wp-admin\/"]};
/* ]]> */
</script>
<script type="text/javascript" src="https://otus.ru/journal/wp-content/plugins/breeze/assets/js/js-front-end/breeze-prefetch-links.min.js" id="breeze-prefetch-js"></script>
<script type="text/javascript" src="https://otus.ru/journal/wp-includes/js/jquery/jquery.min.js" id="jquery-core-js"></script>
<script type="text/javascript" src="https://otus.ru/journal/wp-includes/js/jquery/jquery-migrate.min.js" id="jquery-migrate-js"></script>
<script type="text/javascript" src="https://otus.ru/journal/wp-content/themes/contentberg/js/lazysizes.js" id="lazysizes-js"></script>
<link rel="https://api.w.org/" href="https://otus.ru/journal/wp-json/" /><link rel="alternate" type="application/json" href="https://otus.ru/journal/wp-json/wp/v2/posts/8023" /><link rel='shortlink' href='https://otus.ru/journal/?p=8023' />
<link rel="alternate" type="application/json+oembed" href="https://otus.ru/journal/wp-json/oembed/1.0/embed?url=https%3A%2F%2Fotus.ru%2Fjournal%2Fpiton-i-graficheskij-interfejs%2F" />
<link rel="alternate" type="text/xml+oembed" href="https://otus.ru/journal/wp-json/oembed/1.0/embed?url=https%3A%2F%2Fotus.ru%2Fjournal%2Fpiton-i-graficheskij-interfejs%2F&format=xml" />
<script>var Sphere_Plugin = {"ajaxurl":"https:\/\/otus.ru\/journal\/wp-admin\/admin-ajax.php"};</script><link rel="icon" href="https://otus.ru/journal/wp-content/uploads/2020/11/cropped-OTUS_logo_OTUS-COMP-LOGO-WHITE-1-32x32.png" sizes="32x32" />
<link rel="icon" href="https://otus.ru/journal/wp-content/uploads/2020/11/cropped-OTUS_logo_OTUS-COMP-LOGO-WHITE-1-192x192.png" sizes="192x192" />
<link rel="apple-touch-icon" href="https://otus.ru/journal/wp-content/uploads/2020/11/cropped-OTUS_logo_OTUS-COMP-LOGO-WHITE-1-180x180.png" />
<meta name="msapplication-TileImage" content="https://otus.ru/journal/wp-content/uploads/2020/11/cropped-OTUS_logo_OTUS-COMP-LOGO-WHITE-1-270x270.png" />
<style type="text/css" id="wp-custom-css">
#menu-item-10406 .wpel-icon {
display: none;
}
#menu-item-10407 .wpel-icon {
display: none;
}
.otus-login-site a .wpel-icon {
display: none;
}
.menu-menju-navykov-container a .wpel-icon {
display: none;
}
.otus-login-site a
{
background: #ffd709;
border-radius: 12px;
color: #0f0f10;
font-size: 14px;
font-weight: 700;
line-height: 20px;
display: block;
text-align: center;
padding: 8px 25px;
}
.main-footer.dark {
background: linear-gradient(90deg, #a64fc5, #4f54e6);
border-color: transparent;
}
.main-footer.bold .copyright {
color: #fff;
}
.main-footer.bold .to-top i {
color: #fff;
}
.main-footer.bold .back-to-top {
color: #fff;
}
.nav__scroll {
overflow-x: auto;
-webkit-overflow-scrolling: touch;
}
.scrollable-menu .menu {
display: flex;
}
.nav__scroll
{
background: linear-gradient(90deg, #a64fc5, #4f54e6);
}
.scrollable-menu .menu .menu-item {
flex: 0 0 auto;
padding: 15px 15px;
}
.scrollable-menu .menu .menu-item a {
color: #fff;
}
.nav__scroll::-webkit-scrollbar{background-color:#fff;height:5px;}
.nav__scroll::-webkit-scrollbar-thumb{background-color:#dcdcdc;}
.nav__scroll::-webkit-scrollbar-track{-webkit-border-radius:0;border-radius:0;background-color:#fff;}/
body {
min-width: 320px;
}
.banner-click img {
margin: 0 auto;
display: block;
}
.banner-click {
cursor: pointer;
}
.banner-footer-area {
margin-bottom: 20px;
}
.banner-left-area {
margin-top: 40px;
} </style>
<!--Start VDZ Yandex Metrika Plugin-->
<!-- Yandex.Metrika counter --><script type="text/javascript" >(function(m,e,t,r,i,k,a){m[i]=m[i]||function(){(m[i].a=m[i].a||[]).push(arguments)};m[i].l=1*new Date();k=e.createElement(t),a=e.getElementsByTagName(t)[0],k.async=1,k.src=r,a.parentNode.insertBefore(k,a)})(window, document, "script", "https://mc.yandex.ru/metrika/tag.js", "ym");ym(34531570, "init", {clickmap:true, trackLinks:true, accurateTrackBounce:true, webvisor:true, trackHash:true, ecommerce:"dataLayer"});</script>
<noscript><div><img src="https://mc.yandex.ru/watch/34531570" style="position:absolute; left:-9999px;" alt="" /></div></noscript>
<!-- /Yandex.Metrika counter --><!--START ADD EVENTS FROM CF7--><script type='text/javascript'>document.addEventListener( 'wpcf7submit', function( event ) {
//event.detail.contactFormId;
if(ym){
//console.log(event.detail);
ym(34531570, 'reachGoal', 'VDZ_SEND_CONTACT_FORM_7');
ym(34531570, 'params', {
page_url: window.location.href,
status: event.detail.status,
locale: event.detail.contactFormLocale,
form_id: event.detail.contactFormId,
});
}
}, false );
</script><!--END ADD EVENTS FROM CF7-->
<!--End VDZ Yandex Metrika Plugin-->
</head>
<body class="post-template-default single single-post postid-8023 single-format-standard right-sidebar lazy-normal has-lb">
<div class="main-wrap">
<header id="main-head" class="main-head head-nav-below has-search-modal simple simple-boxed">
<div class="inner inner-head" data-sticky-bar="0">
<div class="wrap cf wrap-head">
<div class="left-contain">
<span class="mobile-nav"><i class="fa fa-bars"></i></span>
<div class="title">
<a href="https://otus.ru/journal/" title="OTUS JOURNAL" rel="home" data-wpel-link="internal">
<span class="text-logo"><img src="/journal/wp-content/themes/contentberg/img/logo_site.svg" alt="OTUS JOURNAL"></span>
</a>
</div>
</div>
<div class="navigation-wrap inline">
<nav class="navigation inline simple light" data-sticky-bar="0">
<div class="menu-rubriki-container"><ul id="menu-rubriki" class="menu"><li id="menu-item-109" class="menu-item menu-item-type-taxonomy menu-item-object-category menu-cat-1 menu-item-109"><a href="https://otus.ru/journal/category/pro-it/" data-wpel-link="internal"><span>Про IT</span></a></li>
<li id="menu-item-113" class="menu-item menu-item-type-taxonomy menu-item-object-category current-post-ancestor current-menu-parent current-post-parent menu-cat-4 menu-item-113"><a href="https://otus.ru/journal/category/polza/" data-wpel-link="internal"><span>Полезное</span></a></li>
<li id="menu-item-114" class="menu-item menu-item-type-taxonomy menu-item-object-category menu-cat-3 menu-item-114"><a href="https://otus.ru/journal/category/lifestyle/" data-wpel-link="internal"><span>Лайфстайл</span></a></li>
<li id="menu-item-10406" class="menu-item menu-item-type-custom menu-item-object-custom menu-item-10406"><a href="https://otus.ru/catalog/courses" data-wpel-link="external" target="_blank" rel="nofollow external noopener noreferrer" class="wpel-icon-right"><span>Обучение</span><span class="wpel-icon wpel-image wpel-icon-6"></span></a></li>
<li id="menu-item-10407" class="menu-item menu-item-type-custom menu-item-object-custom menu-item-10407"><a href="https://otus.ru/about" data-wpel-link="external" target="_blank" rel="nofollow external noopener noreferrer" class="wpel-icon-right"><span>Информация</span><span class="wpel-icon wpel-image wpel-icon-6"></span></a></li>
</ul></div> </nav>
</div>
<div class="actions">
<div class="otus-login-site">
<a href="https://otus.ru/login/" target="_blank" data-wpel-link="external" rel="nofollow external noopener noreferrer" class="wpel-icon-right">Войти<span class="wpel-icon wpel-image wpel-icon-6"></span></a>
</div>
<a href="#" title="Search" class="search-link"><i class="fa fa-search"></i></a>
</div>
</div>
</div>
</header> <!-- .main-head -->
<div class="nav nav_disable nav_colored nav_transparent course-categories__nav nav__scroll ">
<div class="container wrap">
<div class="links inline simple light scrollable-menu">
<div class="menu-menju-navykov-container"><ul id="menu-menju-navykov" class="menu"><li id="menu-item-10413" class="menu-item menu-item-type-custom menu-item-object-custom menu-item-10413"><a href="https://otus.ru/categories/programming/" data-wpel-link="external" target="_blank" rel="nofollow external noopener noreferrer" class="wpel-icon-right">Программирование<span class="wpel-icon wpel-image wpel-icon-6"></span></a></li>
<li id="menu-item-10414" class="menu-item menu-item-type-custom menu-item-object-custom menu-item-10414"><a href="https://otus.ru/categories/architecture/" data-wpel-link="external" target="_blank" rel="nofollow external noopener noreferrer" class="wpel-icon-right">Архитектура<span class="wpel-icon wpel-image wpel-icon-6"></span></a></li>
<li id="menu-item-10415" class="menu-item menu-item-type-custom menu-item-object-custom menu-item-10415"><a href="https://otus.ru/categories/operations/" data-wpel-link="external" target="_blank" rel="nofollow external noopener noreferrer" class="wpel-icon-right">Инфраструктура<span class="wpel-icon wpel-image wpel-icon-6"></span></a></li>
<li id="menu-item-10416" class="menu-item menu-item-type-custom menu-item-object-custom menu-item-10416"><a href="https://otus.ru/categories/information-security-courses/" data-wpel-link="external" target="_blank" rel="nofollow external noopener noreferrer" class="wpel-icon-right">Безопасность<span class="wpel-icon wpel-image wpel-icon-6"></span></a></li>
<li id="menu-item-10417" class="menu-item menu-item-type-custom menu-item-object-custom menu-item-10417"><a href="https://otus.ru/categories/data-science/" data-wpel-link="external" target="_blank" rel="nofollow external noopener noreferrer" class="wpel-icon-right">Data Science<span class="wpel-icon wpel-image wpel-icon-6"></span></a></li>
<li id="menu-item-10418" class="menu-item menu-item-type-custom menu-item-object-custom menu-item-10418"><a href="https://otus.ru/categories/gamedev/" data-wpel-link="external" target="_blank" rel="nofollow external noopener noreferrer" class="wpel-icon-right">GameDev<span class="wpel-icon wpel-image wpel-icon-6"></span></a></li>
<li id="menu-item-10419" class="menu-item menu-item-type-custom menu-item-object-custom menu-item-10419"><a href="https://otus.ru/categories/marketing-business/" data-wpel-link="external" target="_blank" rel="nofollow external noopener noreferrer" class="wpel-icon-right">Управление<span class="wpel-icon wpel-image wpel-icon-6"></span></a></li>
<li id="menu-item-10420" class="menu-item menu-item-type-custom menu-item-object-custom menu-item-10420"><a href="https://otus.ru/categories/analytics/" data-wpel-link="external" target="_blank" rel="nofollow external noopener noreferrer" class="wpel-icon-right">Аналитика и анализ<span class="wpel-icon wpel-image wpel-icon-6"></span></a></li>
<li id="menu-item-10421" class="menu-item menu-item-type-custom menu-item-object-custom menu-item-10421"><a href="https://otus.ru/categories/testing/" data-wpel-link="external" target="_blank" rel="nofollow external noopener noreferrer" class="wpel-icon-right">Тестирование<span class="wpel-icon wpel-image wpel-icon-6"></span></a></li>
</ul></div> </div>
</div>
</div>
<div class="main wrap">
<div class="ts-row cf">
<div class="col-8 main-content cf">
<article id="post-8023" class="the-post post-8023 post type-post status-publish format-standard has-post-thumbnail category-polza tag-python">
<header class="post-header the-post-header cf">
<div class="post-meta the-post-meta">
<span class="post-cat">
<a href="https://otus.ru/journal/category/polza/" class="category" data-wpel-link="internal">Полезное</a>
</span>
<h1 class="post-title">
Питон и графический интерфейс
</h1>
<a href="https://otus.ru/journal/piton-i-graficheskij-interfejs/" class="date-link" data-wpel-link="internal"><time class="post-date">15 ноября, 2023</time></a>
</div>
<div class="featured">
<a href="https://otus.ru/journal/wp-content/uploads/2023/11/oj-1080x72038-1.jpg" class="image-link" data-wpel-link="internal"><img width="770" height="515" src="data:image/svg+xml,%3Csvg%20viewBox%3D%270%200%20770%20515%27%20xmlns%3D%27http%3A%2F%2Fwww.w3.org%2F2000%2Fsvg%27%3E%3C%2Fsvg%3E" class="attachment-contentberg-main size-contentberg-main lazyload wp-post-image" alt="Питон и графический интерфейс" title="Питон и графический интерфейс" decoding="async" fetchpriority="high" data-srcset="https://otus.ru/journal/wp-content/uploads/2023/11/oj-1080x72038-1-770x515.jpg 770w, https://otus.ru/journal/wp-content/uploads/2023/11/oj-1080x72038-1-270x180.jpg 270w" data-src="https://otus.ru/journal/wp-content/uploads/2023/11/oj-1080x72038-1-770x515.jpg" data-sizes="(max-width: 770px) 100vw, 770px" /> </a>
</div>
</header><!-- .post-header -->
<div class="post-content description cf entry-content content-normal">
<div id="ez-toc-container" class="ez-toc-v2_0_61 counter-hierarchy ez-toc-counter ez-toc-grey ez-toc-container-direction">
<div class="ez-toc-title-container">
<p class="ez-toc-title " >Содержание</p>
<span class="ez-toc-title-toggle"><a href="#" class="ez-toc-pull-right ez-toc-btn ez-toc-btn-xs ez-toc-btn-default ez-toc-toggle" aria-label="Toggle Table of Content"><span class="ez-toc-js-icon-con"><span class=""><span class="eztoc-hide" style="display:none;">Toggle</span><span class="ez-toc-icon-toggle-span"><svg style="fill: #999;color:#999" xmlns="http://www.w3.org/2000/svg" class="list-377408" width="20px" height="20px" viewBox="0 0 24 24" fill="none"><path d="M6 6H4v2h2V6zm14 0H8v2h12V6zM4 11h2v2H4v-2zm16 0H8v2h12v-2zM4 16h2v2H4v-2zm16 0H8v2h12v-2z" fill="currentColor"></path></svg><svg style="fill: #999;color:#999" class="arrow-unsorted-368013" xmlns="http://www.w3.org/2000/svg" width="10px" height="10px" viewBox="0 0 24 24" version="1.2" baseProfile="tiny"><path d="M18.2 9.3l-6.2-6.3-6.2 6.3c-.2.2-.3.4-.3.7s.1.5.3.7c.2.2.4.3.7.3h11c.3 0 .5-.1.7-.3.2-.2.3-.5.3-.7s-.1-.5-.3-.7zM5.8 14.7l6.2 6.3 6.2-6.3c.2-.2.3-.5.3-.7s-.1-.5-.3-.7c-.2-.2-.4-.3-.7-.3h-11c-.3 0-.5.1-.7.3-.2.2-.3.5-.3.7s.1.5.3.7z"/></svg></span></span></span></a></span></div>
<nav><ul class='ez-toc-list ez-toc-list-level-1 ' ><li class='ez-toc-page-1 ez-toc-heading-level-2'><a class="ez-toc-link ez-toc-heading-1" href="#GUI_%E2%80%93_%D1%8D%D1%82%D0%BE%E2%80%A6" title="GUI – это…">GUI – это…</a></li><li class='ez-toc-page-1 ez-toc-heading-level-2'><a class="ez-toc-link ez-toc-heading-2" href="#%D0%98%D0%BD%D1%81%D1%82%D1%80%D1%83%D0%BC%D0%B5%D0%BD%D1%82%D1%8B_%D1%80%D0%B0%D0%B7%D1%80%D0%B0%D0%B1%D0%BE%D1%82%D1%87%D0%B8%D0%BA%D0%B0" title="Инструменты разработчика">Инструменты разработчика</a></li><li class='ez-toc-page-1 ez-toc-heading-level-2'><a class="ez-toc-link ez-toc-heading-3" href="#%D0%94%D0%BB%D1%8F_%D1%87%D0%B5%D0%B3%D0%BE_%D0%BD%D1%83%D0%B6%D0%BD%D1%8B_GUI-%D0%B1%D0%B8%D0%B1%D0%BB%D0%B8%D0%BE%D1%82%D0%B5%D0%BA%D0%B8" title="Для чего нужны GUI-библиотеки">Для чего нужны GUI-библиотеки</a></li><li class='ez-toc-page-1 ez-toc-heading-level-2'><a class="ez-toc-link ez-toc-heading-4" href="#%D0%9A%D1%80%D0%B0%D1%82%D0%BA%D0%B8%D0%B9_%D0%BE%D0%B1%D0%B7%D0%BE%D1%80_%D1%84%D1%80%D0%B5%D0%B9%D0%BC%D0%B2%D0%BE%D1%80%D0%BA%D0%BE%D0%B2" title="Краткий обзор фреймворков">Краткий обзор фреймворков</a><ul class='ez-toc-list-level-3' ><li class='ez-toc-heading-level-3'><a class="ez-toc-link ez-toc-heading-5" href="#Eel" title="Eel">Eel</a><ul class='ez-toc-list-level-4' ><li class='ez-toc-heading-level-4'><a class="ez-toc-link ez-toc-heading-6" href="#%D0%9E%D1%81%D0%BE%D0%B1%D0%B5%D0%BD%D0%BD%D0%BE%D1%81%D1%82%D0%B8" title="Особенности">Особенности</a></li></ul></li><li class='ez-toc-page-1 ez-toc-heading-level-3'><a class="ez-toc-link ez-toc-heading-7" href="#PyQt" title="PyQt">PyQt</a></li><li class='ez-toc-page-1 ez-toc-heading-level-3'><a class="ez-toc-link ez-toc-heading-8" href="#PySide" title="PySide">PySide</a></li></ul></li><li class='ez-toc-page-1 ez-toc-heading-level-2'><a class="ez-toc-link ez-toc-heading-9" href="#%D0%97%D0%BE%D0%BB%D0%BE%D1%82%D0%BE%D0%B9_%D1%81%D1%82%D0%B0%D0%BD%D0%B4%D0%B0%D1%80%D1%82_%E2%80%93_TKinter" title="Золотой стандарт – TKinter">Золотой стандарт – TKinter</a><ul class='ez-toc-list-level-3' ><li class='ez-toc-heading-level-3'><a class="ez-toc-link ez-toc-heading-10" href="#%D0%9E_%D1%87%D0%B5%D0%BC_%D0%BD%D1%83%D0%B6%D0%BD%D0%BE_%D0%BF%D0%BE%D0%BC%D0%BD%D0%B8%D1%82%D1%8C_%D1%80%D0%B0%D0%B7%D1%80%D0%B0%D0%B1%D0%BE%D1%82%D1%87%D0%B8%D0%BA%D1%83" title="О чем нужно помнить разработчику">О чем нужно помнить разработчику</a></li></ul></li><li class='ez-toc-page-1 ez-toc-heading-level-2'><a class="ez-toc-link ez-toc-heading-11" href="#%D0%9F%D0%B5%D1%80%D0%B2%D1%8B%D0%B9_%D0%BF%D1%80%D0%BE%D0%B5%D0%BA%D1%82_%D0%BD%D0%B0_TKinter" title="Первый проект на TKinter">Первый проект на TKinter</a><ul class='ez-toc-list-level-3' ><li class='ez-toc-heading-level-3'><a class="ez-toc-link ez-toc-heading-12" href="#%D0%97%D0%B0%D0%BF%D1%83%D1%81%D0%BA_Python_%D0%B8_%D0%B8%D0%BC%D0%BF%D0%BE%D1%80%D1%82_%D0%B1%D0%B8%D0%B1%D0%BB%D0%B8%D0%BE%D1%82%D0%B5%D0%BA%D0%B8" title="Запуск Python и импорт библиотеки">Запуск Python и импорт библиотеки</a></li><li class='ez-toc-page-1 ez-toc-heading-level-3'><a class="ez-toc-link ez-toc-heading-13" href="#%D0%A1%D0%BE%D0%B7%D0%B4%D0%B0%D0%BD%D0%B8%D0%B5_%D1%8D%D1%81%D0%BA%D0%B8%D0%B7%D0%B0_%D0%B8_%D0%BB%D0%BE%D0%B3%D0%B8%D0%BA%D0%B8" title="Создание эскиза и логики">Создание эскиза и логики</a></li><li class='ez-toc-page-1 ez-toc-heading-level-3'><a class="ez-toc-link ez-toc-heading-14" href="#%D0%A1%D0%BE%D0%B7%D0%B4%D0%B0%D0%BD%D0%B8%D0%B5_%D0%BE%D1%81%D0%BD%D0%BE%D0%B2%D0%BD%D0%BE%D0%B3%D0%BE_%D0%BE%D0%BA%D0%BD%D0%B0" title="Создание основного окна">Создание основного окна</a></li><li class='ez-toc-page-1 ez-toc-heading-level-3'><a class="ez-toc-link ez-toc-heading-15" href="#Frame_%D0%B8_%D0%BA%D0%BE%D0%BD%D1%82%D1%80%D0%BE%D0%BB%D1%8C_%D1%80%D0%B0%D1%81%D0%BF%D0%BE%D0%BB%D0%BE%D0%B6%D0%B5%D0%BD%D0%B8%D1%8F_%D0%BA%D0%BE%D0%BC%D0%BF%D0%BE%D0%BD%D0%B5%D0%BD%D1%82%D0%BE%D0%B2" title="Frame и контроль расположения компонентов">Frame и контроль расположения компонентов</a></li><li class='ez-toc-page-1 ez-toc-heading-level-3'><a class="ez-toc-link ez-toc-heading-16" href="#%D0%9F%D0%BE%D0%BB%D1%8F_%D0%B8_%D0%BA%D0%BD%D0%BE%D0%BF%D0%BA%D0%B8" title="Поля и кнопки">Поля и кнопки</a></li><li class='ez-toc-page-1 ez-toc-heading-level-3'><a class="ez-toc-link ez-toc-heading-17" href="#%D0%9F%D1%80%D0%BE%D0%B3%D1%80%D0%B0%D0%BC%D0%BC%D0%B8%D1%80%D0%BE%D0%B2%D0%B0%D0%BD%D0%B8%D0%B5_%D1%84%D1%83%D0%BD%D0%BA%D1%86%D0%B8%D0%B9" title="Программирование функций">Программирование функций</a></li></ul></li></ul></nav></div>
<p>Python – известный язык разработки, который может похвастаться не просто читабельным кодом и низким порогом вхождения, но и функциональностью. Он используется для написания самых разных программ – от десктопных до мобильных и консольных, от бизнес-приложений до небольших игр. Иногда выступает дополнительным инструментом разработчика.</p>
<p>При помощи Python, как говорит Google, можно писать и графические интерфейсы. Далее этот вопрос будет рассмотрен более подробно. Предстоит выяснить, что собой представляет GUI, для чего он нужен, как пишется на рассматриваемом языке программирования. Эта информация пригодится и начинающему разработчику, и уже опытному специалисту.</p>
<h2 class="wp-block-heading"><span class="ez-toc-section" id="GUI_%E2%80%93_%D1%8D%D1%82%D0%BE%E2%80%A6"></span>GUI – это…<span class="ez-toc-section-end"></span></h2>
<p>GUI (Graphical User Interface) – графический пользовательский интерфейс. Своеобразная оболочка программного обеспечения, с которой взаимодействует клиент при помощи клавиатуры и мыши. Форма интерфейса, которая, согласно Google, позволяет пользователям взаимодействовать с программным обеспечением при помощи аудио-индикаторов и графических иконок (кнопок).</p>
<p>Google указывает на то, что графический интерфейс появился как ответ на CLI (интерфейс командной строки), требующей знания команд и их набора с клавиатуры. С GUI пользователи сталкиваются каждый день, когда читают статьи и новости в браузерах, набирают текст в редакторах или играют в игры.</p>
<p>Противоположностью GUI является командная строка. Она позволяет управлять системой не через дружелюбный графический интерфейс, а при помощи специальных текстовых команд. Встретить такой вариант манипулирования системой (CLI) можно в MacOS (терминал), а также в Linux. В Windows подобные возможности тоже есть. Они представлены командной строкой.</p>
<h2 class="wp-block-heading"><span class="ez-toc-section" id="%D0%98%D0%BD%D1%81%D1%82%D1%80%D1%83%D0%BC%D0%B5%D0%BD%D1%82%D1%8B_%D1%80%D0%B0%D0%B7%D1%80%D0%B0%D0%B1%D0%BE%D1%82%D1%87%D0%B8%D0%BA%D0%B0"></span>Инструменты разработчика<span class="ez-toc-section-end"></span></h2>
<p>GUI Python написать можно несколькими способами. Пользовательскую оболочку для приложения редко создают «с нуля». У Питона имеются специальные инструменты, способствующие более быстрой ее разработке. Google называет их фреймворками и библиотеками. В них есть все, чтобы писать функциональные пользовательские окна (window).</p>
<p>Google выделяет следующие GUI-фреймворки и библиотеки:</p>
<ul>
<li>PyQt5;</li>
<li>Tkinter;</li>
<li>PySide2;</li>
<li>Kivy;</li>
<li>PySimpleGUI;</li>
<li>Eel;</li>
<li>wxPython;</li>
<li>PyGObject;</li>
<li>PyGu;</li>
<li>PyForms.</li>
</ul>
<p>Далее все перечисленные библиотеки будут рассмотрены более подробно. На наиболее известных и применяемых из них представлены наглядные примеры разработки user window для приложения.</p>
<h2 class="wp-block-heading"><span class="ez-toc-section" id="%D0%94%D0%BB%D1%8F_%D1%87%D0%B5%D0%B3%D0%BE_%D0%BD%D1%83%D0%B6%D0%BD%D1%8B_GUI-%D0%B1%D0%B8%D0%B1%D0%BB%D0%B8%D0%BE%D1%82%D0%B5%D0%BA%D0%B8"></span>Для чего нужны GUI-библиотеки<span class="ez-toc-section-end"></span></h2>
<p>Google описывает Python как один из самых известных и распространенных языков программирования. Он подойдет как для клиент-серверных моделей, так и для создания графических пользовательских интерфейсов. Чтобы не приходилось каждый раз писать одни и те же функциональности с нуля, были придуманы фреймворки и библиотеки.</p>
<p>GUI-библиотеки дают возможность написания персонализированных графических интерфейсов пользователя для совершенно разных приложений. С их помощью разработка программного обеспечения становится на порядок проще. Users Window получается при помощи упомянутых инструментов красивым, с интуитивно понятным интерфейсом. Библиотеки и фреймворки Python повышают интерактивность программы и ее функциональные возможности, а также способствуют облегченной обработке данных.</p>
<p>GUI-фреймворки активно используются для создания программ с графическим интерфейсом:</p>
<ul>
<li>графических редакторов;</li>
<li>видео-плееров;</li>
<li>аудио-плееров;</li>
<li>игр;</li>
<li>систем управления базами данных и других приложений.</li>
</ul>
<p>Иногда они применяются при веб-разработке сайтов – там, где для работы с пользователями необходимо обеспечить высокий уровень интерактивности.</p>
<h2 class="wp-block-heading"><span class="ez-toc-section" id="%D0%9A%D1%80%D0%B0%D1%82%D0%BA%D0%B8%D0%B9_%D0%BE%D0%B1%D0%B7%D0%BE%D1%80_%D1%84%D1%80%D0%B5%D0%B9%D0%BC%D0%B2%D0%BE%D1%80%D0%BA%D0%BE%D0%B2"></span>Краткий обзор фреймворков<span class="ez-toc-section-end"></span></h2>
<p>Google указывает на то, что у Python очень много библиотек для написания пользовательских интерфейсов любой сложности. Их основной список был представлен выше. Не все указанные библиотеки пригодятся разработчикам. Чтобы понимать, на что обратить внимание в первую очередь, нужно хотя бы поверхностно изучить каждый фреймворк.</p>
<p>Google описывает указанные продукты так:</p>
<ol>
<li>PyForms – кроссплатформенный инструмент разработчика. Google указывает, что он базируется на основе Qt. Позволяет создавать программное обеспечение с графическим интерфейсом через редактирование XML-документов.</li>
<li>PyGObject – GUI-библиотека, созданная на основе GObject Introspection. Позволяет создавать User Window с потрясающей графической оболочкой.</li>
<li>PyGU – работа с этим инструментом осуществляется при помощи SVG-графики. Он имеет понятный интерфейс и подойдет для написания любых интерактивных приложений с минимальными знаниями Питона.</li>
<li>PySimpleGUI – простейшая библиотека для написания user window. Ей очень удобно пользоваться. Все виджеты будут генерироваться за счет определенного набора методов и функций.</li>
<li>Eel – инструмент программиста для написания кроссплатформенных проектов на базе Electron или Flask. Поддерживает возможность работы с JavaScript, CSS и HTML в процессе формирования user window.</li>
<li>wxPython – еще один кроссплатформенный фреймворк. Разработан на базе C++. Поддерживает качественно реализованный API и дружественные пользовательские сообщества. Его достаточно легко освоить каждому программисту.</li>
<li>PySide2 – бесплатная библиотека, которая выступает альтернативой PyQt на основе Qt5. Поддерживает более свободную лицензию, чем PyQt. Функционально от «платной» версии инструмента практически ничем не отличается.</li>
<li>Kivy – кроссплатформенная GUI-библиотека Python. Используется для программирования мультимедийных приложений путем использования графики OpenGL ES 2.</li>
<li>PyQt5 – функциональный и кроссплатформенный инструмент разработчика для GUI. Google указывает на то, что он базируется на Qt и позволяет создавать мощные графические проекты. Обладает развернутой детализированной документацией.</li>
<li>Tkinter – стандартная Python-библиотека для GUI. Отличается простотой использования. На ней обычно пишут простые проекты.</li>
</ol>
<p>Google указывает на то, что углубленно изучать все перечисленные инструменты для того, чтобы сделать визуальное оформление программы на Питоне, необязательно. Далее более подробно будут изучены самые лучшие библиотеки для разработчиков GUI.</p>
<h3 class="wp-block-heading"><span class="ez-toc-section" id="Eel"></span>Eel<span class="ez-toc-section-end"></span></h3>
<p>Eel – модуль, помогающий создавать пользовательские интерфейсы (users windows). Он подойдет тем, кто предварительно изучил CSS и HTML. С его помощью чаще всего пишутся веб-интерфейсы, представленные самостоятельными программами. Примером использования Eel может послужить известный проект – Discord. Он написан на прародителе Eel – Electron.</p>
<figure class="wp-block-image"><img decoding="async" src="https://lh7-us.googleusercontent.com/DDeH8DqRRJ2rPBMyI_VJ4OpY8_lRJPFqpJ3yPo4iClPFdkYVEdNTjQsyRcjs-PlvYxpGJ7jTlpW15kXBWqJjpyfMGle5UGwH067LpUtzSn3egygrNHRMybA6XBrkw2Vr52rVc80WDLIXI0jsHraGnQ" alt="Питон и графический интерфейс"/></figure>
<p>Google указывает, что с помощью этого инструмента можно не только создавать красивые интерфейсы через CSS и HTML, но и обеспечивать динамическую анимацию. Для этого предстоит воспользоваться JavaScript.</p>
<h4 class="wp-block-heading"><span class="ez-toc-section" id="%D0%9E%D1%81%D0%BE%D0%B1%D0%B5%D0%BD%D0%BD%D0%BE%D1%81%D1%82%D0%B8"></span><em>Особенности</em><span class="ez-toc-section-end"></span></h4>
<p>Этот модуль создан на базе Chromium. Данная особенность может приводить к проблемам оптимизации и потребления оперативной памяти. В небольших проектах, как отмечает Google, этого недочета не заметно, а вот в масштабных приложениях – вполне.</p>
<p>Eel позволяет выигрывать в гибкости и упрощает разработку сложных адаптивных программ – для нее достаточно воспользоваться flexbox. Пример – если нужно написать приложение для просмотра и демонстрации больших таблиц, Eel допускает создание user window с HTML-фреймом Google Sheets.</p>
<p>Пользователь будет одновременно выполнять роль клиента и сервера. Eel запустит localhost:8000, а также откроет браузер (Chrome или Windows Edge) с флагом app, позволяющим задавать размер окна по умолчанию. Проекты компилируются через PyInstaller или Auto Py to EXE. После этого они могут распространяться в качестве исполняемых файлов (формата .exe).</p>
<h3 class="wp-block-heading"><span class="ez-toc-section" id="PyQt"></span>PyQt<span class="ez-toc-section-end"></span></h3>
<p>Модуль PyQt – профессиональный инструмент GUI-разработчика. Эта библиотека совмещается с билдером Qt Designer, который представлен набором готовых элементов интерфейса.</p>
<p>Google ссылается на то, что встроенных компонентов Qt у этого модуля всегда было достаточно, но некоторые из них могут некорректно срабатывать. Примером служит QTextBrowser. Этот компонент user window не способен считать сложный HTML-код вроде blockquote.</p>
<figure class="wp-block-image"><img decoding="async" src="https://lh7-us.googleusercontent.com/4jL691yBTtlxkhlhCWfBhhKhko-NCmf2GNnq_15Qa_T-Fd8nsFZ5vXx8xUjLvlMp0clKrivM2jaEKGx4SQdRlrqnMpy26T3yPQYPREpUA53vEgnxRT7gwr6RFRT8uzM7xRWNMnHdz9pZlZtXIdUFbA" alt="Питон и графический интерфейс"/></figure>
<p>Основным преимуществом PyQt Google называет наличие подробной документации. В ней грамотно описаны все интерфейсные элементы, их характеристики и типы данных. По этому инструменту снято множество видеоуроков и гайдов. PyQt доступна на коммерческой и бесплатной основе (по лицензии GPL).</p>
<h3 class="wp-block-heading"><span class="ez-toc-section" id="PySide"></span>PySide<span class="ez-toc-section-end"></span></h3>
<p>Пользовательское окно в Python можно создать при помощи PySide. Google называет этот инструмент библиотекой с открытым исходным кодом, поддерживающей связь с Qt. Qt – это кроссплатформенная разработка, UI-фреймворк для написания и развертывания приложений на разных операционных системах без предварительной переписи исходного кода.</p>
<p>PySide объединяет Qt и Python, предоставляя богатый набор инструментов для создания user window. Модуль подойдет не только для простых проектов, но и для достаточно сложных веб-сайтов.</p>
<h2 class="wp-block-heading"><span class="ez-toc-section" id="%D0%97%D0%BE%D0%BB%D0%BE%D1%82%D0%BE%D0%B9_%D1%81%D1%82%D0%B0%D0%BD%D0%B4%D0%B0%D1%80%D1%82_%E2%80%93_TKinter"></span>Золотой стандарт – TKinter<span class="ez-toc-section-end"></span></h2>
<p>Создание интерфейса в Python для пользователей – простая задача, если пользоваться специальными библиотеками и фреймворками рассматриваемого языка. Золотым стандартом и функциональным инструментом GUI-программистов Google называет TKinter. Это самый известный модуль. С его помощью можно программировать user window для:</p>
<ul>
<li>Linux;</li>
<li>Windows;</li>
<li>MacOS.</li>
</ul>
<p>Инструмент используется для получения кроссплатформенных и гибких проектов. Работа с TKinter может быть условно представлена в виде нескольких простейших шагов:</p>
<figure class="wp-block-image"><img decoding="async" src="https://lh7-us.googleusercontent.com/NJT3iIZ8gkk4wbyB91ONpWs8kpv1K63Buc_n6Y9s-5gbPqunyZvOKUhQSu3bZw-DisHgjMEVjoa6gT4gUI1-DUsPIBjl85EjSrPs0neIaiQ8AcStm49OIYWqV30uleLnzJeWKfbk9Pbk3NyR21gyhg" alt="Питон и графический интерфейс"/></figure>
<p>Процесс написания user window выглядит так:</p>
<ol>
<li>Сначала программисту необходимо подключить библиотеку. TKinter обладает простой установкой. Провести ее поможет директива import: import tkinter as.</li>
<li>Создать окно (window) приложения, в котором будут размещаться все необходимые графические составляющие.</li>
<li>Добавить необходимые виджеты. Это визуальные компоненты, используемые для выполнения тех или иных действий.</li>
<li>Создать основной цикл событий. Google относит сюда все события, происходящие при пользовательском взаимодействии с GUIS.</li>
</ol>
<p>Ключевыми объектами в работе TKinter Google называет виджеты. Они представляют собой своеобразные аналоги тегов HTML, которые дают возможность создания интерактивных и неинтерактивных элементов. Примерами могут послужить кнопки и надписи.</p>
<p>Google выделяет у рассматриваемой библиотеки всего 18 виджетов, но наиболее используемыми выступают следующие элементы:</p>
<ul>
<li>menu – виджет, помогающий создавать меню в window;</li>
<li>label – контейнер, в котором будет размещаться текст или картинка;</li>
<li>canvas – пространство, на котором рисуются графические фигуры;</li>
<li>entry – инструмент, обеспечивающий в user window поля ввода;</li>
<li>button – кнопки.</li>
</ul>
<p>Далее этот инструмент будет рассмотрен более подробно. С его помощью предстоит написать калькулятор расчета индекса массы тела. Это приложение обучит основам работы с библиотекой.</p>
<h3 class="wp-block-heading"><span class="ez-toc-section" id="%D0%9E_%D1%87%D0%B5%D0%BC_%D0%BD%D1%83%D0%B6%D0%BD%D0%BE_%D0%BF%D0%BE%D0%BC%D0%BD%D0%B8%D1%82%D1%8C_%D1%80%D0%B0%D0%B7%D1%80%D0%B0%D0%B1%D0%BE%D1%82%D1%87%D0%B8%D0%BA%D1%83"></span>О чем нужно помнить разработчику<span class="ez-toc-section-end"></span></h3>
<p>Google подчеркивает, что TKinter – простой и одновременно сложный инструмент для написания GUI-интерфейсов. При формировании масштабных пользовательских окон (window) могут возникнуть некоторые трудности: работать допустимо только с кодом, а механика размещения компонентов окажется не всегда очевидной.</p>
<p>Допустимо использование сетки grid, а также менеджеров геометрии – pack и place. Самый тяжелый этап Tkinter – это изучение соответствующих элементов разработки. Они особо важны для разработчиков, планирующих заниматься созданием адаптивных интерфейсов.</p>
<h2 class="wp-block-heading"><span class="ez-toc-section" id="%D0%9F%D0%B5%D1%80%D0%B2%D1%8B%D0%B9_%D0%BF%D1%80%D0%BE%D0%B5%D0%BA%D1%82_%D0%BD%D0%B0_TKinter"></span>Первый проект на TKinter<span class="ez-toc-section-end"></span></h2>
<p>GUI-интерфейс в Python (или users windows) можно создать при помощи библиотеки TKinter. Она используется как для крупных, так и для небольших проектов. Далее будет представлен процесс разработки user window для программы расчета индекса массы тела. Этот показатель оценивает наличие лишнего веса у человека, а также показывает наличие ожирения.</p>
<p>Для расчета ИМТ (индекса массы тела) необходимо воспользоваться формулой:</p>
<figure class="wp-block-image"><img decoding="async" src="https://lh7-us.googleusercontent.com/WTB_F-qXU9eTLIrHzdBA1AK7LzWqGf-HwJUTIl6lJf90pKuHeuAhANJTj-Lpdite3CwrshjEbhWEu2kNHBjtZBfoeY7mN61P30RXc-8os4QtKULY154tOQrEV9rvDYApxUQ1mFPkHjip1mftxJp_Sw" alt="Питон и графический интерфейс"/></figure>
<p>Результаты расчетов будут оцениваться по специальной таблице. У врачей она может быть представлена различными способами. В приложении предстоит воспользоваться элементарной версией:</p>
<figure class="wp-block-image"><img decoding="async" src="https://lh7-us.googleusercontent.com/5gjgECuXxuP71IpqeiNLRbV4Ob_g9TGexRhS6ccKFDhZAg7udpOTD6Rja0mu8bUWuW8Mi-PS-sHaBzKP7I-TGvv8c5luq5SpupauSMeeCNlLjfafDssy0JBXTov7kF1CJVJG00gIm1UFSqIu9LT_xA" alt="Питон и графический интерфейс"/></figure>
<p>Это – то, что должен учитывать программист перед непосредственной разработкой программного обеспечения для расчета ИМТ. Далее можно приступить к использованию TKinter и Python.</p>
<h3 class="wp-block-heading"><span class="ez-toc-section" id="%D0%97%D0%B0%D0%BF%D1%83%D1%81%D0%BA_Python_%D0%B8_%D0%B8%D0%BC%D0%BF%D0%BE%D1%80%D1%82_%D0%B1%D0%B8%D0%B1%D0%BB%D0%B8%D0%BE%D1%82%D0%B5%D0%BA%D0%B8"></span>Запуск Python и импорт библиотеки<span class="ez-toc-section-end"></span></h3>
<p>Google указывает на то, что любая PY-библиотека должна быть импортирована в проект. Писать код рекомендуется в специальной IDE. Пример – Visual Studio Code. Здесь есть подсветка синтаксиса, а также автоматическое предложение продолжения кода. Соответствующая функциональность значительно упрощает разработку.</p>
<p>TKinter, согласно Google, уже предустановлена в Python. Для ее использования предстоит лишь импортировать этот инструмент в проект:</p>
<figure class="wp-block-image"><img decoding="async" src="https://lh7-us.googleusercontent.com/B7fGxbliiASqMn1miVgUTMWJJI8Gzx0f5n3QXGeaof6iQ24-huLBp-RWIQy9IUj7yD3ARDm2DC0XqKZ2t4OMceuZkzRZadxa8qEN5iVSJ407Vgc_7n-ASU_T1wgNJwYoNOO1TNFHaL8L7zAQh3vHAw" alt="Питон и графический интерфейс"/></figure>
<p>Теперь можно заняться разработкой приложения и его user window.</p>
<h3 class="wp-block-heading"><span class="ez-toc-section" id="%D0%A1%D0%BE%D0%B7%D0%B4%D0%B0%D0%BD%D0%B8%D0%B5_%D1%8D%D1%81%D0%BA%D0%B8%D0%B7%D0%B0_%D0%B8_%D0%BB%D0%BE%D0%B3%D0%B8%D0%BA%D0%B8"></span>Создание эскиза и логики<span class="ez-toc-section-end"></span></h3>
<p>User Window нуждается в тщательной проработке перед реализацией в виде кода. Сначала разработчику нужно решить:</p>
<ul>
<li>какие данные и в каком виде требуется получить от пользователя;</li>
<li>какое событие в приложении отвечает за расчет индекса массы тел: нажатие на кнопку, получение приложением определенных данных или что-нибудь другое;</li>
<li>каким способом демонстрировать конечный результат.</li>
</ul>
<p>User Window в рассматриваемом проекте позволяет получить от пользователя рост и вес в виде простых чисел. Вес вводится в килограммах, рост – в сантиметрах. Индекс массы тела рассчитывается при нажатии на специальную кнопку. Результат произведенных расчетов выводится во всплывающем window в качестве значения индекса массы тела и категории, к которой он имеет непосредственное отношение.</p>
<figure class="wp-block-image"><img decoding="async" src="https://lh7-us.googleusercontent.com/9s2klZ70I3mvCy0rEm07sDFqZVWGJlbQ65J9cPx11X1CkyHP14E5KM6qm_9E9OGPihVhDTpR4Z4C8X3E2WDVA8xmg4eeSG6V2knUt6TxAfrD2NuDVuLeOiuBpb_yeMIYNlmA-17XcFGWR-ow3oO0pg" alt="Питон и графический интерфейс"/></figure>
<p>Выше – наглядный пример того, как будет выглядеть app window. Это элементарный пример интерфейса.</p>
<h3 class="wp-block-heading"><span class="ez-toc-section" id="%D0%A1%D0%BE%D0%B7%D0%B4%D0%B0%D0%BD%D0%B8%D0%B5_%D0%BE%D1%81%D0%BD%D0%BE%D0%B2%D0%BD%D0%BE%D0%B3%D0%BE_%D0%BE%D0%BA%D0%BD%D0%B0"></span>Создание основного окна<span class="ez-toc-section-end"></span></h3>
<p>Создание GUI на Python начинается с импорта библиотеки и загрузки ее методов:</p>
<figure class="wp-block-image"><img decoding="async" src="https://lh7-us.googleusercontent.com/Hrw2TY7jvO7ozOZhI7ljotjFfTqQJE82YdHZnxj9AeGlyiwRX1gsrKQ6oicqk1yoA32FkuuqF4b7q-Wtc9fYQC5ekhZBamv2sYP49JPPbjBgI4nMOqfT0tMb4uyO-zvJZhkXXKWOrvrGafn7wLzusw" alt="Питон и графический интерфейс"/></figure>
<p>Здесь первая строка дает возможность загрузки методов TKinter, а затем пользоваться ими в процессе написания исходного кода без ссылки на их именования. Вторая строка поддерживает явный импорт метода messagebox. Он используется для вывода всплывающего окна (result window) в качестве ответа на пользовательские действия. Этот прием является удобным, потому что упомянутый метод в исходном приложении потребуется несколько раз.</p>
<p>Теперь можно создать окно приложения (app window). Для этой цели рекомендуется использовать модуль TK. Программа будет называться «Калькулятор индекса массы тела (ИМТ)»:</p>
<figure class="wp-block-image"><img decoding="async" src="https://lh7-us.googleusercontent.com/8T5PD-w_HH8j7cFVVCoeSd3vaZx44Bz8xyJaKdxXUAkGpaoIop8Slufwd8KWT1gpJj1DOsoA6whtL4Kx_Hpe64QXeAZCdfC7gqvGCGX22gnWws4WGd5YyKbnAkfXbvdvz8aw882cYYMl1vHO1Mm_0A" alt="Питон и графический интерфейс"/></figure>
<p>После запуска предложенного фрагмента ничего не произойдет. Такое поведение Google не называет ошибочным. На самом деле код будет выполнен, а app window после этого закроется. Для устранения ситуации нужно явно указать, что окно программы не должно закрываться до тех пор, пока пользователь сам не инициирует соответствующий процесс. Google говорит о том, что к исходному коду нужно добавить функцию window.mainloop, указывающую на запуск цикла событий:</p>
<figure class="wp-block-image"><img decoding="async" src="https://lh7-us.googleusercontent.com/mD4rAe1dV7caZVY64UAl_R7KGDLvLlp5wHQ2msvqF9YJW1-TJHVyYFhzpIxud6798wAjTxP5m6_73EJGh7c9k_1uxw__MiXqfX25FFP3aXGT6q73QxCXSYZA63RW2Jk9asyIdl8r0lTOpR921Qk86w" alt="Питон и графический интерфейс"/></figure>
<p>Чтобы окно поместилось на экране, рекомендуется воспользоваться методом geometry. Он используется для задания размера окна программы:</p>
<figure class="wp-block-image"><img decoding="async" src="https://lh7-us.googleusercontent.com/lDGU9u2qzmNNksZ_Jbtx87Q-qXvF2TlEsQLLs10PXQbqwQdfFsaz-DqgDfWPr8VHmMsjrv3Vbo-BOixksE1KlCA1FcY4-kX4feFs-vIKFZFCZ0xmDm2NRYGHTJmg3HdcaZ7ELotvqqBrgqKnwAT36Q" alt="Питон и графический интерфейс"/></figure>
<p>Теперь можно заняться контролем расположения компонентов программного обеспечения.</p>
<h3 class="wp-block-heading"><span class="ez-toc-section" id="Frame_%D0%B8_%D0%BA%D0%BE%D0%BD%D1%82%D1%80%D0%BE%D0%BB%D1%8C_%D1%80%D0%B0%D1%81%D0%BF%D0%BE%D0%BB%D0%BE%D0%B6%D0%B5%D0%BD%D0%B8%D1%8F_%D0%BA%D0%BE%D0%BC%D0%BF%D0%BE%D0%BD%D0%B5%D0%BD%D1%82%D0%BE%D0%B2"></span>Frame и контроль расположения компонентов<span class="ez-toc-section-end"></span></h3>
<p>В app window нужно разместить несколько элементов с получившегося ранее эскиза: два поля ввода данных с характерными подписями, а также одну кнопку. Требуется следить, чтобы эти компоненты не накладывались друг на друга и не уходили за пределы app window. Google указывает, что в TKinter для контроля за элементами есть разные методы:</p>
<ol>
<li>Pack – применяется при работе с контейнерами для элементов. Дает возможность позиционировать кнопки, надписи и другие графические компоненты внутри контейнеров.</li>
<li>Place – используется для позиционирования по точным координатам.</li>
<li>Grid – применяется для размещения элементов по ячейкам словной сетки. Она будет служить разделителем окна программы.</li>
</ol>
<p>Далее будут использованы grid и pack. Для начала нужно создать виджет Frame – в нем размещаются надписи, поля ввода и кнопки. Отступы по горизонтали и вертикали будут 10 пикселей:</p>
<figure class="wp-block-image"><img decoding="async" src="https://lh7-us.googleusercontent.com/jjvhJUo3-QhRrJDi4o40LcqUtdxVFBd9B939f2o1nBngWuA_B2VgWh_AIik2jn8uOs6y8c619hWnBeJ_MlkfyzmdgODff5at0rDHYgSzMnSSCZI-uO0rlX7FRE8hxSxqf8BVpNyXzMethQrdV7YGEA" alt="Питон и графический интерфейс"/></figure>
<p>Выше – фрагмент программного кода, который нужно добавить в свой проект.</p>
<h3 class="wp-block-heading"><span class="ez-toc-section" id="%D0%9F%D0%BE%D0%BB%D1%8F_%D0%B8_%D0%BA%D0%BD%D0%BE%D0%BF%D0%BA%D0%B8"></span>Поля и кнопки<span class="ez-toc-section-end"></span></h3>
<p>Следующий этап разработки – это добавление в окне приложения (app window) трех видов виджетов:</p>
<ul>
<li>поле ввода данных (Entry);</li>
<li>текстовые надписи (Label);</li>
<li>кнопку (Button).</li>
</ul>
<p>Google указывает на то, что надписи создаются через Label-виджет:</p>
<figure class="wp-block-image"><img decoding="async" src="https://lh7-us.googleusercontent.com/B3VIa35Eu8tJqoV8DyDtIlOoYkAtBqCfnT05NXXTJnp-bCwOtgammMBBTq8LeGGPFgWK4ECPPEi_UsS28dr4Kw6jlmZbJS28yRDc2DoVf6aeqBGTz9n38iJ-zGmjC36anR0G026BUT28-ZzeBYwg6A" alt="Питон и графический интерфейс"/></figure>
<p>Ему передаются два параметра:</p>
<ol>
<li>Frame – используется заготовка виджета Frame. В нем уже имеются настройки для отступов по вертикали и горизонтали.</li>
<li>Text – текст, который выводится на экран app window.</li>
</ol>
<p>Для позиционирования Google рекомендует использовать grid-метод. Предстоит указать, что текст должен располагаться в ячейке с координатами «третья строка и первый столбец». При запуске программы надпись отобразится по центру. Нужное положение будет принято после добавления других компонентов.</p>
<p>Теперь можно добавить вторую надпись, но при позиционировании в grid указывается 4-я строка:</p>
<figure class="wp-block-image"><img decoding="async" src="https://lh7-us.googleusercontent.com/Q0ggLV8RYU7dCMzd7jm467tuJkSkjBsJowEMbkPVtsy_Cd0d5_VLkzzGnoDHo8T8QyDR8aIPVQF_0LJC2kVriteRH0wiEsok2fK8SVUt4X10oAGNQfUQScIoHU2YzGzZccQeui3qXpBzglRYZpqYuQ" alt="Питон и графический интерфейс"/></figure>
<p>Поля ввода пользовательской информации добавляются, согласно Google, через Entry:</p>
<figure class="wp-block-image"><img decoding="async" src="https://lh7-us.googleusercontent.com/huMrt4uwp5TleZyKWkLrdoPYmAeSR2-iMezkzrSaSlOkNql_KCY82YwD_nN61MKW86-blNK9RadHwegewxhXAFjMV8r_zyFnRGOSSzbccJqOkL02JZcp8I_5DHfQP9DsfbzuTSk1-KlpAzz1NBIcVg" alt="Питон и графический интерфейс"/></figure>
<p>Для позиционирования здесь тоже используется метод grid. Entry должен быть расположен около надписи «Введите свой рост». Это приводит к тому, что нужно использовать ячейку в той же строке, но в другом столбце. Остается добавить поле ввода веса:</p>
<figure class="wp-block-image"><img decoding="async" src="https://lh7-us.googleusercontent.com/CsFCjz_Emn9IkB2dQmsYv2G17qREnI7NbS2ZT6jn4Qi5s8m9j-Ngk_7po3_N5RBqflU4xUdGkdHtN1dBAUAyoiS5dZZ4b6nBG5x5xF-2TKz1tn8PHufKxrIhrQZ_Mn0nkg7DcEHiID4BppfXrhPylA" alt="Питон и графический интерфейс"/></figure>
<p>А вот принцип добавления кнопки, которая отвечает за расчет индекса массы тела:</p>
<figure class="wp-block-image"><img decoding="async" src="https://lh7-us.googleusercontent.com/4trJRseI-Qvu7vm9YxND1WSc4rTyysigvVqppZSTH_z3ZSIF_vh6_k6A0DWAhmBuOMeJeiXrhfcPJx40xiW9mBRyH-PTI3jfVk2fL5MBlOG3M0igdveU0fSe7vCz_k0TNHdjDLiziOmCdm3OFXTSVg" alt="Питон и графический интерфейс"/></figure>
<p>Графическое приложение на Python почти готово. Остается написать код, который будет отвечать за получение данных из Entry и рассчитывать ИМТ.</p>
<h3 class="wp-block-heading"><span class="ez-toc-section" id="%D0%9F%D1%80%D0%BE%D0%B3%D1%80%D0%B0%D0%BC%D0%BC%D0%B8%D1%80%D0%BE%D0%B2%D0%B0%D0%BD%D0%B8%D0%B5_%D1%84%D1%83%D0%BD%D0%BA%D1%86%D0%B8%D0%B9"></span>Программирование функций<span class="ez-toc-section-end"></span></h3>
<p>Google указывает на то, что для расчетов используется функция calculate:</p>
<figure class="wp-block-image"><img decoding="async" src="https://lh7-us.googleusercontent.com/ifaJE2zh62S2ZubB5fX-8_brzLya-TQax7yfLxCsiwwZmyVrXOQpwW36KPAqP7DfSY3l9btdqAzyvIPpsGPQfBEwDzkmVjniQMH0hOB0GeYIW6m7F0kbSUx8NDDvIOS5syYVACCf1XsU-a9mNLFK-A" alt="Питон и графический интерфейс"/></figure>
<p>Для вывода результата пользователю на экран эта команда дополняется условным оператором if. Он поможет учесть полученные значения индекса массы тела. В TKinter есть messagebox, который используется для отображения сообщения о всплывающем окне:</p>
<figure class="wp-block-image"><img decoding="async" src="https://lh7-us.googleusercontent.com/ac_iO9SNnQU5UM2AB5oCNyldgurgH5Zhqipc7XTmGkmjHMw0JIx2qXmv9idMI_gT2r_YwZipxGRhSRyZBfo29ffaE0pI4kXBoEflmou2mrehVWOt_mF-rHZbRhzFUWHeEoI8PlBjz3EqUWab5RHVkA" alt="Питон и графический интерфейс"/></figure>
<p>Завершающий этап – привязка расчетов к нажатию по кнопке «Рассчитать ИМТ». Для этого Google требует использования свойства command в виджете Button:</p>
<figure class="wp-block-image"><img decoding="async" src="https://lh7-us.googleusercontent.com/34jhjmeaTkowQgNw_MH6g88_68FVHprSLAADvs34Phs0EqNblVYFb5d5jvEgNHAkvWB_nr4A35ca3TgDUDDHTiSRXZ-aS4JPv7mZwuviW-NHmvaI5nIIx8RP8uynhD9jREqdXUlKTQU75tbcwAyNpw" alt="Питон и графический интерфейс"/></figure>
<p>Графический интерфейс на Python и простейшее первое приложение на TKinter готовы.<br><br>Интересует <a href="https://otus.ru/lessons/python-professional/?utm_source=oj&utm_medium=affilate&utm_campaign=python" title="" data-wpel-link="external" target="_blank" rel="nofollow external noopener noreferrer" class="wpel-icon-right">Python<span class="wpel-icon wpel-image wpel-icon-6"></span></a>? Добро пожаловать на курс в Otus!</p>
</div><!-- .post-content -->
<div class="the-post-foot cf">
<div class="tag-share cf">
<div class="post-tags"><a href="https://otus.ru/journal/tag/python/" rel="tag" data-wpel-link="internal">Python</a></div>
<div class="post-share">
<div class="post-share-icons cf">
<span class="counters">
</span>
<a href="https://www.facebook.com/sharer.php?u=https%3A%2F%2Fotus.ru%2Fjournal%2Fpiton-i-graficheskij-interfejs%2F" class="link facebook wpel-icon-right" target="_blank" title="Share on Facebook" data-wpel-link="external" rel="nofollow external noopener noreferrer"><i class="fa fa-facebook"></i><span class="wpel-icon wpel-image wpel-icon-6"></span></a>
<a href="https://twitter.com/intent/tweet?url=https%3A%2F%2Fotus.ru%2Fjournal%2Fpiton-i-graficheskij-interfejs%2F&text=%D0%9F%D0%B8%D1%82%D0%BE%D0%BD%20%D0%B8%20%D0%B3%D1%80%D0%B0%D1%84%D0%B8%D1%87%D0%B5%D1%81%D0%BA%D0%B8%D0%B9%20%D0%B8%D0%BD%D1%82%D0%B5%D1%80%D1%84%D0%B5%D0%B9%D1%81" class="link twitter wpel-icon-right" target="_blank" title="Share on Twitter" data-wpel-link="external" rel="nofollow external noopener noreferrer"><i class="fa fa-twitter"></i><span class="wpel-icon wpel-image wpel-icon-6"></span></a>
<a href="https://www.linkedin.com/shareArticle?mini=true&url=https%3A%2F%2Fotus.ru%2Fjournal%2Fpiton-i-graficheskij-interfejs%2F" class="link linkedin wpel-icon-right" target="_blank" title="LinkedIn" data-wpel-link="external" rel="nofollow external noopener noreferrer"><i class="fa fa-linkedin"></i><span class="wpel-icon wpel-image wpel-icon-6"></span></a>
<a href="https://pinterest.com/pin/create/button/?url=https%3A%2F%2Fotus.ru%2Fjournal%2Fpiton-i-graficheskij-interfejs%2F&media=https%3A%2F%2Fotus.ru%2Fjournal%2Fwp-content%2Fuploads%2F2023%2F11%2Foj-1080x72038-1.jpg&description=%D0%9F%D0%B8%D1%82%D0%BE%D0%BD%20%D0%B8%20%D0%B3%D1%80%D0%B0%D1%84%D0%B8%D1%87%D0%B5%D1%81%D0%BA%D0%B8%D0%B9%20%D0%B8%D0%BD%D1%82%D0%B5%D1%80%D1%84%D0%B5%D0%B9%D1%81" class="link pinterest wpel-icon-right" target="_blank" title="Pinterest" data-wpel-link="external" rel="nofollow external noopener noreferrer"><i class="fa fa-pinterest-p"></i><span class="wpel-icon wpel-image wpel-icon-6"></span></a>
</div>
</div>
</div>
</div>
<div class="post-nav">
<div class="post previous cf">
<a href="https://otus.ru/journal/gps-opisanie-princip-raboty-alternativy/" title="Prev Post" class="nav-icon" data-wpel-link="internal">
<i class="fa fa-angle-left"></i>
</a>
<span class="content">
<a href="https://otus.ru/journal/gps-opisanie-princip-raboty-alternativy/" class="image-link" rel="previous" data-wpel-link="internal">
<img width="150" height="106" src="data:image/svg+xml,%3Csvg%20viewBox%3D%270%200%20150%20106%27%20xmlns%3D%27http%3A%2F%2Fwww.w3.org%2F2000%2Fsvg%27%3E%3C%2Fsvg%3E" class="attachment-thumbnail size-thumbnail lazyload wp-post-image" alt="GPS: описание, принцип работы, альтернативы" decoding="async" data-srcset="https://otus.ru/journal/wp-content/uploads/2023/11/oj-1080x72037-1-150x106.jpg 150w, https://otus.ru/journal/wp-content/uploads/2023/11/oj-1080x72037-1-300x212.jpg 300w, https://otus.ru/journal/wp-content/uploads/2023/11/oj-1080x72037-1-1024x724.jpg 1024w, https://otus.ru/journal/wp-content/uploads/2023/11/oj-1080x72037-1-768x543.jpg 768w, https://otus.ru/journal/wp-content/uploads/2023/11/oj-1080x72037-1-1536x1086.jpg 1536w" data-src="https://otus.ru/journal/wp-content/uploads/2023/11/oj-1080x72037-1-150x106.jpg" data-sizes="(max-width: 150px) 100vw, 150px" title="GPS: описание, принцип работы, альтернативы" /> </a>
<div class="post-meta">
<span class="label">Prev Post</span>
<div class="post-meta post-meta-b">
<h2 class="post-title">
<a href="https://otus.ru/journal/gps-opisanie-princip-raboty-alternativy/" data-wpel-link="internal">GPS: описание, принцип работы, альтернативы</a>
</h2>
<div class="below">
<a href="https://otus.ru/journal/gps-opisanie-princip-raboty-alternativy/" class="meta-item date-link" data-wpel-link="internal"><time class="post-date" datetime="2023-11-15T20:29:59+00:00">15 ноября, 2023</time></a>
<span class="meta-sep"></span>
<span class="meta-item read-time">12 Mins Read</span>
</div>
</div> </div>
</span>
</div>
<div class="post next cf">
<a href="https://otus.ru/journal/html-opisanie-harakteristika-primery/" title="Next Post" class="nav-icon" data-wpel-link="internal">
<i class="fa fa-angle-right"></i>
</a>
<span class="content">
<a href="https://otus.ru/journal/html-opisanie-harakteristika-primery/" class="image-link" rel="next" data-wpel-link="internal">
<img width="150" height="106" src="data:image/svg+xml,%3Csvg%20viewBox%3D%270%200%20150%20106%27%20xmlns%3D%27http%3A%2F%2Fwww.w3.org%2F2000%2Fsvg%27%3E%3C%2Fsvg%3E" class="attachment-thumbnail size-thumbnail lazyload wp-post-image" alt="HTML: описание, характеристика, примеры" decoding="async" data-srcset="https://otus.ru/journal/wp-content/uploads/2023/11/oj-1080x72039-1-150x106.jpg 150w, https://otus.ru/journal/wp-content/uploads/2023/11/oj-1080x72039-1-300x212.jpg 300w, https://otus.ru/journal/wp-content/uploads/2023/11/oj-1080x72039-1-1024x724.jpg 1024w, https://otus.ru/journal/wp-content/uploads/2023/11/oj-1080x72039-1-768x543.jpg 768w, https://otus.ru/journal/wp-content/uploads/2023/11/oj-1080x72039-1-1536x1086.jpg 1536w" data-src="https://otus.ru/journal/wp-content/uploads/2023/11/oj-1080x72039-1-150x106.jpg" data-sizes="(max-width: 150px) 100vw, 150px" title="HTML: описание, характеристика, примеры" /> </a>
<div class="post-meta">
<span class="label">Next Post</span>
<div class="post-meta post-meta-b">
<h2 class="post-title">
<a href="https://otus.ru/journal/html-opisanie-harakteristika-primery/" data-wpel-link="internal">HTML: описание, характеристика, примеры</a>
</h2>
<div class="below">
<a href="https://otus.ru/journal/html-opisanie-harakteristika-primery/" class="meta-item date-link" data-wpel-link="internal"><time class="post-date" datetime="2023-11-15T21:11:16+00:00">15 ноября, 2023</time></a>
<span class="meta-sep"></span>
<span class="meta-item read-time">7 Mins Read</span>
</div>
</div> </div>
</span>
</div>
</div>
<section class="related-posts grid-3">
<h4 class="section-head"><span class="title">Читать ещё</span></h4>
<div class="ts-row posts cf">
<article class="post col-4">
<a href="https://otus.ru/journal/uroven-gotovnosti-cto-k-2026/" title="Уровень готовности CTO к 2026" class="image-link" data-wpel-link="internal">
<img width="270" height="180" src="data:image/svg+xml,%3Csvg%20viewBox%3D%270%200%20270%20180%27%20xmlns%3D%27http%3A%2F%2Fwww.w3.org%2F2000%2Fsvg%27%3E%3C%2Fsvg%3E" class="image lazyload wp-post-image" alt="Уровень готовности CTO к 2026" title="Уровень готовности CTO к 2026" decoding="async" loading="lazy" data-srcset="https://otus.ru/journal/wp-content/uploads/2025/11/oj-1080x720-kopiya-3-270x180.jpg 270w, https://otus.ru/journal/wp-content/uploads/2025/11/oj-1080x720-kopiya-3-770x515.jpg 770w, https://otus.ru/journal/wp-content/uploads/2025/11/oj-1080x720-kopiya-3-370x245.jpg 370w" data-src="https://otus.ru/journal/wp-content/uploads/2025/11/oj-1080x720-kopiya-3-270x180.jpg" data-sizes="(max-width: 270px) 100vw, 270px" /> </a>
<div class="content">
<h3 class="post-title"><a href="https://otus.ru/journal/uroven-gotovnosti-cto-k-2026/" class="post-link" data-wpel-link="internal">Уровень готовности CTO к 2026</a></h3>
<div class="post-meta">
<time class="post-date" datetime="2025-11-16T19:50:59+00:00">16 ноября, 2025</time>
</div>
</div>
</article >
<article class="post col-4">
<a href="https://otus.ru/journal/novye-uroki-noyabrya-tolko-top-temy-po-programmirovaniju/" title="Новые уроки ноября: только топ-темы по программированию" class="image-link" data-wpel-link="internal">
<img width="270" height="180" src="data:image/svg+xml,%3Csvg%20viewBox%3D%270%200%20270%20180%27%20xmlns%3D%27http%3A%2F%2Fwww.w3.org%2F2000%2Fsvg%27%3E%3C%2Fsvg%3E" class="image lazyload wp-post-image" alt="Новые уроки ноября: только топ-темы по программированию" title="Новые уроки ноября: только топ-темы по программированию" decoding="async" loading="lazy" data-srcset="https://otus.ru/journal/wp-content/uploads/2025/11/oj-1080x720-kopiya-2-270x180.jpg 270w, https://otus.ru/journal/wp-content/uploads/2025/11/oj-1080x720-kopiya-2-770x515.jpg 770w, https://otus.ru/journal/wp-content/uploads/2025/11/oj-1080x720-kopiya-2-370x245.jpg 370w" data-src="https://otus.ru/journal/wp-content/uploads/2025/11/oj-1080x720-kopiya-2-270x180.jpg" data-sizes="(max-width: 270px) 100vw, 270px" /> </a>
<div class="content">
<h3 class="post-title"><a href="https://otus.ru/journal/novye-uroki-noyabrya-tolko-top-temy-po-programmirovaniju/" class="post-link" data-wpel-link="internal">Новые уроки ноября: только топ-темы по программированию</a></h3>
<div class="post-meta">
<time class="post-date" datetime="2025-11-09T23:24:11+00:00">9 ноября, 2025</time>
</div>
</div>
</article >
<article class="post col-4">
<a href="https://otus.ru/journal/schjot-idjot-na-chasy/" title="Счёт идёт на часы" class="image-link" data-wpel-link="internal">
<img width="270" height="180" src="data:image/svg+xml,%3Csvg%20viewBox%3D%270%200%20270%20180%27%20xmlns%3D%27http%3A%2F%2Fwww.w3.org%2F2000%2Fsvg%27%3E%3C%2Fsvg%3E" class="image lazyload wp-post-image" alt="Счёт идёт на часы" title="Счёт идёт на часы" decoding="async" loading="lazy" data-srcset="https://otus.ru/journal/wp-content/uploads/2025/10/oj-1080x720-kopiya-7-270x180.png 270w, https://otus.ru/journal/wp-content/uploads/2025/10/oj-1080x720-kopiya-7-770x515.png 770w, https://otus.ru/journal/wp-content/uploads/2025/10/oj-1080x720-kopiya-7-370x245.png 370w" data-src="https://otus.ru/journal/wp-content/uploads/2025/10/oj-1080x720-kopiya-7-270x180.png" data-sizes="(max-width: 270px) 100vw, 270px" /> </a>
<div class="content">
<h3 class="post-title"><a href="https://otus.ru/journal/schjot-idjot-na-chasy/" class="post-link" data-wpel-link="internal">Счёт идёт на часы</a></h3>
<div class="post-meta">
<time class="post-date" datetime="2025-10-30T15:04:59+00:00">30 октября, 2025</time>
</div>
</div>
</article >
</div>
</section>
</article> <!-- .the-post -->
</div>
<aside class="col-4 sidebar">
<div class="inner">
<ul>
<li id="search-2" class="widget widget_search"><h5 class="widget-title"><span>Поиск по блогу</span></h5>
<form method="get" class="search-form" action="https://otus.ru/journal/">
<label>
<span class="screen-reader-text">Search for:</span>
<input type="search" class="search-field" placeholder="Введите запрос и нажмите Enter" value="" name="s" title="Search for:" />
</label>
<button type="submit" class="search-submit"><i class="fa fa-search"></i></button>
</form>
</li>
<li id="tag_cloud-5" class="widget widget_tag_cloud"><h5 class="widget-title"><span>Метки</span></h5><div class="tagcloud"><a href="https://otus.ru/journal/tag/android-2/" class="tag-cloud-link tag-link-74 tag-link-position-1" style="font-size: 12.472222222222pt;" aria-label="Android (34 элемента)" data-wpel-link="internal">Android</a>
<a href="https://otus.ru/journal/tag/c-3/" class="tag-cloud-link tag-link-91 tag-link-position-2" style="font-size: 10.916666666667pt;" aria-label="C (23 элемента)" data-wpel-link="internal">C</a>
<a href="https://otus.ru/journal/tag/c-2/" class="tag-cloud-link tag-link-81 tag-link-position-3" style="font-size: 12.666666666667pt;" aria-label="C# (35 элементов)" data-wpel-link="internal">C#</a>
<a href="https://otus.ru/journal/tag/c/" class="tag-cloud-link tag-link-20 tag-link-position-4" style="font-size: 12.472222222222pt;" aria-label="c++ (34 элемента)" data-wpel-link="internal">c++</a>
<a href="https://otus.ru/journal/tag/computer-science/" class="tag-cloud-link tag-link-209 tag-link-position-5" style="font-size: 15.972222222222pt;" aria-label="computer science (78 элементов)" data-wpel-link="internal">computer science</a>
<a href="https://otus.ru/journal/tag/css/" class="tag-cloud-link tag-link-288 tag-link-position-6" style="font-size: 8.6805555555556pt;" aria-label="CSS (13 элементов)" data-wpel-link="internal">CSS</a>
<a href="https://otus.ru/journal/tag/data-science/" class="tag-cloud-link tag-link-151 tag-link-position-7" style="font-size: 8pt;" aria-label="Data Science (11 элементов)" data-wpel-link="internal">Data Science</a>
<a href="https://otus.ru/journal/tag/devops/" class="tag-cloud-link tag-link-98 tag-link-position-8" style="font-size: 10.138888888889pt;" aria-label="devops (19 элементов)" data-wpel-link="internal">devops</a>
<a href="https://otus.ru/journal/tag/docker/" class="tag-cloud-link tag-link-143 tag-link-position-9" style="font-size: 8.2916666666667pt;" aria-label="Docker (12 элементов)" data-wpel-link="internal">Docker</a>
<a href="https://otus.ru/journal/tag/gamedev/" class="tag-cloud-link tag-link-25 tag-link-position-10" style="font-size: 11.694444444444pt;" aria-label="gamedev (28 элементов)" data-wpel-link="internal">gamedev</a>
<a href="https://otus.ru/journal/tag/hr/" class="tag-cloud-link tag-link-103 tag-link-position-11" style="font-size: 8pt;" aria-label="hr (11 элементов)" data-wpel-link="internal">hr</a>
<a href="https://otus.ru/journal/tag/html/" class="tag-cloud-link tag-link-217 tag-link-position-12" style="font-size: 11.208333333333pt;" aria-label="HTML (25 элементов)" data-wpel-link="internal">HTML</a>
<a href="https://otus.ru/journal/tag/ios/" class="tag-cloud-link tag-link-101 tag-link-position-13" style="font-size: 8.9722222222222pt;" aria-label="iOS (14 элементов)" data-wpel-link="internal">iOS</a>
<a href="https://otus.ru/journal/tag/it/" class="tag-cloud-link tag-link-50 tag-link-position-14" style="font-size: 10.527777777778pt;" aria-label="IT (21 элемент)" data-wpel-link="internal">IT</a>
<a href="https://otus.ru/journal/tag/java/" class="tag-cloud-link tag-link-75 tag-link-position-15" style="font-size: 15.680555555556pt;" aria-label="Java (73 элемента)" data-wpel-link="internal">Java</a>
<a href="https://otus.ru/journal/tag/javascript/" class="tag-cloud-link tag-link-83 tag-link-position-16" style="font-size: 14.319444444444pt;" aria-label="JavaScript (53 элемента)" data-wpel-link="internal">JavaScript</a>
<a href="https://otus.ru/journal/tag/linux/" class="tag-cloud-link tag-link-141 tag-link-position-17" style="font-size: 11.888888888889pt;" aria-label="Linux (29 элементов)" data-wpel-link="internal">Linux</a>
<a href="https://otus.ru/journal/tag/machine-learning/" class="tag-cloud-link tag-link-167 tag-link-position-18" style="font-size: 8.6805555555556pt;" aria-label="Machine Learning (13 элементов)" data-wpel-link="internal">Machine Learning</a>
<a href="https://otus.ru/journal/tag/otus-book/" class="tag-cloud-link tag-link-261 tag-link-position-19" style="font-size: 9.9444444444444pt;" aria-label="otus book (18 элементов)" data-wpel-link="internal">otus book</a>
<a href="https://otus.ru/journal/tag/php/" class="tag-cloud-link tag-link-45 tag-link-position-20" style="font-size: 10.527777777778pt;" aria-label="PHP (21 элемент)" data-wpel-link="internal">PHP</a>
<a href="https://otus.ru/journal/tag/python/" class="tag-cloud-link tag-link-27 tag-link-position-21" style="font-size: 16.944444444444pt;" aria-label="Python (99 элементов)" data-wpel-link="internal">Python</a>
<a href="https://otus.ru/journal/tag/qa/" class="tag-cloud-link tag-link-155 tag-link-position-22" style="font-size: 11.402777777778pt;" aria-label="qa (26 элементов)" data-wpel-link="internal">qa</a>
<a href="https://otus.ru/journal/tag/sql/" class="tag-cloud-link tag-link-38 tag-link-position-23" style="font-size: 12.861111111111pt;" aria-label="SQL (37 элементов)" data-wpel-link="internal">SQL</a>
<a href="https://otus.ru/journal/tag/team-lead/" class="tag-cloud-link tag-link-364 tag-link-position-24" style="font-size: 9.9444444444444pt;" aria-label="team lead (18 элементов)" data-wpel-link="internal">team lead</a>
<a href="https://otus.ru/journal/tag/unity/" class="tag-cloud-link tag-link-24 tag-link-position-25" style="font-size: 8pt;" aria-label="unity (11 элементов)" data-wpel-link="internal">unity</a>
<a href="https://otus.ru/journal/tag/algoritmy/" class="tag-cloud-link tag-link-30 tag-link-position-26" style="font-size: 9.9444444444444pt;" aria-label="Алгоритмы (18 элементов)" data-wpel-link="internal">Алгоритмы</a>
<a href="https://otus.ru/journal/tag/bazy-dannyh/" class="tag-cloud-link tag-link-40 tag-link-position-27" style="font-size: 10.138888888889pt;" aria-label="Базы данных (19 элементов)" data-wpel-link="internal">Базы данных</a>
<a href="https://otus.ru/journal/tag/matematika/" class="tag-cloud-link tag-link-44 tag-link-position-28" style="font-size: 10.916666666667pt;" aria-label="Математика (23 элемента)" data-wpel-link="internal">Математика</a>
<a href="https://otus.ru/journal/tag/arhitektura-po/" class="tag-cloud-link tag-link-10 tag-link-position-29" style="font-size: 9.4583333333333pt;" aria-label="архитектура ПО (16 элементов)" data-wpel-link="internal">архитектура ПО</a>
<a href="https://otus.ru/journal/tag/bazy-dannyh-2/" class="tag-cloud-link tag-link-251 tag-link-position-30" style="font-size: 10.138888888889pt;" aria-label="базы данных (19 элементов)" data-wpel-link="internal">базы данных</a>
<a href="https://otus.ru/journal/tag/vebinar/" class="tag-cloud-link tag-link-201 tag-link-position-31" style="font-size: 13.930555555556pt;" aria-label="вебинар (48 элементов)" data-wpel-link="internal">вебинар</a>
<a href="https://otus.ru/journal/tag/dajdzhest/" class="tag-cloud-link tag-link-308 tag-link-position-32" style="font-size: 10.722222222222pt;" aria-label="дайджест (22 элемента)" data-wpel-link="internal">дайджест</a>
<a href="https://otus.ru/journal/tag/zapis-vebinara/" class="tag-cloud-link tag-link-226 tag-link-position-33" style="font-size: 14.902777777778pt;" aria-label="запись вебинара (61 элемент)" data-wpel-link="internal">запись вебинара</a>
<a href="https://otus.ru/journal/tag/zapis-uroka/" class="tag-cloud-link tag-link-272 tag-link-position-34" style="font-size: 16.069444444444pt;" aria-label="запись урока (80 элементов)" data-wpel-link="internal">запись урока</a>
<a href="https://otus.ru/journal/tag/informacionnaya-bezopasnost/" class="tag-cloud-link tag-link-232 tag-link-position-35" style="font-size: 10.138888888889pt;" aria-label="информационная безопасность (19 элементов)" data-wpel-link="internal">информационная безопасность</a>
<a href="https://otus.ru/journal/tag/karera-v-it/" class="tag-cloud-link tag-link-292 tag-link-position-36" style="font-size: 9.9444444444444pt;" aria-label="карьера в IT (18 элементов)" data-wpel-link="internal">карьера в IT</a>
<a href="https://otus.ru/journal/tag/podborka/" class="tag-cloud-link tag-link-7 tag-link-position-37" style="font-size: 12.666666666667pt;" aria-label="подборка (35 элементов)" data-wpel-link="internal">подборка</a>
<a href="https://otus.ru/journal/tag/podborka-statej/" class="tag-cloud-link tag-link-219 tag-link-position-38" style="font-size: 15.777777777778pt;" aria-label="подборка статей (75 элементов)" data-wpel-link="internal">подборка статей</a>
<a href="https://otus.ru/journal/tag/programmirovanie/" class="tag-cloud-link tag-link-65 tag-link-position-39" style="font-size: 22pt;" aria-label="программирование (332 элемента)" data-wpel-link="internal">программирование</a>
<a href="https://otus.ru/journal/tag/proekt/" class="tag-cloud-link tag-link-321 tag-link-position-40" style="font-size: 11.888888888889pt;" aria-label="проект (29 элементов)" data-wpel-link="internal">проект</a>
<a href="https://otus.ru/journal/tag/proektnaya-rabota/" class="tag-cloud-link tag-link-310 tag-link-position-41" style="font-size: 11.597222222222pt;" aria-label="проектная работа (27 элементов)" data-wpel-link="internal">проектная работа</a>
<a href="https://otus.ru/journal/tag/seti/" class="tag-cloud-link tag-link-181 tag-link-position-42" style="font-size: 12.958333333333pt;" aria-label="сети (38 элементов)" data-wpel-link="internal">сети</a>
<a href="https://otus.ru/journal/tag/testirovanie/" class="tag-cloud-link tag-link-69 tag-link-position-43" style="font-size: 13.930555555556pt;" aria-label="тестирование (48 элементов)" data-wpel-link="internal">тестирование</a>
<a href="https://otus.ru/journal/tag/upravlenie-komandoj/" class="tag-cloud-link tag-link-63 tag-link-position-44" style="font-size: 11.694444444444pt;" aria-label="управление командой (28 элементов)" data-wpel-link="internal">управление командой</a>
<a href="https://otus.ru/journal/tag/habr-2/" class="tag-cloud-link tag-link-203 tag-link-position-45" style="font-size: 13.930555555556pt;" aria-label="хабр (48 элементов)" data-wpel-link="internal">хабр</a></div>
</li>
</ul>
</div>
</aside>
</div> <!-- .ts-row -->
</div> <!-- .main -->
<footer class="main-footer dark bold">
<section class="lower-footer cf">
<div class="wrap">
<div class="links">
<div class="menu-menju-navykov-container"><ul id="menu-menju-navykov-1" class="menu"><li class="menu-item menu-item-type-custom menu-item-object-custom menu-item-10413"><a href="https://otus.ru/categories/programming/" data-wpel-link="external" target="_blank" rel="nofollow external noopener noreferrer" class="wpel-icon-right">Программирование<span class="wpel-icon wpel-image wpel-icon-6"></span></a></li>
<li class="menu-item menu-item-type-custom menu-item-object-custom menu-item-10414"><a href="https://otus.ru/categories/architecture/" data-wpel-link="external" target="_blank" rel="nofollow external noopener noreferrer" class="wpel-icon-right">Архитектура<span class="wpel-icon wpel-image wpel-icon-6"></span></a></li>
<li class="menu-item menu-item-type-custom menu-item-object-custom menu-item-10415"><a href="https://otus.ru/categories/operations/" data-wpel-link="external" target="_blank" rel="nofollow external noopener noreferrer" class="wpel-icon-right">Инфраструктура<span class="wpel-icon wpel-image wpel-icon-6"></span></a></li>
<li class="menu-item menu-item-type-custom menu-item-object-custom menu-item-10416"><a href="https://otus.ru/categories/information-security-courses/" data-wpel-link="external" target="_blank" rel="nofollow external noopener noreferrer" class="wpel-icon-right">Безопасность<span class="wpel-icon wpel-image wpel-icon-6"></span></a></li>
<li class="menu-item menu-item-type-custom menu-item-object-custom menu-item-10417"><a href="https://otus.ru/categories/data-science/" data-wpel-link="external" target="_blank" rel="nofollow external noopener noreferrer" class="wpel-icon-right">Data Science<span class="wpel-icon wpel-image wpel-icon-6"></span></a></li>
<li class="menu-item menu-item-type-custom menu-item-object-custom menu-item-10418"><a href="https://otus.ru/categories/gamedev/" data-wpel-link="external" target="_blank" rel="nofollow external noopener noreferrer" class="wpel-icon-right">GameDev<span class="wpel-icon wpel-image wpel-icon-6"></span></a></li>
<li class="menu-item menu-item-type-custom menu-item-object-custom menu-item-10419"><a href="https://otus.ru/categories/marketing-business/" data-wpel-link="external" target="_blank" rel="nofollow external noopener noreferrer" class="wpel-icon-right">Управление<span class="wpel-icon wpel-image wpel-icon-6"></span></a></li>
<li class="menu-item menu-item-type-custom menu-item-object-custom menu-item-10420"><a href="https://otus.ru/categories/analytics/" data-wpel-link="external" target="_blank" rel="nofollow external noopener noreferrer" class="wpel-icon-right">Аналитика и анализ<span class="wpel-icon wpel-image wpel-icon-6"></span></a></li>
<li class="menu-item menu-item-type-custom menu-item-object-custom menu-item-10421"><a href="https://otus.ru/categories/testing/" data-wpel-link="external" target="_blank" rel="nofollow external noopener noreferrer" class="wpel-icon-right">Тестирование<span class="wpel-icon wpel-image wpel-icon-6"></span></a></li>
</ul></div> </div>
<p class="copyright"> © 2015-2026 OTUS </p>
<div class="to-top">
<a href="#" class="back-to-top"><i class="fa fa-angle-up"></i> Top</a>
</div>
</div>
</section>
</footer>
</div> <!-- .main-wrap -->
<div class="mobile-menu-container off-canvas" id="mobile-menu">
<a href="#" class="close"><i class="fa fa-times"></i></a>
<div class="logo">
</div>
<ul class="mobile-menu"></ul>
</div>
<div class="search-modal-wrap">
<div class="search-modal-box" role="dialog" aria-modal="true">
<form method="get" class="search-form" action="https://otus.ru/journal/">
<input type="search" class="search-field" name="s" placeholder="Search..." value="" required />
<button type="submit" class="search-submit visuallyhidden">Submit</button>
<p class="message">
Type above and press <em>Enter</em> to search. Press <em>Esc</em> to cancel. </p>
</form>
</div>
</div>
<script type="text/javascript" src="https://otus.ru/journal/wp-content/plugins/clearfy/components/comments-plus/assets/js/url-span.js" id="wbcr-comments-plus-url-span-js"></script>
<script type="text/javascript" id="ez-toc-scroll-scriptjs-js-extra">
/* <![CDATA[ */
var eztoc_smooth_local = {"scroll_offset":"30"};
/* ]]> */
</script>
<script type="text/javascript" src="https://otus.ru/journal/wp-content/plugins/easy-table-of-contents/assets/js/smooth_scroll.min.js" id="ez-toc-scroll-scriptjs-js"></script>
<script type="text/javascript" src="https://otus.ru/journal/wp-content/plugins/easy-table-of-contents/vendor/js-cookie/js.cookie.min.js" id="ez-toc-js-cookie-js"></script>
<script type="text/javascript" src="https://otus.ru/journal/wp-content/plugins/easy-table-of-contents/vendor/sticky-kit/jquery.sticky-kit.min.js" id="ez-toc-jquery-sticky-kit-js"></script>
<script type="text/javascript" id="ez-toc-js-js-extra">
/* <![CDATA[ */
var ezTOC = {"smooth_scroll":"1","visibility_hide_by_default":"","scroll_offset":"30","fallbackIcon":"<span class=\"\"><span class=\"eztoc-hide\" style=\"display:none;\">Toggle<\/span><span class=\"ez-toc-icon-toggle-span\"><svg style=\"fill: #999;color:#999\" xmlns=\"http:\/\/www.w3.org\/2000\/svg\" class=\"list-377408\" width=\"20px\" height=\"20px\" viewBox=\"0 0 24 24\" fill=\"none\"><path d=\"M6 6H4v2h2V6zm14 0H8v2h12V6zM4 11h2v2H4v-2zm16 0H8v2h12v-2zM4 16h2v2H4v-2zm16 0H8v2h12v-2z\" fill=\"currentColor\"><\/path><\/svg><svg style=\"fill: #999;color:#999\" class=\"arrow-unsorted-368013\" xmlns=\"http:\/\/www.w3.org\/2000\/svg\" width=\"10px\" height=\"10px\" viewBox=\"0 0 24 24\" version=\"1.2\" baseProfile=\"tiny\"><path d=\"M18.2 9.3l-6.2-6.3-6.2 6.3c-.2.2-.3.4-.3.7s.1.5.3.7c.2.2.4.3.7.3h11c.3 0 .5-.1.7-.3.2-.2.3-.5.3-.7s-.1-.5-.3-.7zM5.8 14.7l6.2 6.3 6.2-6.3c.2-.2.3-.5.3-.7s-.1-.5-.3-.7c-.2-.2-.4-.3-.7-.3h-11c-.3 0-.5.1-.7.3-.2.2-.3.5-.3.7s.1.5.3.7z\"\/><\/svg><\/span><\/span>"};
/* ]]> */
</script>
<script type="text/javascript" src="https://otus.ru/journal/wp-content/plugins/easy-table-of-contents/assets/js/front.min.js" id="ez-toc-js-js"></script>
<script type="text/javascript" src="https://otus.ru/journal/wp-content/themes/contentberg/js/custom-script.js" id="custom-script-js"></script>
<script type="text/javascript" src="https://otus.ru/journal/wp-content/themes/contentberg/js/magnific-popup.js" id="magnific-popup-js"></script>
<script type="text/javascript" src="https://otus.ru/journal/wp-content/themes/contentberg/js/jquery.fitvids.js" id="jquery-fitvids-js"></script>
<script type="text/javascript" src="https://otus.ru/journal/wp-includes/js/imagesloaded.min.js" id="imagesloaded-js"></script>
<script type="text/javascript" src="https://otus.ru/journal/wp-content/themes/contentberg/js/object-fit-images.js" id="object-fit-images-js"></script>
<script type="text/javascript" id="contentberg-theme-js-extra">
/* <![CDATA[ */
var Bunyad = {"custom_ajax_url":"\/journal\/piton-i-graficheskij-interfejs\/"};
/* ]]> */
</script>
<script type="text/javascript" src="https://otus.ru/journal/wp-content/themes/contentberg/js/theme.js" id="contentberg-theme-js"></script>
<script type="text/javascript" src="https://otus.ru/journal/wp-content/themes/contentberg/js/theia-sticky-sidebar.js" id="theia-sticky-sidebar-js"></script>
<script type="text/javascript" src="https://otus.ru/journal/wp-content/themes/contentberg/js/jquery.slick.js" id="jquery-slick-js"></script>
<script type="text/javascript" src="https://otus.ru/journal/wp-content/themes/contentberg/js/jarallax.js" id="jarallax-js"></script>
<script type="text/javascript" src="https://otus.ru/journal/wp-includes/js/masonry.min.js" id="masonry-js"></script>
<script type="text/javascript" src="https://otus.ru/journal/wp-includes/js/jquery/jquery.masonry.min.js" id="jquery-masonry-js"></script>
</body>
</html>
<!-- Cache served by breeze CACHE - Last modified: Mon, 09 Mar 2026 16:07:56 GMT -->