Почему Desktop-приложение на Питоне?
Если Вы, как и я, решили впервые взглянуть в сторону Python после нескольких попыток изучения С++/C# то скорее всего первым проектом станет desktop-приложение. Отходя от темы скажу что тяга к изучению этих языков была безнадежно утрачена в виду классического преподавания в духе "лишь бы сдали" и бесчисленных однотипных и монотонных лекций. Как я сказал выше хоть и на начальном уровне, но я всё же касался разработки приложений для Windows и поэтому мне хотелось посмотреть на принципы работы питона сначала отсюда(а не прыгать в django и прочие мощные фреймворки). Должен предупредить - в статье не приводятся выдержки из кода и она является скорее выражением моих эмоций, полученных за этот проект.
Какое приложение создавать?
В этом я не сомневался ни секунды и сразу выбрал - ТАЙМЕР! Я люблю засыпать под звуки фильмов с различных ресурсов, но то что после их окончания комп работал лишние 6 часов меня решительно не устраивало. Я конечно знаю про существование разного рода приложений с подобным функционалом(например SMtimer), но во-первых его UX/UI это просто привет нулевым, а во-вторых хотелось всё-таки своё.
Задачи намечены - время действовать
Посмотрев полтора гайда с youtube преисполнился и написал первый прототип с использованием стандартной библиотеки tkinter. Выглядело это весьма сомнительно с точки зрения того же UX/UI, но это уже было что-то
Тут каждый может заметить и сказать "но ведь это ещё хуже чем SMtimer" и будут правы, в целом и меня посещали такие мысли и я решил обратиться к поиску чего-то что сможет сделать из этого адекватное приложение которым я смогу пользоваться без зазрения совести.
CustomTkinter или как я пытался познать дзен
После недолгого поиска я нашел его - CustomTkinter. Он обещал буквально сделать из моего прототипа приложение, которое будто изначально было в Windows 10. Непосредственно exampl'ы вы можете смотреть ниже:
Вдобавок к этому библиотека обещала и минимальные правки кода для переноса моего "прототипа" на эту прелесть, но мне предстоял ещё большой путь в понимании как это тут работает...
Куча проблем и нехватка понимания
Именно так бы я описал свой путь в познании этой библиотеки. Буквально пытаясь взаимодействовать с ней я понял как устроены типы данных Python(да, может показаться смешным, но когда впервые встречаешь NoneType слегка удивляешься), понял как взаимодействовать с объектами классов и собственно разделять код проекта на функциональные блоки (что до этого мне казалось чем-то странным). Но для того чтобы понять насколько всё было грустно в моих познаниях - вот референс который я запилил от безысходности( на тот момент я хотел получить хотя бы это):
Проблем была целая гора - я решительно не мог понять как общаться с CusomTkinter - создание и позиционирование его объектов хоть сейчас и кажутся достаточно логичными и понятными, но тогда они были для меня сродни китайским иероглифам. После нескольких вечеров, проведённых за курением мануалов я смог собрать 3ю версию (её первая реинкарнация):
Получив это я уже был рад, что не сдался и приступил к починке расположения всех объектов по экрану. Однако следует упомянуть о "маленькая проблема" - в CustomTkinter нет SpinBox, а значит вводить данные было нужно либо с клавиатуры, либо искать как сделать этот самый SpinBox самому. Выбор пал на второй вариант, на сайте, посвященном самому ctk автор сделал FloatSpinBox, доработав который я уже мог получить то что хотел.
Главным его косяком было отсутствие реакции на колёсико мышки - для меня это было критично - нажимать 32 раза для установки минут меня не прельщало и я решил допилить его самостоятельно:
Добавил min и max value - теперь я мог использовать этот класс и для минут и для часов (сначала я просто наспамил несколько классов где вручную установил ограничения для каждого из них)
Реакция на колёсико мышки теперь охватывала весь SpinBox и это было чудесно. Если просто повесить обработчик на self.bind("MouseWheel", self.on_mouse_wheel)" то срабатывание будет только на границах entry и элементах кнопок, что просто ужасно.
Ну и конечно реализовал прокрутку в обратную сторону. Это так странно делать то что обычно реализовано уже за тебя.
Ну и немного поиграл с темами самого customtkinter:
Наконец то, что я и хотел получить
Теперь я решил сделать вывод времени до срабатывания. Я прорабатывал разные версии этого таймера и пришел к тому что запилил TimeBox. Главное отличие - никаких кнопок. Вывод конечно же стал гораздо веселее.
После того как я насмотрелся на кастомные темы с просторов github я решил, что мне такого ужаса точно не нужно и вернулся к истокам - стандартной зелёной теме. Победив эффект циклопа (даже 3х) я добавил переключение тем и поправил логику приложения - перезагрузка. выключение, сон и блокировка работают на ура ну и два вида условий таймера - через промежуток времени и В конкретное время. Я был полностью доволен и буквально счастлив что теперь мне не нужно каждый день идти в планировщик заданий и выставлять время выключения вручную! Но тут я увидел то, что впоследствии переведет меня из Notepad++ (да, да, именно там я и писал свой проект до этого момента) в PyCharm. Это была библиотечка pywinstyles, обещающая эффекты прозрачности как из win7 но в стиле десятки. То что нужно.
Мне показалось это просто идеальным дополнением моей програмки. Запускаешь поверх фильма и не мешает и знаешь сколько времени осталось - красота. Но полное отсутствие документации и внятных sampl'ов заставило заново пересмотреть перспективы проекта. Я написал автору pywinstyles и с его описанием я таки смог заставить работать это всё вместе:
Если тут есть такие же странные люди, которые решат потрогать pywinstyles - будьте готовы к множеству проблем. К примеру после смены темы на прозрачную назад вернуть никак. Только перезапуск. У main_frame от ctk тут беловатый фон, что заставляет программу "сиять" на светлых фонах.
Выводы
Я получил то, что хотел и кучу необходимого опыта сверху. В будущем хочу реализовать автоматическую остановку таймера. В случае если фильм ставиться на паузу то и сам таймер останавливается. Как это реализовать при просмотре фильма из браузера я пока не знаю, но если у Вас есть идеи - с радостью почитаю.