Как сделать приложение на python
Перейти к содержимому

Как сделать приложение на python

  • автор:

Создание красивого Desktop-приложения на Python (customtkinter)

Если Вы, как и я, решили впервые взглянуть в сторону Python после нескольких попыток изучения С++/C# то скорее всего первым проектом станет desktop-приложение. Отходя от темы скажу что тяга к изучению этих языков была безнадежно утрачена в виду классического преподавания в духе «лишь бы сдали» и бесчисленных однотипных и монотонных лекций. Как я сказал выше хоть и на начальном уровне, но я всё же касался разработки приложений для Windows и поэтому мне хотелось посмотреть на принципы работы питона сначала отсюда(а не прыгать в django и прочие мощные фреймворки). Должен предупредить — в статье не приводятся выдержки из кода и она является скорее выражением моих эмоций, полученных за этот проект.

Какое приложение создавать?

В этом я не сомневался ни секунды и сразу выбрал — ТАЙМЕР! Я люблю засыпать под звуки фильмов с различных ресурсов, но то что после их окончания комп работал лишние 6 часов меня решительно не устраивало. Я конечно знаю про существование разного рода приложений с подобным функционалом(например SMtimer), но во-первых его UX/UI это просто привет нулевым, а во-вторых хотелось всё-таки своё.

Непосредственно сам SMtimer

Задачи намечены — время действовать

Посмотрев полтора гайда с youtube преисполнился и написал первый прототип с использованием стандартной библиотеки tkinter. Выглядело это весьма сомнительно с точки зрения того же UX/UI, но это уже было что-то

Первая версия моего многострадального проекта

Тут каждый может заметить и сказать «но ведь это ещё хуже чем SMtimer» и будут правы, в целом и меня посещали такие мысли и я решил обратиться к поиску чего-то что сможет сделать из этого адекватное приложение которым я смогу пользоваться без зазрения совести.

CustomTkinter или как я пытался познать дзен

После недолгого поиска я нашел его — CustomTkinter. Он обещал буквально сделать из моего прототипа приложение, которое будто изначально было в Windows 10. Непосредственно exampl’ы вы можете смотреть ниже:

Темная тема Соответственно светлая тема

Вдобавок к этому библиотека обещала и минимальные правки кода для переноса моего «прототипа» на эту прелесть, но мне предстоял ещё большой путь в понимании как это тут работает.

Куча проблем и нехватка понимания

Именно так бы я описал свой путь в познании этой библиотеки. Буквально пытаясь взаимодействовать с ней я понял как устроены типы данных Python(да, может показаться смешным, но когда впервые встречаешь NoneType слегка удивляешься), понял как взаимодействовать с объектами классов и собственно разделять код проекта на функциональные блоки (что до этого мне казалось чем-то странным). Но для того чтобы понять насколько всё было грустно в моих познаниях — вот референс который я запилил от безысходности( на тот момент я хотел получить хотя бы это):

Как можно заметить даже цвет в тупую залит в Paint

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

Пусть и работающая на коленях, но РАБОТАЮЩАЯ версия

Получив это я уже был рад, что не сдался и приступил к починке расположения всех объектов по экрану. Однако следует упомянуть о «маленькая проблема» — в CustomTkinter нет SpinBox, а значит вводить данные было нужно либо с клавиатуры, либо искать как сделать этот самый SpinBox самому. Выбор пал на второй вариант, на сайте, посвященном самому ctk автор сделал FloatSpinBox, доработав который я уже мог получить то что хотел.

Собственно FloatSpinBox

Главным его косяком было отсутствие реакции на колёсико мышки — для меня это было критично — нажимать 32 раза для установки минут меня не прельщало и я решил допилить его самостоятельно:

  1. Добавил min и max value — теперь я мог использовать этот класс и для минут и для часов (сначала я просто наспамил несколько классов где вручную установил ограничения для каждого из них)
  2. Реакция на колёсико мышки теперь охватывала весь SpinBox и это было чудесно. Если просто повесить обработчик на self.bind(«MouseWheel», self.on_mouse_wheel)» то срабатывание будет только на границах entry и элементах кнопок, что просто ужасно.
  3. Ну и конечно реализовал прокрутку в обратную сторону. Это так странно делать то что обычно реализовано уже за тебя. Ну и немного поиграл с темами самого customtkinter:

