Pull to refresh

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

Level of difficultyEasy
Reading time4 min
Views60K

Почему Desktop-приложение на Питоне?

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

Собственно FloatSpinBox
Собственно FloatSpinBox

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

  1. Добавил min и max value - теперь я мог использовать этот класс и для минут и для часов (сначала я просто наспамил несколько классов где вручную установил ограничения для каждого из них)

  2. Реакция на колёсико мышки теперь охватывала весь SpinBox и это было чудесно. Если просто повесить обработчик на self.bind("MouseWheel", self.on_mouse_wheel)" то срабатывание будет только на границах entry и элементах кнопок, что просто ужасно.

  3. Ну и конечно реализовал прокрутку в обратную сторону. Это так странно делать то что обычно реализовано уже за тебя.

    Ну и немного поиграл с темами самого customtkinter:

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

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

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

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

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

Sample Customtkinter но с Pywinstyles
Sample Customtkinter но с Pywinstyles

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

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

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

Выводы

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

Потрогать версию без pywinstyles можно тут

Tags:
Hubs:
Total votes 27: ↑25 and ↓2+26
Comments112

Articles