Рождение первого адекватного прототипаТемы которые я нашел на просторах github

Наконец то, что я и хотел получить

Теперь я решил сделать вывод времени до срабатывания. Я прорабатывал разные версии этого таймера и пришел к тому что запилил TimeBox. Главное отличие — никаких кнопок. Вывод конечно же стал гораздо веселее.

Предрелизная версия моего таймера

После того как я насмотрелся на кастомные темы с просторов github я решил, что мне такого ужаса точно не нужно и вернулся к истокам — стандартной зелёной теме. Победив эффект циклопа (даже 3х) я добавил переключение тем и поправил логику приложения — перезагрузка. выключение, сон и блокировка работают на ура ну и два вида условий таймера — через промежуток времени и В конкретное время. Я был полностью доволен и буквально счастлив что теперь мне не нужно каждый день идти в планировщик заданий и выставлять время выключения вручную! Но тут я увидел то, что впоследствии переведет меня из Notepad++ (да, да, именно там я и писал свой проект до этого момента) в PyCharm. Это была библиотечка pywinstyles, обещающая эффекты прозрачности как из win7 но в стиле десятки. То что нужно.

Sample Customtkinter но с Pywinstyles

Мне показалось это просто идеальным дополнением моей програмки. Запускаешь поверх фильма и не мешает и знаешь сколько времени осталось — красота. Но полное отсутствие документации и внятных sampl’ов заставило заново пересмотреть перспективы проекта. Я написал автору pywinstyles и с его описанием я таки смог заставить работать это всё вместе:

Итоговые версии с pywinstyles

Если тут есть такие же странные люди, которые решат потрогать pywinstyles — будьте готовы к множеству проблем. К примеру после смены темы на прозрачную назад вернуть никак. Только перезапуск. У main_frame от ctk тут беловатый фон, что заставляет программу «сиять» на светлых фонах.

Выводы

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

Как быстро создать и развернуть веб-приложение на Python

В этой статье речь пойдет о разработке и развертывании простейшего дашборда по COVID-19 с помощью Streamlit. Streamlit — фреймворк, предназначенный для быстрого создания приложений по обработке данных путем развертывания организованного на Python пользовательского интерфейса. Streamlit не требует от разработчика предшествующего опыта (хотя практические навыки, конечно, не помешают).

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

Настройка виртуальной среды

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

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

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

Кроме того, виртуальная среда помогает поддерживать чистоту и организованность разработки. Приложение, вероятно, не будет использовать все библиотеки Python, установленные на компьютере. Если создавать его вне виртуальной среды, каждую библиотеку надо было бы включить в так называемый файл требований (подробнее об этом позже), необходимый для развертывания приложения. Это привело бы к значительному раздуванию кода.

Чтобы настроить виртуальную среду, откройте терминал или командную строку. Если работаете на Mac, перейдите к рабочему столу, набрав cd desktop , а для windows это будет cd C:\Users\YOUR PC USERNAME\Desktop . Затем введите mkdir streamlit_project && cd streamlit_project . В каталоге проекта создайте виртуальную среду с помощью python3 -m venv , за которым следует любое название. Обычно виртуальные среды называют .venv , но в данном примере будет virt_env . Вот как это выглядит:

python3 -m venv virt_env # Mac
python -m venv virt_env # Windows

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

source virt_env/bin/activate # Mac
virt_env\Scripts\activate # Windows
После активации вы должны увидеть
(virt_env) .

Создание приложения

Теперь установим streamlit и другие пакеты, которые понадобятся в приложении на Python:

python3 -m pip install streamlit # Mac
python -m pip install streamlit # Windows
python3 -m pip install pandas # Mac
python -m pip install pandas # Windows
python3 -m pip install matplotlib # Mac
python -m pip install matplotlib # Windows

После установки этих пакетов скопируйте и вставьте код из Github-репозитория, сохранив его под именем covid_dashboard.py в каталоге виртуальной среды. Этот файл Python, содержащий приложение streamlit, выполняет две основные задачи.

1) Вычисляет четыре метрики.

2) Строит граф временных рядов новых случаев по штатам.

Объясню каждый раздел более подробно.

@st.cache(allow_output_mutation=True)def load_dataset(): try: df = pd.read_csv("https://raw.githubusercontent.com/nytimes/covid-19-data/master/us-counties.csv", sep=",") states = list(df['state'].unique()) except: Exception return df, states

Функция load_dataset() извлекает все данные по COVID-19 из аккаунта NYT на Github и создает список штатов США для фильтрации. Важно использовать st.cache над этой функцией, чтобы сохранить весь набор данных в памяти. В таком случае программе не придется перезагружать весь набор данных каждый раз при применении другого фильтра.

def pct_change(data, state, today): 
.

Функция pct_change принимает три аргумента: набор данных по COVID-19, штат, выбранный нами в выпадающем списке и сегодняшнюю дату. Эта функция возвращает словарь с четырьмя метриками (новые случаи, изменение по случаям за 14 дней, новые смерти и изменение по смертям за 14 дней).

def chart_data(data, state): 
.

def chart_data берет набор данных по COVID-19 и выбранный штат из выпадающего списка и возвращает временной ряд данных о новых случаях для выбранного штата.

Переходим к последней части кода (именно здесь вызываются функции, а данные возвращаются и отображаются в приложении). Вызываемая функция load_dataset() создает датафрейм и список штатов США. Затем создаем выпадающий список с помощью st.selectbox , добавляем к нему метку и список штатов. Добавляем логику, когда выпадающий список выбран.

Наконец, streamlit предлагает удобный способ добавления колонок и графов на веб-страницу, создавая более чистый общий формат. Главное преимущество — возможность создавать организованные и отзывчивые HTML-компоненты на чистом Python с минимальным количеством кода.

df, states = load_dataset()state_dropdown = st.selectbox('Select a State', states)if state_dropdown:data_dict = pct_change(df, state_dropdown, today)col1, col2, col3, col4 = st.columns(4)col1.markdown(f"New Cases: ")col2.markdown(f"""

14-Day Change: %

""", unsafe_allow_html=True)
col3.markdown(f"New Deaths: ")col4.markdown(f"""

14-Day Change: %

""", unsafe_allow_html=True)
chart_data = chart_data(df, state_dropdown)st.line_chart(chart_data)

Развертывание приложения: начальные шаги

Пока созданное в виртуальной среде приложение streamlit живет только на локальном компьютере. Чтобы поделиться им со всем миром, нужно установить Git и Heroku.

Чтобы установить Git, откройте новое окно командной строки и на Mac введите:

git --version

Должно появиться всплывающее окно с дальнейшими инструкциями, позволяющее продолжить установку. Если вы пользователь Windows, используйте следующую ссылку для загрузки Git.

Чтобы установить Heroku на Mac, сначала установите Homebrew (если этого еще не сделали), а затем введите в новом окне терминала:

brew tap heroku/brew && brew install heroku

Если компьютер Mac работает на чипе M1, может произойти ошибка. Для решения проблемы воспользуйтесь страницей поддержки Apple.

Если вы пользователь Windows, используйте следующую ссылку для загрузки Heroku CLI.

После установки этих зависимостей можно опубликовать код на Github. Сначала создайте файл .gitignore , чтобы исключить файл виртуальной среды из репозитория Github, а затем измените его, введя virt_env/ (сохраните файл после внесения изменений):

(virt_env) > touch .gitignore # Mac
(virt_env) > echo.>.gitignore # Windows

Теперь инициализируйте Git в окне командной строки, где активна виртуальная среда, через git:

git init
git add -A
git commit -m "initial commit"

Войдите в аккаунт Github, создайте новый репозиторий, а затем выберите опцию Push an existing repository from the command line. Скопируйте и вставьте фрагмент кода из этой опции в командную строку, где запущена виртуальная среда.

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

python -m pip freeze > requirements.txt

Создайте новый файл в каталоге виртуальной среды под названием setup.sh и сохраните в нем следующее:

mkdir -p ~/.streamlit/echo "\[server]\n\headless = true\n\port = $PORT\n\enableCORS = false\n\\n\" > ~/.streamlit/config.toml

Затем создайте Procfile (назовите его просто Procfile ) в каталоге виртуальной среды и сохраните в нем следующее:

web: sh setup.sh && streamlit run covid_dashboard.py

Теперь пришло время добавить файлы requirements.txt , Procfile и setup.sh в репозиторий Github:

git add -A
git commit -m "files for Heroku deployment"
git push -u origin main

Развертывание приложения на Heroku

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

(virt_env) > heroku login
(virt_env) > heroku create

Это создаст случайное url-имя и развернет приложение, что займет 1–2 минуты. Вы должны увидеть в командной строке url, подобный приведенному здесь. Можете скопировать его в свой браузер.

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

  • Простое руководство по форматированию строк в Python с помощью f-строк
  • 7 расширенных возможностей Python
  • 10 ошибок, которые выдают новичков в Python

Десктопное приложение на Python: UI и сигналы

С помощью Python можно создавать современные десктопные приложения. Рассказываем, как сделать графический интерфейс с помощью кода.

Считается, что Python не лучший выбор для десктопных приложений. Однако, когда в 2016 году я собирался переходить от разработки сайтов к программному обеспечению, Google подсказал мне, что на Python можно создавать сложные современные приложения. Например blender3d, который написан на Python.

Десктопное приложение на Python: UI и сигналы 1

Мы будем использовать PyQt (произносится «Пай-Кьют‎»‎). Это фреймворк Qt, портированный с C++. Qt известен тем, что необходим C++ разработчикам. С помощью этого фреймворка сделаны blender3d, Tableau, Telegram, Anaconda Navigator, Ipython, Jupyter Notebook, VirtualBox, VLC и другие. Мы будем использовать его вместо удручающего Tkinter.

Требования

  1. Вы должны знать основы Python
  2. Вы должны знать, как устанавливать пакеты и библиотеки с помощью pip.
  3. У вас должен быть установлен Python.

Установка

Вам нужно установить только PyQt. Откройте терминал и введите команду:

>>> pip install PyQt5 

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

Hello, World!

Создайте папку с проектом, мы назовём его helloApp. Откройте файл main.py, лучше сделать это vscode, и введите следующий код:

import sys from PyQt5.QtGui import QGuiApplication from PyQt5.QtQml import QQmlApplicationEngine app = QGuiApplication(sys.argv) engine = QQmlApplicationEngine() engine.quit.connect(app.quit) engine.load('./UI/main.qml') sys.exit(app.exec()) 

Этот код вызывает QGuiApplication и QQmlApplicationEngine которые используют Qml вместо QtWidget в качестве UI слоя в Qt приложении. Затем, мы присоединяем UI функцию выхода к главной функции выхода приложения. Теперь они оба закроются одновременно, когда пользователь нажмёт выход. Затем, загружаем qml файл для Qml UI. Вызов app.exec(), запускает приложение, он находится внутри sys.exit, потому что возвращает код выхода, который передается в sys.exit.

Добавьте этот код в main.qml:

import QtQuick 2.15 import QtQuick.Controls 2.15 ApplicationWindow < visible: true width: 600 height: 500 title: "HelloApp" Text < anchors.centerIn: parent text: "Hello, World" font.pixelSize: 24 >> 

Этот код создает окно, делает его видимым, с указанными размерами и заголовком. Объект Text отображается в середине окна.

Теперь давайте запустим приложение:

>>> python main.py 

Вы увидите такое окно:

Обновление UI

Давайте немного обновим UI, добавим фоновое изображение и время:

import QtQuick 2.15 import QtQuick.Controls 2.15 ApplicationWindow < visible: true width: 400 height: 600 title: "HelloApp" Rectangle < anchors.fill: parent Image < sourceSize.width: parent.width sourceSize.height: parent.height source: "./images/playas.jpg" fillMode: Image.PreserveAspectCrop >Rectangle < anchors.fill: parent color: "transparent" Text < text: "16:38:33" font.pixelSize: 24 color: "white" >> > > 

Внутри типа ApplicationWindow находится содержимое окна, тип Rectangle заполняет пространство окна. Внутри него находится тип Image и другой прозрачный Rectangle который отобразится поверх изображения.

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

Text < anchors < bottom: parent.bottom bottomMargin: 12 left: parent.left leftMargin: 12 >text: "16:38:33" font.pixelSize: 24 . > 

После запуска вы увидите следующее:

Показываем текущее время

Модуль gmtime позволяет использовать структуру со временем, а strftime даёт возможность преобразовать её в строку. Импортируем их:

import sys from time import strftime, gmtime 

Теперь мы можем получить строку с текущим временем:

curr_time = strftime("%H:%M:%S", gmtime()) 

Строка «%H:%M:%S» означает, что мы получим время в 24 часовом формате, с часами минутами и секундами (подробнее о strtime).

Давайте создадим property в qml файле, для хранения времени. Мы назовём его currTime.

property string currTime: "00:00:00" 

Теперь заменим текст нашей переменной:

Text < . text: currTime // used to be; text: "16:38:33" font.pixelSize: 48 color: "white" > 

Теперь, передадим переменную curr_time из pyhton в qml:

engine.load('./UI/main.qml') engine.rootObjects()[0].setProperty('currTime', curr_time) 

Это один из способов передачи информации из Python в UI.

Запустите приложение и вы увидите текущее время.

Обновление времени

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

Чтобы использовать сигналы нам нужен подкласс QObject. Назовём его Backend.

. from PyQt5.QtCore import QObject, pyqtSignal class Backend(QObject): def __init__(self): QObject.__init__(self) . 

У нас уже имеется свойства для строки со временем curr_time, теперь создадим свойство backend типа QtObject в файле main.qml.

property string currTime: "00:00:00" property QtObject backend 

Передадим данные из Python в qml:

engine.load('./UI/main.qml') back_end = Backend() engine.rootObjects()[0].setProperty('backend', back_end) 

В qml файле один объект QtObject может получать несколько функций (называемых сигналами) из Python.

Создадим тип Connections и укажем backend в его target. Теперь внутри этого типа может быть столько функций, сколько нам необходимо получить в backend.

. Rectangle < anchors.fill: parent Image < . >. > Connections < target: backend >. 

Таким образом мы свяжем qml и сигналы из Python.

Мы используем потоки, для того чтобы обеспечить своевременное обновление UI. Создадим две функции, одну для управления потоками, а вторую для выполнения действий. Хорошая практика использовать в названии одной из функций _.

. import threading from time import sleep . class Backend(QObject): def __init__(self): QObject.__init__(self) def bootUp(self): t_thread = threading.Thread(target=self._bootUp) t_thread.daemon = True t_thread.start() def _bootUp(self): while True: curr_time = strftime("%H:%M:%S", gmtime()) print(curr_time) sleep(1) . 

Создадим pyqtsignal и назовём его updated, затем вызовем его из функции updater.

. from PyQt5.QtCore import QObject, pyqtSignal . def __init__(self): QObject.__init__(self) updated = pyqtSignal(str, arguments=['updater']) def updater(self, curr_time): self.updated.emit(curr_time) . 

В этом коде updated имеет параметр arguments, который является списком, содержащим имя функции “updater”. Qml будет получать данные из этой функции. В функции updater мы вызываем метод emit и передаём ему данные о времени.

Обновим qml, получив сигнал, с помощью обработчика, название которого состоит из “on” и имени сигнала:

target: backend function onUpdated(msg)

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

curr_time = strftime("%H:%M:%S", gmtime()) self.updater(curr_time) sleep(0.1) 

Функция bootUp должна быть вызвана сразу же после загрузки UI:

engine.rootObjects()[0].setProperty('backend', back_end) back_end.bootUp() sys.exit(app.exec()) 

Всё готово

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

flags: Qt.FramelessWindowHint | Qt.Window 

Так должен выглядеть файл main.py:

import sys from time import strftime, gmtime import threading from time import sleep from PyQt5.QtGui import QGuiApplication from PyQt5.QtQml import QQmlApplicationEngine from PyQt5.QtCore import QObject, pyqtSignal class Backend(QObject): def __init__(self): QObject.__init__(self) updated = pyqtSignal(str, arguments=['updater']) def updater(self, curr_time): self.updated.emit(curr_time) def bootUp(self): t_thread = threading.Thread(target=self._bootUp) t_thread.daemon = True t_thread.start() def _bootUp(self): while True: curr_time = strftime("%H:%M:%S", gmtime()) self.updater(curr_time) sleep(0.1) app = QGuiApplication(sys.argv) engine = QQmlApplicationEngine() engine.quit.connect(app.quit) engine.load('./UI/main.qml') back_end = Backend() engine.rootObjects()[0].setProperty('backend', back_end) back_end.bootUp() sys.exit(app.exec()) 

Вот содержимое файла main.qml:

import QtQuick 2.15 import QtQuick.Controls 2.15 ApplicationWindow < visible: true width: 360 height: 600 x: screen.desktopAvailableWidth - width - 12 y: screen.desktopAvailableHeight - height - 48 title: "HelloApp" flags: Qt.FramelessWindowHint | Qt.Window property string currTime: "00:00:00" property QtObject backend Rectangle < anchors.fill: parent Image < sourceSize.width: parent.width sourceSize.height: parent.height source: "./images/playas.jpg" fillMode: Image.PreserveAspectFit >Text < anchors < bottom: parent.bottom bottomMargin: 12 left: parent.left leftMargin: 12 >text: currTime font.pixelSize: 48 color: "white" > > Connections < target: backend function onUpdated(msg) < currTime = msg; >> > 

Сборка приложения

Для сборки десктопного приложения на Python нам понадобится pyinstaller.

>>> pip install pyinstaller 

Чтобы в сборку добавились все необходимые ресурсы, создадим файл spec:

>>> pyi-makespec main.py 

Настройки файла spec

Параметр datas можно использовать для того, чтобы включить файл в приложение. Это список кортежей, каждый из которых обязательно должен иметь target path(откуда брать файлы) и destination path(где будет находится приложение). destination path должен быть относительным. Чтобы расположить все ресурсы в одной папке с exe-файлами используйте пустую строку.

Измените параметр datas, на путь к вашей папке с UI:

a = Analysis(['main.py'], . datas=[('I:/path/to/helloApp/UI', 'UI')], hiddenimports=[], . exe = EXE(pyz, a.scripts, [], . name='main', debug=False, . console=False ) coll = COLLECT(exe, . upx_exclude=[], name='main') 

Параметр console установим в false, потому что у нас не консольное приложение.

Параметр name внутри вызова Exe, это имя исполняемого файла. name внутри вызова Collect, это имя папки в которой появится готовое приложение. Имена создаются на основании файла для которого мы создали spec — main.py.

Теперь можно запустить сборку:

>>> pyinstaller main.spec 

В папке dist появится папка main. Для запуска программы достаточно запустить файл main.exe.

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

О том, как использовать Qt Designer для создания UI приложений на Python читайте в нашей статье.

Разработка мобильных приложений на Python. Создание анимаций в Kivy. Part 2

Приветствую всех любителей и знатоков языка программирования Python!

Сегодня продолжим разбираться с темой анимаций в кроссплатформенном фреймворке для с поддержкой мультитач — Kivy в связке с библиотекой компонентов Google Material Design — KivyMD. В прошлой статье мы уже разбирали пример тестового приложения на Python/Kivy/KivyMD, в этой — пройдемся по теме анимаций более подробно. В конце статьи я приведу ссылку на репозиторий проекта, в котором вы сможете скачать и сами пощупать, демонстрационное Kivy/KivyMD приложение. Как и предыдущая, эта статья будет содержать не маленькое количество GIF анимаций и видео, а поэтому наливайте кофе и погнали!

Kivy работает на Linux, Windows, OS X, Android, iOS и Raspberry Pi. Вы можете запустить один и тот же код на всех поддерживаемых платформах без внесения дополнительных изменений в кодовую базу. Kivy поддерживает большое количество устройств ввода, включая WM_Touch, WM_Pen, Mac OS X Trackpad и Magic Mouse, Mtdev, Linux Kernel HID, TUIO и так же как и Flutter, не задействует нативные элементы управления. Все его виджеты настраиваются. Это значит, что приложения Kivy будут выглядеть одинаково на всех платформах. Но благодаря тому, что виджеты Kivy могут быть кастомизированы как угодно, вы можете создавать свои собственные виджеты. Например, так появилась библиотека KivyMD. Прежде чем продолжить, давайте посмотрим небольшой обзор возможностей Kivy:

Демонстрационные ролики Kivy приложений

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

from kivy.animation import Animation from kivy.lang import Builder from kivymd.app import MDApp KV = """ opacity: 0 adaptive_height: True halign: "center" y: -self.height MDScreen: on_touch_down: app.start_animation() CommonLabel: id: lbl_1 font_size: "32sp" text: "M A R S" CommonLabel: id: lbl_2 font_size: "12sp" text: "Lorem ipsum dolor sit amet, consectetur adipiscing elit" """ class TestAnimation(MDApp): def build(self): return Builder.load_string(KV) def start_animation(self): lbl_1 = self.root.ids.lbl_1 lbl_2 = self.root.ids.lbl_2 Animation( opacity=1, y=lbl_1.height * 2, d=0.9, t="in_out_back" ).start(lbl_1) Animation( opacity=1, y=lbl_2.height + ids.lbl_1.height, d=1, t="in_out_back" ).start(lbl_2) TestAnimation().run() 

Это уже готовое приложение. Мы будем его лишь слегка редактировать. Правило CommonLabel в KV строке аналогично созданию класса в Python коде. Сравните:

Код в Kivy Language всегда короче и читабельнее. Поэтому в Python коде у нас будет только логика. Мы создали две метки с общими свойствами, описанными в правиле CommonLabel: прозрачность (opacity), размер текстуры метки (adaptive_height), горизонтальное выравнивание (halign), положение по оси Y (y ) и дали этим меткам id-шники (lbl_1, lbl_2), чтобы иметь возможность обращаться к свойствам объектов меток и манипулировать ими из Python кода. Далее мы привязали к событию on_touch_down (сработает при прикосновении к экрану в любом месте) вызов метода start_animation, в котором будем анимировать наши две метки.

Animation

Для анимарования объектов в Kivy используется класс Animation. Использовать его очень просто: при инициализации класса Animation вы должны передать в качестве аргументов имена свойств с целевыми значениями, которые будут достигнуты в конце анимации. Например:

 def start_animation(self): # Получаем объекты меток из KV разметки lbl_1 = self.root.ids.lbl_1 lbl_2 = self.root.ids.lbl_2 # Анимация первой метки Animation( opacity=1, # анимация прозрачности до значения 1 y=lbl_1.height * 2, # анимация положения виджета по оси Y d=0.9, # время выполнения анимация t="in_out_back" # тип анимации ).start(lbl_1) # в метод start передаем объект, который нужно анимаровать # Анимация второй метки Animation( opacity=1, y=lbl_2.height + lbl_1.height, d=1, t="in_out_back" ).start(lbl_2) 

На нижеследующей анимации я продемонстрировал результат простейшей анимации, которую мы создали, с разными типами анимирования:

Давайте немного усложним задачу и попробуем анимировать вращение меток на плоскости. Для этого будем использовать матричные манипуляции (PushMatrix, PopMatrix, Rotate, Translate, Scale). Добавим к общей метке инструкции canvas:

 angle: 180 # значение вращения [. ] canvas.before: PushMatrix Rotate: angle: self.angle origin: self.center canvas.after: PopMatrix 

А в Python коде в класс Animation передадим новое свойство angle для анимации:

 def start_animation(self): lbl_1 = self.root.ids.lbl_1 lbl_2 = self.root.ids.lbl_2 Animation(angle=0, [. ]).start(lbl_1) Animation(angle=0, [. ]).start(lbl_2) 

Добавим анимирование масштаба меток:

 scale: 5 # значение масшбирования [. ] canvas.before: PushMatrix [. ] Scale: # масштабирование по трем осям x: self.scale y: self.scale z: self.scale origin: self.center canvas.after: PopMatrix 

В Python коде в класс Animation передадим новое свойство scale для анимации:

 def start_animation(self): lbl_1 = self.root.ids.lbl_1 lbl_2 = self.root.ids.lbl_2 Animation(scale=1, [. ]).start(lbl_1) Animation(scale=1, [. ]).start(lbl_2) 

Класс Animation имеет ряд событий для отслеживания процесса анимации: on_start, on_progress, on_complete. Рассмотрим последний. on_complete вызывается в момент завершения процесса анимации. Привяжем это событие к методу complete_animation, который мы сейчас создадим:

[. ] class TestAnimation(MDApp): [. ] def complete_animation(self, animation, animated_instance): """ :type animation: :type animated_instance: > """ # Анимируем масштаб и цвет первой метки. Animation(scale=1.4, d=1, t="in_out_back").start(animated_instance) Animation(color=(1, 0, 1, 1), d=1).start(animated_instance) 
 def start_animation(self): [. ] animation = Animation( angle=0, scale=1, opacity=1, y=lbl_1.height * 2, d=0.9, t="in_out_back" ) animation.bind(on_complete=self.complete_animation) animation.start(lbl_1) [. ] 

На этом пока все. Просили:

Ниже прикрепляю превью Kivy/KivyMD проекта и ссылку на репозиторий, где можно скачать APK и пощупать:

APK можно найти в директории репозитория — StarTest/bin

Добавить комментарий

Ваш адрес email не будет опубликован. Обязательные поля помечены *