На чем лучше и быстрее написать GUI приложение? — Хабр Q&A
Не слушайте тех, кто Delphi рекомендуют.
1.Оно не развивается (юникод в 2010(или 2009) году только добавили!).
2.Оно таки мало того, что проприетарное, так еще и платное!
Насчет С++, то ни в коем случае не пробуйте юзать Visual Studio и всякие извращения типа MFC, только мозг вынесете себе и возненавидите плюсы, от которых там по правде говоря только название.
Что остается?
Nokia Qt, причем можно как на C++ кодить, так и на любимых ruby,python.
C# WPF, тут уж за меня все расскажут.
Остальное не стоит внимания, имхо.
Ответ написан
А почему через web нельзя всё реализовать? Кроссплатформенность будет и везде доступно))
Ответ написан
Если нет жестких требований по проиводительности, то я бы советовал WPF (или Silverlight если готовы пожертвовать частью возможностей ради макоси и работы из браузера).
C# гораздо проще и развивается куда динамичнее чем C++. Хотя почитать Рихтера со временем все равно стоит, так как простые и лаконичные куски кода на C# иногда оказываются чудовищно неэффективными.
Ответ написан
Комментировать
Лично мне сложно представить себе что-то удобнее и проще C# WinForms. Если задача стоит действительно «здесь и сейчас», то, imho, надо выбирать этот вариант. Если учиться на перспективу с целью научиться чему-то новому и интересному, я бы выбрал WPF. Со стратегической точки зрения наверно правильнее всего освоить какой-нибудь хороший Javascript UI toolkit и делать всё на web-интерфейсах.
Ответ написан
Если нужно быстро написать:
То C# плюс WPF.
А если время для разработки есть, плюс желание — то Питон, либо Руби можно попробовать)
Ответ написан
Комментировать
Если у вас стоит задача написать простую программку, и при это вам хотелось бы изучить что-то новое и вы знаете Ruby, то я бы посоветовал попробовать IronRuby — это возможность писать приложение на знакомом уже вам языке, но при этом познакомиться с мощью платформы .
Ответ написан
Можно конечно начать учить Java, C# или C++, но это на мой взгляд будет слишком трудозатратно для такой задачи.
Ответ написан
Комментировать
Мой выбор: Nokia Qt. Сейчас этот фреймворк очень сильно вырос и позволяет просто делать сложные вещи.
Ответ написан
Просто интересно, почему вы не рассматриваете тот же Delphi как кандидата? По крайней мере в тексте вопроса я не нашел прямых противопоказаний. Единственное ограничение, мультиплатформенность. Но под тем же Linux несложноя дельфевая программа под Wine пойдет без проблем.
Ответ написан
Комментировать
Каждый кулик хвалит свое болото 🙂
Если надо быстро и хорошо надо использоваться готовый framework. Тормозить может все, если его накормить «фантой». В вашем случае qt, думаю, будет лучшим выбором.
Ответ написан
Комментировать
Delphi?
Java (SWT)?
dotNet (любой язык из семейства, какой ближе)?
Ответ написан 2010, в 06:15″> более трёх лет назад
Зависит от задачи: если Вам нужно просто быстро написать приложение — нужно взять знакомый инструмент, который Вы уже знаете, т.е. Дельфи. Если изучить что-то новое, то Питон, думаю, будет вполне хорошим вариантом, т.к. на нем можно и десктопные приложения писать и как серверный вариант использовтаь, т.е. приобретенный опыт будет весьма полезным.
Ответ написан
Всё зависит от целей разработки: Если нужно дёшево и сердито, то
Писать стоит на том, что лучше всего знаешь для целевой платформы, или что быстрее всего можно выучить. Для винды с установленным офисом — MS Access — всё в одном файле, при желании можно и к SQL серверу клиент подключить или к файл-серверу, можно распространять как один файл в виде приложения для Access Runtime — без установки самого Аксеса.
Если нужно писать ради изучения чего-то нового, то посмотреть, разработчикам на какой платформе больше платят или какие разработчики чаще требуются на сайтах фрилансеров и поиска работы.
Ответ написан
Не очень давно нечто подобное спрашивал На чем написать програмку?
Ответ написан
Комментировать
Универсальный GUI / Хабр
Здравствуйте! Меня зовут Халитов Кирилл, я аспирант из МГУДТ (Московский государственный университет дизайна и технологии (МГУДТ) ). В моей диссертации возникла задача упростить процесс создания интерфейса для локального и веб-приложения и в итоге получился сабж.
Введение
В настоящее время любая современная мониторинговая система включает в себя прикладное программное обеспечение (ПО) для визуализации данных. Как правило, запуск этого ПО предполагает наличие рекомендуемой операционной системы (ОС), в большинстве своих случаев ОС компании Microsoft. Однако сейчас наблюдается тенденция использования кроссплатформенных средств для разработки ПО. В результате этого появляется возможность запуска готового программного продукта на разных ОС, включая и мобильные ОС.
Кроме того, в связи с бурным распространением интернета популярным направлением разработки ПО стала разработка веб-приложений или веб-сервисов. Веб-приложение является полезным дополнением к клиентской прикладной программе (приложению). Обычно веб-приложение даёт возможность удалённого использования мониторинговой системы. Это означает, что пользователь не привязан к месту расположения аппаратной части мониторинговой системы и может использовать её из любой точки мира, где есть рекомендуемое интернет-соединение.
Современные способы построения интерфейсов
Рассмотрим наиболее популярные в настоящий момент способы построения интерфейсов клиентских приложений на языке C++, как наиболее используемом для разработки ПО, для ОС Microsoft Windows (MS Windows) и ОС Linux. Главным средством разработки ПО для MS Windows является MS Visual Studio [1]. Эта интегрированная среда разработки (IDE) позволяет разрабатывать ПО на разных языках программирования, но основными языками, конечно, являются C++ и C#. Для разработки интерфейса приложения имеются два основных средства — Windows Forms (WinForms) и Windows Presentation Foundation (WPF). Большая часть существующих приложений для MS Windows разработана с использованием WinForms, однако с появлением более современных версий ОС (MS Windows 7, 8), система WPF становится более популярной. Кроме того, последние версии MS Visual Studio позволяют использовать язык разметки HTML5 для построения интерфейсов, близких по стилю к нативным веб-приложениям. Однако стоит заметить, что коммерческая лицензия MS Visual Studio является платной, как и лицензия MS Windows, что несомненно является недостатком для низкобюджетных проектах.
Если говорить о низкобюджетных проектах, то тут наиболее подходящим вариантом является ОС Linux. Помимо того, что большинство дистрибутивов этой ОС являются абсолютно бесплатными, в том числе и для коммерческого использования, также имеется ряд бесплатных средств для разработки качественного ПО для ОС Linux. Самым распространённым средством для разработки ПО на языке С++ является кроссплатформенный инструментарий Qt [2]. Важно подчеркнуть, что Qt позволяет разрабатывать приложения не только для ОС Linux, но и для MS Windows, Mac OS X, Android и других UNIX-подобных ОС. Разработчики Qt предлагают как бесплатную для коммерческого использования, так и платную лицензию с дополнительными возможностями. Но исходя из современной практики разработки ПО с помощью этого инструментария, бесплатной лицензии оказывается больше чем достаточно.
Если проводить аналогию с MS Visual Studio, то в Qt мы имеем IDE Qt Creator. Здесь альтернативой WinForms являются так называемые виджеты (Qt Widgets), а альтернатива для WPF — Qt Quick. Также в Qt Creator имеется возможность создания интерфейсов на основе HTML5. Но наиболее интересным модулем инструментария является встраиваемый веб-движок WebKit, который лежит в основе всех современных веб-браузеров. Подобный модуль имеется и в MS Visual Studio, но он имеет ряд ограничений, и тем более нас больше интересуют низкобюджетные средства, которые позволяют уменьшить издержки при создания программного продукта. Веб-движок — это ядро браузера, он отвечает за правильное отображения веб-страниц. Модуль Qt WebKit позволяет создавать интерфейс клиентского приложения с использованием техники разработки интерфейсов веб-приложений. В основе создания интерфейса веб-приложения лежит устоявшийся стек технологий. Он включает язык разметки HTML (HTML 4, 5), каскадные таблицы стилей (CSS 2, 3) и скриптовый язык JavaScript с богатым выбором дополнительных библиотек (каркасов). Отдельного внимания заслуживает тот факт, что скорость появления новых полезных каркасов для языка JavaScript стремительно растёт, а это делает разработку, насыщенных функционалом приложений, более быстрой и удобной.
Теперь решение проблемы создания универсального GUI лежит на поверхности, но это только на первый взгляд.
Традиционный способ: Qt WebKit + Qt-костыли
Рассмотрим традиционный способ создания универсального GUI с помощью модуля Qt WebKit на примере модуля визуализации данных системы акустического мониторинга, разрабатываемой в рамках кандидатской диссертационной работы [3]. Под системой акустического мониторинга подразумевается система, включающая аппаратную и программную части. Аппаратная часть системы состоит из сенсорной сети акустических датчиков, данные с которых обрабатываются на микроконтроллере и отправляются по какому-либо интерфейсу (UART, IEEE 802.X и др.) на персональный компьютер (ПК). Программная часть состоит из набора прикладных программ, работающих как на локальном ПК (клиентское ПО), так и на удалённом сервере (серверное ПО).
Традиционный метод подразумевает использование межпроцессного
Рис. 1. Традиционный метод реализации универсального GUI
взаимодействия по средствам встроенного механизма Qt. Здесь подразумевается взаимодействие между основной логикой клиентского приложения, изображённой на рис.1 как Обработчик данных, и GUI-элементом. Одним из недостатков такого подхода является то, что код для реализации GUI на языке JavaScript будет иметь специфические функции, которые будут актуальны только для клиентского Qt-приложения. Для серверного приложения, отвечающего за GUI, нужен будет другой, специфичный для серверной реализации, код. Например, в случае использования PHP-скрипта для реализации основной логики серверного приложения, понадобится реализация межпроцессного взаимодействия с помощью какой-либо другой технологии (AJAX или WebSocket). Отсюда следует ещё один недостаток, а именно использование дополнительного языка программирования для реализации основной логики серверного приложения и разработка нового алгоритма межпроцессного взаимодействия.
Более интересный подход: Qt WebKit + WebSocket
Для решения этих проблем предлагается новый метод, основанный на использования упомянутой выше технологии WebSocket. Суть метода заключается в том, чтобы унифицировать метод межпроцессного взаимодействия между основной логикой приложения и GUI, как на клиентской стороне, так и на серверной. В этом случае появляется возможность использования JavaScript кода для реализации универсального для обеих сторон GUI.
Рис. 2. Новый метод реализации универсального GUI
На рис. 2. видно, что теперь для межпроцессного взаимодействия, как для клиентской, так и для серверной части используется технология WebSocket. То есть теперь мы имеем один универсальный JavaScript код для разных приложений. В этом случае необходимым условием является серверное приложение, основная логика которого реализована с помощью Qt, на не совсем привычном для веб-разработчиков, языке C++. С одной стороны такой подход к реализации серверного приложения усложняет задачу для узкоспециализированного веб-разработчика. Но с другой стороны мы имеем универсальные части кода, которые позволяют нам сэкономить время на дублировании одних и тех по смыслу алгоритмов на разных языках. Важно также подчеркнуть, что для использования технологии WebSocket необходима дополнительная библиотека, которая имеется в интернете в свободном доступе или включается по умолчанию в более поздние версии Qt.
Рис. 3. Локальное (справа) и серверное (слева) приложения, запущенные на ОС Ubuntu 14. 04
На рис. 3 приведён пример реализации нового метода создания универсального GUI для ОС Ubuntu 14.04. Как видно на рисунке, в конечном итоге мы получаем универсальный интерфейс, как для локального приложения, запущенного в качестве исполняемого файла ОС, так и для серверного приложения, запущенного в современном веб-браузере. Так как для разработки ПО используются кроссплатформенные инструменты, это позволяет говорить о простой переносимости программного продукта на другие ОС в будущем.
Список литературы
1. Qt Documentation [Электронный ресурс]. Режим доступа: qt-project.org/doc
2. Visual Studio Library [Электронный ресурс]. Режим доступа: msdn.microsoft.com/en-us/library/vstudio
3. Молодые учёные – развитию текстильно-промышленного кластера (ПОИСК — 2014): сборник материалов межвузовской научно-технической конференции аспирантов и студентов с международным участием. Ч. 2. – Иваново: Иванов. гос. политехн. Ун-т, 2014. — С. 25 [Электронный ресурс]. Режим доступа: ti.ivgpu.com/poisk/file/part_2.pdf
P.S. Единственное, что на картинке бросается в глаза — это разные шрифты, но мне, честно говоря, тогда было не до них.
P.P.S. Можно ли запатентовать этот способ, чтобы на защите было чем козырнуть кроме свидетельства о регистрации ПО?
Запуск приложений графического пользовательского интерфейса Linux с помощью WSL
- Статья
- Чтение занимает 3 мин
подсистема Windows для Linux (WSL) теперь поддерживает запуск приложений графического пользовательского интерфейса Linux (X11 и Wayland) в Windows в полностью интегрированном интерфейсе рабочего стола.
WSL 2 позволяет приложениям графического интерфейса Linux чувствовать себя собственными и естественными для использования в Windows.
- Запуск приложений Linux из меню «Пуск» Windows
- Закрепление приложений Linux на панели задач Windows
- Переключение между приложениями Linux и Windows с помощью alt-tab
- Вырезать и вставить в приложениях Windows и Linux
Теперь вы можете интегрировать приложения Windows и Linux в рабочий процесс для эффективного рабочего стола.
Установка поддержки приложений графического пользовательского интерфейса Linux
Предварительные требования
Для доступа к этой функции потребуется Windows 11 сборке 22000 или более поздней версии.
Установленный драйвер для VGPU
Чтобы запустить приложения графического пользовательского интерфейса Linux, необходимо сначала установить драйвер, соответствующий вашей системе ниже. Это позволит использовать виртуальный GPU (vGPU), чтобы воспользоваться преимуществами аппаратного ускорения отрисовки OpenGL.
- Intel Драйвер GPU для WSL
- AMD Драйвер GPU для WSL
- NVIDIA Драйвер GPU для WSL
Новая установка — нет предыдущей установки WSL
Теперь вы можете установить все необходимое для запуска подсистемы Windows для Linux (WSL), введя эту команду в PowerShell от имени администратора или командной строке Windows, а затем перезапустив компьютер.
wsl --install
После завершения перезагрузки компьютера установка продолжится, и вам будет предложено ввести имя пользователя и пароль. Это будут ваши учетные данные Linux для дистрибутива Ubuntu.
Теперь вы готовы приступить к использованию приложений графического пользовательского интерфейса Linux в WSL!
Дополнительные сведения см. в статье об установке WSL.
Существующая установка WSL
Если на компьютере уже установлен WSL, можно обновить до последней версии, которая включает поддержку графического пользовательского интерфейса Linux, выполнив команду обновления из командной строки с повышенными привилегиями.
Выберите «Пуск», введите PowerShell, щелкните правой кнопкой мыши Windows PowerShell и выберите «Запуск от имени администратора«.
Введите команду обновления WSL:
wsl --update
Чтобы обновление вступило в силу, необходимо перезапустить WSL. Вы можете перезапустить WSL, выполнив команду завершения работы в PowerShell.
wsl --shutdown
Примечание
Приложения графического пользовательского интерфейса Linux поддерживаются только с WSL 2 и не будут работать с дистрибутивом Linux, настроенным для WSL 1. Узнайте , как изменить распределение с WSL 1 на WSL 2.
Запуск приложений с графическим пользовательским интерфейсом Linux
Чтобы скачать и установить эти популярные приложения Linux, можно выполнить следующие команды из терминала Linux. Если вы используете дистрибутив, отличный от Ubuntu, он может использовать другой диспетчер пакетов, отличный от apt. После установки приложения Linux его можно найти в меню «Пуск » под именем дистрибутива. Например:
Ubuntu -> Microsoft Edge
.
Примечание
Поддержка приложений графического пользовательского интерфейса в WSL не обеспечивает полнофункциональный интерфейс рабочего стола. Он использует классический компьютер Windows, поэтому установка средств или приложений, ориентированных на настольные компьютеры, может не поддерживаться. Чтобы запросить дополнительную поддержку, можно отправить проблему в репозитории WSLg на GitHub.
Обновление пакетов в дистрибутиве
sudo apt update
Установка Gedit
Gedit — это текстовый редактор по умолчанию в классической среде JSON.
sudo apt install gedit -y
Чтобы запустить файл bashrc в редакторе, введите: gedit ~/.bashrc
Установка GIMP
GIMP — это бесплатный и растровый графический редактор с открытым кодом, используемый для обработки изображений и редактирования изображений, рисования свободной формы, перекодирования между различными форматами файлов изображений и более специализированными задачами.
sudo apt install gimp -y
Чтобы запустить, введите: gimp
Установка Nautilus
Nautilus, также известный как ФАЙЛЫ GNOME, является диспетчером файлов для рабочего стола GPU. (Аналогично Windows проводник).
sudo apt install nautilus -y
Чтобы запустить, введите: nautilus
Установка VLC
VLC — это бесплатный и открытый код кроссплатформенный мультимедийный проигрыватель и платформа, которая воспроизводит большинство мультимедийных файлов.
sudo apt install vlc -y
Чтобы запустить, введите: vlc
Установка приложений X11
X11 — это система окон Linux, и это разное семейство приложений и инструментов, которые поставляются с ним, например xclock, xcalc calculator, xclipboard для вырезания и вставки, xev для тестирования событий и т. д. Дополнительные сведения см. в x.org документации .
sudo apt install x11-apps -y
Чтобы запустить, введите имя средства, который вы хотите использовать. Пример:
xcalc
,xclock
,xeyes
Установка Google Chrome для Linux
Чтобы установить Google Chrome для Linux, выполните следующие действия.
- Измените каталоги в папку temp:
cd /tmp
- Используйте wget для скачивания:
sudo wget https://dl.google.com/linux/direct/google-chrome-stable_current_amd64.deb
- Получите текущую стабильную версию:
sudo dpkg -i google-chrome-stable_current_amd64.deb
- Исправление пакета:
sudo apt install --fix-broken -y
- Настройте пакет:
sudo dpkg -i google-chrome-stable_current_amd64.deb
Чтобы запустить, введите: google-chrome
Установка Microsoft Teams для Linux
Чтобы установить Microsoft Teams для Linux, выполните следующее:
- Измените каталоги в папку temp:
cd /tmp
- Используйте curl для скачивания пакета:
sudo curl -L -o ".
/teams.deb" "https://teams.microsoft.com/downloads/desktopurl?env=production&plat=linux&arch=x64&download=true&linuxArchiveType=deb"
- Используйте apt для установки:
sudo apt install ./teams.deb -y
Чтобы запустить, введите: teams
Установка браузера Microsoft Edge для Linux
Сведения об установке браузера Microsoft Edge для Linux с помощью командной строки на сайте предварительной оценки Edge. Выберите » Получить инструкции» в разделе установки командной строки на странице.
Чтобы запустить, введите: microsoft-edge
Устранение неполадок
Если у вас возникли проблемы с запуском приложений графического пользовательского интерфейса, сначала ознакомьтесь с этим руководством: диагностика проблем с типом «не удается открыть отображение» с WSLg
А чем Qt не понравился? По-моему, он прекрасен.
Я работал в основном с биндингами к Питону. ИМХО. Невероятно сложная и глючная хрень. Особенно если люди пишут на сигналах, а не на моделях. Получить циклический граф вызовов — фигня. Отладка ? Какая отладка. QVariant, блин, ненавижу. Индексы в моделях — я не знаю какой извращенец их придумал. Нативного вида нет ни на линуксе ни на винде. Перевод вообще эпичен. Ну т.е. да с нуля писать дольше. Но геммороя все равно хватает. Веб в этом отношении куда как разумнее и понятнее.
debugging sucks testing rocks, но если сильно надо то в хроме все сейчас норм с дебаггингом.
Уже давно пришел я к выводу, что весь гуй надо писать на вебе (html, js), а функциональность на бакенде. И даже локальную инсталляцию разбивать на эти два кусочка. Впервые это я увидел в гугловском локальном поиске, который был выкачен этак лет 10 назад, и с тех пор забыт. Так с тех пор сам и делаю.
Знакомая дилемма. Сейчас кажется популярно бандлить Хромиум с сервером в одном приложении, для этого какие-то тулы были.
С UI/UX беда, никто его не умел и не умеет делать. А на мобильниках вообще аховая ситуация. НИЧЕГО ХОРОШЕГО НЕТ НУ ВООБЩЕ. Особенно если мутить что-то кроссплатформенное, игры там тырыпыры. Давным-давно, в году где-то 2000-ом был у нас один веб-магазин на PHP. Заказчику срочно понадобилась оффлайн версия, каталог на CD, для понтов и презентаций. Сваял за неделю на Delphi, весь дизайн HTML-ный показывался через хитровыеб@ный ActiveX в окне IE4. MySQL базу конвертнули в .dbf-ки, каким-то макаром даже SQL запросы работали, практически без изменений, и главное весь этот глюкодром даже работал, причем с сюдюка.
Делать как HTML5 + js, компилировать в приложение с помощью http://electron.atom.io/ Какой конкретно фреймворк использовать для гуя – сложно сказать, не зная задачи и твоих скиллов/пристрастий.
Да, я про Электрон читал на Хабре, его сравнивали с более старым фреймворком такого типа NW.js (node-webkit) https://habrahabr.ru/post/304574/, плюсов больше набрал Электрон. Можно ещё такой финт на тему «выглядящего нативно» (то есть без HTML, JS управляет платформно-специфичным маркапом, который надо делать отдельно для мобильных платфом iOS / Android / Windows Universal, то есть Windows 10): забить на «десктоповость» и взять мобильный фреймворк React Native или NativeScript. Под Windows 10 запускать результирующее приложение как Windows Store приложение. Дима, если ты это читаешь — кроме рассматриваемой идеи JS-приложения имей так же в виду Xamarin (кроссплатформенный С#), он нынче бесплатный extension к Visual Studio 2015. Unity — тоже кроссплатформенный C#, но это коммерческий продукт (и я не знаю, как там с библиотеками контролов, это игровая платформа в первую очередь). Если всё-таки выберешь JS… Я лично, если буду когда-либо что-либо делать на JS, буду с самого начала использовать TypeScript. У NativeScript он с самого начала хорошо прикручен, но, по идее, прикрутить можно где угодно с компиляцией в JS. Коррекция: я писал выше «Windows 10» как синоним «Universal Windows», однако возможность строить «Universal Windows» приложения для Windows Store появилась в Windows 8.1. Это мелочи, поскольку Windows-телефонами никто не пользуется (и, вероятно, они умрут, но ещё не умерли). Edited at 2016-07-29 02:45 am (UTC)
спасибо за линки, очень интересно!
Это вприглядку в основном — на практике я установил и пособирал в разных конфигурациях React Native для Windows Store в рамках короткого экспериментального проектика.
Насчёт TS/NS – по-моему, вы зря продвигаете технологии, которыми сами не пользуетесь. TS в маленьких проектах, делаемых в одно лицо – просто лишний слой. «В гамаке и скафандре», да. Насчёт NS – там всё грустно с поддерживаемыми гуёвыми контролами. Начинать с них точно не стóит.
конкретнее про мой опыт с TS версус JS. Я писал три года назад на JS в Visual Studio апп для Windows Store среднего размера в команде человек пять и чувствовал себя очень некомфортно, собирался переводить на TS, но проект закончился раньше. Года два назад помогал школьнику с маленьким проектиком и тоже почувствовал себя легче с TS. С тех пор JS обновился, и среду разработки можно выбрать более дружественную к JS, но мне лично этот лишний слой при работе с Visual Studio был нужен.
> но мне лично этот лишний слой при работе с Visual Studio был нужен Рискну предположить, что дело не в VS, а в привычке писать в ООП-стиле. Общепринято считается, что мире JS такой подход (за редкими исключениями) всё таки даёт больше ограничений, чем преимуществ. Скромное распространение TS, особенно если учесть мощь вендора – дополнительный (хотя и небесспорный) аргумент в пользу того, что накладываемые ограничения серьёзно обесценивают ООП-шные плюшки. > Расскажите поподробнее про Электрон, вы с ним работаете Тут надо сравнить nw.js и Электрон, по-хорошему то, и объяснить, почему я посоветовал Электрон. Мы не делаем десктопные/мобильные приложения на заказ, поэтому с Электроном я только вдумчиво баловался. С nw.js всё чуть серьёзнее, его мы используем в боевых условиях, но не как обёртку для изготовления стэндэлон-приложений. То-есть, приложения я с ним делал, но тоже в рамках вдумчивого «поиграться». В силу того, что я занимаюсь по преимуществу гуем или тем, у чего есть гуй и он важен, я, конечно, пробовал обернуть уже имеющийся код сложных гуёвых разработок. С Электроном порог входа из точки «вот у меня есть html+js+css, сделай десктопное приложение» чуть выше, чем с nw.js. Тем не менее, после прохождения порога дальше телодвижений точно меньше. Отладка приложений, сделанных из такой начальной точки, одинаково комфортная в обоих случаях. Дима, скорее всего, будет в это всё погружаться из другой начальной точки.
Да, это был ООП-стиль — во-первых, в обоих случаях обстоятельства диктовали; во-вторых, у меня нет опыта программирования в другом стиле. Спасибо за информацию про Электрон / nw.js! Попробую найти время / силы поиграться с Электроном.
А после отладки в браузере — нет проблем приклеить вместо html-рендера какой-нибудь другой, если так будет сильно лучше для конкретной платформы (это сможет сделать даже другой человек).
Эта идея мягко говоря не нова. Я сейчас лоббирую переписывание нашей программы с PyQt4 на embedded Chrome + react.js + HTML https://github.com/cztomczak/cefpython Тем более что мы параллельно все равно разрабатываем интерфейс для веба. Вебсервер необязателен, так как можно вызывать функции из javascript нативно. IDE отладка и тестирование для веб-интерфейса, на голову превосходят все что есть для отладки GUI не под javascript. | |||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
создаём простое приложение с PyQt и Qt Designer
Эта статья предназначена для тех, кто только начинает своё знакомство с созданием приложений с графическим интерфейсом (GUI) на Python. В ней мы рассмотрим основы использования PyQt в связке с Qt Designer. Шаг за шагом мы создадим простое Python GUI приложение, которое будет отображать содержимое выбранной директории.
Что нам потребуется
Нам понадобятся PyQt и Qt Designer, ну и Python, само собой.
В этой статье используется PyQt5 с Python 3, но особых различий между PyQt и PySide или их версиями для Python 2 нет.
Windows: PyQt можно скачать здесь. В комплекте с ним идёт Qt Designer.
macOS: Вы можете установить PyQt с помощью Homebrew:
$ brew install pyqt5
Скачать пакет с большинством компонентов и инструментов Qt, который содержит Qt Designer, можно по этой ссылке.
Linux: Всё нужное, вероятно, есть в репозиториях вашего дистрибутива. Qt Designer можно установить из Центра Приложений, но PyQt придётся устанавливать через терминал. Установить всё, что нам понадобится, одной командой можно, например, так:
# для Fedora: $ sudo dnf install python3-qt5 qt-creator # для Debian/Ubuntu: $ sudo apt install python3-qt5 pyqt5-dev-tools qtcreator
После того как вы закончили с приготовлениями, откройте командную строку/терминал и убедитесь, что вы можете использовать команду pyuic5
. Вы должны увидеть следующее:
$ pyuic5 Error: one input ui-file must be specified
Если вы видите сообщение, что такой команды нет или что-то в таком роде, попробуйте загуглить решение проблемы для вашей операционной системы и версии PyQt.
Если вы используете Windows, то, скорее всего, путь C:\Python36\Scripts
(измените 36
на вашу версию Python) не прописан в вашем PATH
. Загляните в этот тред на Stack Overflow, чтобы узнать, как решить проблему.
Дизайн
Основы
Теперь, когда у нас всё готово к работе, давайте начнём с простого дизайна.
Откройте Qt Designer, где вы увидите диалог новой формы, выберите Main Window и нажмите Create.
После этого у вас должна появиться форма — шаблон для окна, размер которого можно менять и куда можно вставлять объекты из окна виджетов и т.д. Ознакомьтесь с интерфейсом, он довольно простой.
Теперь давайте немного изменим размер нашего главного окна, т. к. нам не нужно, чтобы оно было таким большим. А ещё давайте уберём автоматически добавленное меню и строку состояния, поскольку в нашем приложении они не пригодятся.
Все элементы формы и их иерархия по умолчанию отображаются в правой части окна Qt Designer под названием Object Inspector. Вы с лёгкостью можете удалять объекты, кликая по ним правой кнопкой мыши в этом окне. Или же вы можете выбрать их в основной форме и нажать клавишу DEL на клавиатуре.
В итоге мы имеем почти пустую форму. Единственный оставшийся объект — centralwidget
, но он нам понадобится, поэтому с ним мы ничего не будем делать.
Теперь перетащите куда-нибудь в основную форму List Widget (не List View) и Push Button из Widget Box.
Макеты
Вместо использования фиксированных позиций и размеров элементов в приложении лучше использовать макеты. Фиксированные позиции и размеры у вас будут выглядеть хорошо (пока вы не измените размер окна), но вы никогда не можете быть уверены, что всё будет точно так же на других машинах и/или операционных системах.
Макеты представляют собой контейнеры для виджетов, которые будут удерживать их на определённой позиции относительно других элементов. Поэтому при изменении размера окна размер виджетов тоже будет меняться.
Давайте создадим нашу первую форму без использования макетов. Перетащите список и кнопку в форме и измените их размер, чтобы вышло вот так:
Теперь в меню Qt Designer нажмите Form, затем выберите Preview и увидите что-то похожее на скриншот выше. Выглядит хорошо, не так ли? Но вот что случится, когда мы изменим размер окна:
Наши объекты остались на тех же местах и сохранили свои размеры, несмотря на то что размер основного окна изменился и кнопку почти не видно. Вот поэтому в большинстве случаев стоит использовать макеты. Конечно, бывают случаи, когда вам, например, нужна фиксированная или минимальная/максимальная ширина объекта. Но вообще при разработке приложения лучше использовать макеты.
Основное окно уже поддерживает макеты, поэтому нам ничего не нужно добавлять в нашу форму. Просто кликните правой кнопкой мыши по Main Window в Object Inspector и выберите Lay out → Lay out vertically. Также вы можете кликнуть правой кнопкой по пустой области в форме и выбрать те же опции:
Ваши элементы должны быть в том же порядке, что и до внесённых изменений, но если это не так, то просто перетащите их на нужное место.
Так как мы использовали вертикальное размещение, все элементы, которые мы добавим, будут располагаться вертикально. Можно комбинировать размещения для получения желаемого результата. Например, горизонтальное размещение двух кнопок в вертикальном будет выглядеть так:
Если у вас не получается переместить элемент в главном окне, вы можете сделать это в окне Object Inspector.
Последние штрихи
Теперь, благодаря вертикальному размещению, наши элементы выровнены правильно. Единственное, что осталось сделать (но не обязательно), — изменить имя элементов и их текст.
В простом приложении вроде этого с одним лишь списком и кнопкой изменение имён не обязательно, так как им в любом случае просто пользоваться. Тем не менее правильное именование элементов — то, к чему стоит привыкать с самого начала.
Свойства элементов можно изменить в разделе Property Editor.
Подсказка: вы можете менять размер, передвигать или добавлять часто используемые элементы в интерфейс Qt Designer для ускорения рабочего процесса. Вы можете добавлять скрытые/закрытые части интерфейса через пункт меню View.
Нажмите на кнопку, которую вы добавили в форму. Теперь в Property Editor вы должны видеть все свойства этого элемента. В данный момент нас интересуют objectName
и text
в разделе QAbstractButton
. Вы можете сворачивать разделы в Property Editor нажатием по названию раздела.
Измените значение objectName
на btnBrowse
и text
на Выберите папку.
Должно получиться так:
Именем объекта списка является listWidget
, что вполне подходит в данном случае.
Сохраните дизайн как design.
в папке проекта. ui
Превращаем дизайн в код
Конечно, можно использовать .ui
-файлы напрямую из Python-кода, однако есть и другой путь, который может показаться легче. Можно конвертировать код .ui
-файла в Python-файл, который мы потом сможем импортировать и использовать. Для этого мы используем команду pyuic5
из терминала/командной строки.
Чтобы конвертировать .ui
-файл в Python-файл с названием design.py
, используйте следующую команду:
$ pyuic5 path/to/design.ui -o output/path/to/design.py
Пишем код
Теперь у нас есть файл design.py
с нужной частью дизайна нашего приложения и мы начинать работу над созданием его логики.
Создайте файл main.py
в папке, где находится design.py
.
Другие интересные статьи по Python.
Используем дизайн
Для Python GUI приложения понадобятся следующие модули:
import sys # sys нужен для передачи argv в QApplication from PyQt5 import QtWidgets
Также нам нужен код дизайна, который мы создали ранее, поэтому его мы тоже импортируем:
import design # Это наш конвертированный файл дизайна
Так как файл с дизайном будет полностью перезаписываться каждый раз при изменении дизайна, мы не будем изменять его. Вместо этого мы создадим новый класс
ExampleApp
, который объединим с кодом дизайна для использования всех его функций:
class ExampleApp(QtWidgets.QMainWindow, design.Ui_MainWindow): def __init__(self): # Это здесь нужно для доступа к переменным, методам # и т.д. в файле design.py super().__init__() self.setupUi(self) # Это нужно для инициализации нашего дизайна
В этом классе мы будем взаимодействовать с элементами интерфейса, добавлять соединения и всё остальное, что нам потребуется. Но для начала нам нужно инициализировать класс при запуске кода. С этим мы разберёмся в функции main()
:
def main(): app = QtWidgets.QApplication(sys.argv) # Новый экземпляр QApplication window = ExampleApp() # Создаём объект класса ExampleApp window.show() # Показываем окно app.exec_() # и запускаем приложение
И чтобы выполнить эту функцию, мы воспользуемся привычной конструкцией:
if __name__ == '__main__': # Если мы запускаем файл напрямую, а не импортируем main() # то запускаем функцию main()
В итоге main.
выглядит таким образом: py
import sys # sys нужен для передачи argv в QApplication from PyQt5 import QtWidgets import design # Это наш конвертированный файл дизайна class ExampleApp(QtWidgets.QMainWindow, design.Ui_MainWindow): def __init__(self): # Это здесь нужно для доступа к переменным, методам # и т.д. в файле design.py super().__init__() self.setupUi(self) # Это нужно для инициализации нашего дизайна def main(): app = QtWidgets.QApplication(sys.argv) # Новый экземпляр QApplication window = ExampleApp() # Создаём объект класса ExampleApp window.show() # Показываем окно app.exec_() # и запускаем приложение if __name__ == '__main__': # Если мы запускаем файл напрямую, а не импортируем main() # то запускаем функцию main()
Если запустить этот код: $ python3 main.py
, то наше приложение запустится!
Но нажатие на кнопку ничего не даёт, поэтому нам придётся с этим разобраться.
Добавляем функциональность в наше Python GUI приложение
Примечание Весь дальнейший код пишется внутри класса ExampleApp
.
Начнём с кнопки Выберите папку. Привязать к функции событие вроде нажатия на кнопку можно следующим образом:
self.btnBrowse.clicked.connect(self.browse_folder)
Добавьте эту строку в метод __init__
класса ExampleApp
, чтобы выполнить привязку при запуске приложения. А теперь взглянем на неё поближе:
self.btnBrowse
: здесьbtnBrowse
— имя объекта, который мы определили в Qt Designer.self
говорит само за себя и означает принадлежность к текущему классу;clicked
— событие, которое мы хотим привязать. У разных элементов разные события, например, у виджетов списка естьitemSelectionChanged
и т.д.;connect()
— метод, который привязывает событие к вызову переданной функции;self.
— просто функция (метод), которую мы описали в классеbrowse_folder
ExampleApp
.
Для открытия диалога выбора папки мы можем использовать встроенный метод QtWidgets.QFileDialog.getExistingDirectory
:
directory = QtWidgets.QFileDialog.getExistingDirectory(self, "Выберите папку")
Если пользователь выберет директорию, переменной directory
присвоится абсолютный путь к выбранной директории, в противном случае она будет равна None
. Чтобы не выполнять код дальше, если пользователь закроет диалог, мы используем команду if directory:
.
Для отображения содержимого директории нам нужно импортировать os
:
import os
И получить список содержимого следующим образом:
os.listdir(path)
Для добавления элементов в listWidget
мы используем метод addItem()
, а для удаления всех элементов у нас есть self.listWidget.clear()
.
В итоге функция browse_folder
должна выглядеть так:
def browse_folder(self): self.listWidget.clear() # На случай, если в списке уже есть элементы directory = QtWidgets.QFileDialog.getExistingDirectory(self, "Выберите папку") # открыть диалог выбора директории и установить значение переменной # равной пути к выбранной директории if directory: # не продолжать выполнение, если пользователь не выбрал директорию for file_name in os.listdir(directory): # для каждого файла в директории self.listWidget.addItem(file_name) # добавить файл в listWidget
Теперь, если запустить приложение, нажать на кнопку и выбрать директорию, мы увидим:
Так выглядит весь код нашего Python GUI приложения:
import sys # sys нужен для передачи argv в QApplication import os # Отсюда нам понадобятся методы для отображения содержимого директорий from PyQt5 import QtWidgets import design # Это наш конвертированный файл дизайна class ExampleApp(QtWidgets.QMainWindow, design.Ui_MainWindow): def __init__(self): # Это здесь нужно для доступа к переменным, методам # и т.д. в файле design.py super().__init__() self.setupUi(self) # Это нужно для инициализации нашего дизайна self.btnBrowse.clicked.connect(self.browse_folder) # Выполнить функцию browse_folder # при нажатии кнопки def browse_folder(self): self.listWidget.clear() # На случай, если в списке уже есть элементы directory = QtWidgets.QFileDialog.getExistingDirectory(self, "Выберите папку") # открыть диалог выбора директории и установить значение переменной # равной пути к выбранной директории if directory: # не продолжать выполнение, если пользователь не выбрал директорию for file_name in os.listdir(directory): # для каждого файла в директории self.
listWidget.addItem(file_name) # добавить файл в listWidget def main(): app = QtWidgets.QApplication(sys.argv) # Новый экземпляр QApplication window = ExampleApp() # Создаём объект класса ExampleApp window.show() # Показываем окно app.exec_() # и запускаем приложение if __name__ == '__main__': # Если мы запускаем файл напрямую, а не импортируем main() # то запускаем функцию main()
Это были основы использования Qt Designer и PyQt для разработки Python GUI приложения. Теперь вы можете спокойно изменять дизайн приложения и использовать команду pyuic5
без страха потерять написанный код.
Перевод статьи «PyQt: Getting started with PyQt and Qt Designer»
Языки программирования для написания GUI-приложения
Вопрос:
Кроме .NET или Java, какой язык можно использовать для написания приложения для Windows и Linux?
Лучший ответ:
Вы можете отменить свой вопрос: какие инструменты имеются, и какие языки они поддерживают?
Пример GTK: (из wikipedia)
C GTK+ C++ gtkmm Ruby ruby-gtk2 Python PyGTK Java java-gnome .NET Gtk# PHP PHP-GTK Perl Gtk2-Perl
Вы можете найти поддержку для многих языков, если вы изучите эти другие инструменты для виджета:
Juce — An extensive cross-platform UI toolkit FLTK — A light, cross platform, non-native widget toolkit FOX toolkit — A fast, open source, cross-platform widget toolkit GTK+ — The GIMP toolkit, a widget toolkit used by GNOME applications IUP_(software) -- IUP cross platform static/dynamic library C/LUA, Lua (MIT) licence JX Application Framework Microsoft Foundation Class - The most commonly used widgeting toolkit for Windows. Motif Object Windows Library & OWLNext Qt — A widget toolkit used by KDE Standard Widget Toolkit — SWT for Java Swing — Java widget toolkit Tk — Toolkit part of the Tcl - project and often used by Perl and Python programmers Ultimate++ Visual Component Library wxWidgets — A free widget toolkit XForms
Ответ №1
С++ с картой Qt: http://qt. nokia.com/products
Ответ №2
Python – отличный вариант для просмотра с PyQT и wxPython в качестве двух широко используемых фреймворков для графических приложений для ПК.
Ответ №3
- Каждый язык программирования (или, точнее, каждый механизм выполнения языка программирования), который может взаимодействовать с собственным кодом, может использоваться для реализации приложений GUI. Это уже включает почти все языки программирования, созданные за последние 60 лет, включая, но не ограничиваясь ими, C, С++, Objective-C, Objective-C ++, D, Eiffel, Fortran, Pascal, Modula, Oberon, Go, Haskell, OCaml, Python, Ruby, Perl, PHP, Tcl, С#, VB.NET, Java, Scala, F #, Newspeak, Animorphic Smalltalk, Eiffel, Lua, Potion, Falcon, Dao, Nimrod, Genie, Vala, Scheme, CommonLisp, Cobol.
- Каждый язык программирования, который работает на платформе Java, может использоваться для написания графических приложений. Это включает около 400 языков, о которых мы публично знаем, плюс кто знает, сколько языков не известно общеизвестно.
В этот список входят Java, Scala, NetRexx, Python, Ruby, PHP, ECMAScript, Groovy, Fan, Clojure, JavaFX, AspectJ, Fortress, Cobol.
- Каждый язык программирования, который работает на платформе CLI и/или .NET(подсказка:.NET не является языком программирования, это маркетинговый термин для комбинации механизма выполнения CIL, реализации CLI, реализации CTS, реализации BCL и фреймворк) можно использовать для написания графических приложений. Это включает около 200 языков, о которых мы публично знаем. Этот список включает С#, VB.NET, F #, Eiffel.NET, SpeС#, Sing #, X #, Polyphonic С#, Cω, Ruby, Python, Perl, Tcl, PHP, С++, SABLE, Scheme, CommonLisp, Clojure, Вентилятор, Scala, Cobol, Cobra, Perl.
- Многие языки программирования привносят свой собственный графический интерфейс для написания графических приложений, например Tcl, Newspeak, Dolphin Smalltalk, Squeak Smalltalk, Delphi, Rebol.
И это только те, которые я мог придумать с головы.
Ответ №4
Ну, вы сказали windows и linux, так что вы всегда можете вернуться на С++. С ним сделано множество хороших приложений для настольных компьютеров.
Ответ №5
Ruby Shoes. Это самый красивый API, который я когда-либо видел, и он работает на Windows, OS X и Linux.
Ответ №6
Любой язык, обеспечивающий доступ к интересующим вас графическим интерфейсам.
Ответ №7
Tcl/Tk
Ответ №8
сборка x86
Ответ №9
Если вы хотите использовать Ruby, попробуйте FXRuby.
Ответ №10
Это действительно зависит от многих факторов, так или иначе, если вы хотите использовать многоплатформенное приложение с собственным пользовательским интерфейсом, я предлагаю вам комбинацию wxWidgets и C/С++ (я использую прямо сейчас).
Ответ №11
Я немного удивлен, что никто не предложил REALbasic, поскольку он в очень схожих ключевых формах с .NET и Java ( IDE, которая очень похожа на кросс-платформу Visual Studio, и которая начиналась как инструмент разработки Java на Mac), не в последнюю очередь, поскольку они регулярно запускают рекламные объявления в Stack Overflow.
Сам язык является “OO VB”. Не совсем VB.NET, но очень похоже. Лично мне не нравится этот язык, но как среда для разработки графических приложений, это очень важно. У него есть некоторые ошибки, но еще быстрее обходить ошибки, чем реализовывать один и тот же интерфейс на 2 или 3 целевых платформах (если ваше приложение не является огромным проектом, который оправдывает создание собственной GUI-инфраструктуры).
Я бы, вероятно, оставил тяжелую работу над внешними компонентами, написанными на C/С++, но у него есть полноценные и очень функциональные API, включая все, от высокоуровневого SOAP-клиента до сырых TCP-сокетов, а также 2D и 3D (включая поверхность OpenGL) API.
Вы также можете использовать Mono – и использовать С#, например, – но с GTK вместо WinForms, используя Mono Develop (I предположите, что это технически это не “.NET”, но вы, возможно, уже рассмотрели его). Для приложений с графическим интерфейсом он довольно зрелый в Windows и Linux, до тех пор, пока вы создаете свое приложение с обеих сторон с самого начала.
Ответ №12
Erlang и его привязки к Wx.
Я не встречал язык, на котором не было привязки к некоторому набору инструментов GUI: если люди заботятся о языке, они строят привязки.
Ответ №13
Одна важная вещь, которую следует учитывать, – это ваш предыдущий опыт, который не является второстепенной темой, потому что освоение языка программирования требует времени.
Сказал так, я люблю Smalltalk в любом вкусе, поэтому вы можете выбрать (в мире Smalltalk):
- Dolphin Smalltalk (является родным Windows, но exes работает на Linux под
Вино) - Visual Works
- Visual Age
- Smalltalk/X
- Писк /Pharo
Они являются основными Smalltalk и называются в определенном порядке.
Ответ №14
В зависимости от того, как вы определяете приложение GUI.
Вы можете использовать HTML/Flash/Flex/JavaScript для создания приложения Adobe AIR, которое может работать как обычное приложение.
Как создать приложение Python с графическим интерфейсом с помощью wxPython — настоящий Python
Существует множество наборов инструментов для графического пользовательского интерфейса (GUI), которые можно использовать с языком программирования Python. Большая тройка — это Tkinter, wxPython и PyQt. Каждый из этих наборов инструментов будет работать с Windows, macOS и Linux, а PyQt имеет дополнительные возможности для работы на мобильных устройствах.
Графический интерфейс пользователя — это приложение, имеющее кнопки, окна и множество других виджетов, которые пользователь может использовать для взаимодействия с вашим приложением. Хорошим примером может быть веб-браузер. Он имеет кнопки, вкладки и главное окно, в котором загружается весь контент.
В этой статье вы узнаете, как создать графический пользовательский интерфейс с помощью Python, используя набор инструментов wxPython GUI.
Вот затронутые темы:
- Начало работы с wxPython
- Определение графического интерфейса пользователя
- Создание каркасного приложения
- Создание рабочего приложения
Начнем учиться!
Начало работы с wxPython
Инструментарий wxPython GUI представляет собой оболочку Python для библиотеки C++, которая называется wxWidgets. Первоначальный выпуск wxPython был в 1998, поэтому wxPython существует довольно давно. Основное отличие wxPython от других наборов инструментов, таких как PyQt или Tkinter , заключается в том, что wxPython по возможности использует настоящие виджеты на собственной платформе. Это делает приложения wxPython естественными для операционной системы, в которой они работают.
PyQt и Tkinter сами рисуют свои виджеты, поэтому они не всегда совпадают с нативными виджетами, хотя PyQt очень близок.
Это не означает, что wxPython не поддерживает пользовательские виджеты. На самом деле в набор инструментов wxPython входит множество пользовательских виджетов, а также десятки основных виджетов. На странице загрузок wxPython есть раздел под названием 9.0007 Дополнительные файлы , которые стоит проверить.
Здесь находится загрузка демонстрационного пакета wxPython. Это милое маленькое приложение, демонстрирующее подавляющее большинство виджетов, входящих в состав wxPython. Демонстрация позволяет разработчику просматривать код на одной вкладке и запускать его на второй вкладке. Вы даже можете отредактировать и повторно запустить код в демоверсии, чтобы увидеть, как ваши изменения повлияют на приложение.
Удалить рекламу
Установка wxPython
В этой статье вы будете использовать последнюю версию wxPython версии 9.0007 wxPython 4 , также известный как выпуск Phoenix. Версии wxPython 3 и wxPython 2 созданы только для Python 2 . Когда Робин Данн, основной сопровождающий wxPython, создал версию wxPython 4, он отказался от многих псевдонимов и подчистил большую часть кода, чтобы сделать wxPython более питоническим и простым в обслуживании.
Если вы переходите со старой версии wxPython на wxPython 4 (Phoenix), воспользуйтесь следующими ссылками:
- Классик против Феникса
- Руководство по переходу на wxPython Project Phoenix
Пакет wxPython 4 совместим как с Python 2. 7, так и с Python 3.
Теперь вы можете использовать pip
для установки wxPython 4, что было невозможно в устаревших версиях wxPython. Вы можете сделать следующее, чтобы установить его на свой компьютер:
$ pip установить wxpython
Примечание: В Mac OS X вам потребуется установленный компилятор, например XCode , для успешного завершения установки. Linux также может потребовать, чтобы вы установили некоторые зависимости до того, как 9Установщик 0062 pip будет работать правильно.
Например, мне нужно было установить freeglut3-dev , libgstreamer-plugins-base0.10-dev и libwebkitgtk-3.0-dev на Xubuntu, чтобы установить его.
К счастью, сообщения об ошибках, отображаемые pip
, помогают выяснить, чего не хватает, и вы можете использовать раздел предварительных требований на странице wxPython Github, чтобы найти необходимую информацию, если вы хотите установить wxPython в Linux.
Для самых популярных версий Linux доступно несколько колес Python, которые вы можете найти в разделе Extras Linux с версиями GTK2 и GTK3. Чтобы установить одно из этих колес, вы должны использовать следующую команду:
$ pip install -U -f https://extras.wxpython.org/wxPython4/extras/linux/gtk3/ubuntu-18.04/wxPython
Убедитесь, что вы изменили приведенную выше команду, чтобы она соответствовала вашей версии Linux.
Определение графического интерфейса
Как упоминалось во введении, графический пользовательский интерфейс (GUI) — это интерфейс, отображаемый на экране для взаимодействия пользователя с ним.
Пользовательские интерфейсы имеют некоторые общие компоненты:
- Главное окно
- Меню
- Панель инструментов
- Кнопки
- Ввод текста
- Этикетки
Все эти элементы известны как виджеты . Есть много других общих виджетов и множество пользовательских виджетов, которые поддерживает wxPython. Разработчик возьмет виджеты и логически расположит их в окне, чтобы пользователь мог с ними взаимодействовать.
Циклы событий
Графический пользовательский интерфейс работает, ожидая действий пользователя. Что-то называется событием . События происходят, когда пользователь что-то вводит, когда ваше приложение находится в фокусе, или когда пользователь использует мышь для нажатия кнопки или другого виджета.
Под прикрытием инструментарий GUI выполняет бесконечный цикл, который называется циклом событий . Цикл событий просто ожидает возникновения событий, а затем действует на эти события в соответствии с тем, что разработчик закодировал в приложении. Когда приложение не перехватывает событие, оно фактически игнорирует то, что оно вообще произошло.
Когда вы программируете графический интерфейс пользователя, вы должны иметь в виду, что вам нужно будет подключить каждый из виджетов к обработчикам событий , чтобы ваше приложение что-то делало.
Существует особое соображение, которое необходимо учитывать при работе с циклами событий: они могут быть заблокированы. Когда вы блокируете цикл обработки событий, графический интерфейс пользователя перестает отвечать на запросы и кажется пользователю зависшим.
Любой процесс, который вы запускаете в графическом интерфейсе и который занимает больше четверти секунды, вероятно, следует запускать как отдельный поток или процесс. Это предотвратит зависание вашего графического интерфейса и улучшит взаимодействие с пользователем.
Платформа wxPython имеет специальные потокобезопасные методы, которые вы можете использовать для обратной связи с вашим приложением, чтобы сообщить ему о завершении потока или дать ему обновление.
Давайте создадим каркас приложения, чтобы продемонстрировать, как работают события.
Удалить рекламу
Создание скелетного приложения
Скелет приложения в контексте GUI — это пользовательский интерфейс с виджетами, не имеющими обработчиков событий. Они полезны для прототипирования. По сути, вы просто создаете графический интерфейс и представляете его своим заинтересованным сторонам для утверждения, прежде чем тратить много времени на внутреннюю логику.
Давайте начнем с создания приложения Hello World
с помощью wxPython:
импорт wx приложение = wx.App() frame = wx.Frame(parent=None, title='Hello World') кадр. Показать () приложение.MainLoop()
Примечание. Пользователи Mac могут получить следующее сообщение: Этой программе требуется доступ к экрану. Пожалуйста, запускайте со сборкой Python Framework и только тогда, когда вы вошли в систему на главном дисплее вашего Mac. Если вы видите это сообщение и не работаете в виртуальной среде, вам нужно запустить приложение с pythonw вместо python . Если вы запускаете wxPython из virtualenv, см. wxPython wiki для решения.
В этом примере у вас есть две части: wx.
и App
wx.Frame
. wx.App
— это объект приложения wxPython, необходимый для запуска вашего графического интерфейса. wx.App
запускает нечто, называемое .MainLoop()
. Это цикл событий, о котором вы узнали в предыдущем разделе.
Другая часть головоломки — это wx.Frame
, который создаст окно для взаимодействия с пользователем. В этом случае вы сказали wxPython, что у фрейма нет родителя и что его заголовок Hello World
. Вот как это выглядит при запуске кода:
Примечание: Приложение будет выглядеть по-другому при запуске на Mac или Windows.
По умолчанию wx.Frame
будет включать кнопки свертывания, развертывания и выхода вверху. Однако обычно вы не будете создавать приложение таким образом. Большая часть кода wxPython потребует от вас подкласса wx.Frame
и другие виджеты, чтобы вы могли получить всю мощь набора инструментов.
Давайте уделим немного времени и перепишем ваш код как класс:
импорт wx класс MyFrame(wx.Frame): защита __init__(сам): super().__init__(parent=None, title='Hello World') самовыражение() если __name__ == '__main__': приложение = wx.App() кадр = МойКадр() приложение.MainLoop()
Вы можете использовать этот код в качестве шаблона для своего приложения. Однако это приложение не очень много делает, поэтому давайте уделим немного времени, чтобы узнать немного о некоторых других виджетах, которые вы можете добавить.
Виджеты
Инструментарий wxPython содержит более сотни виджетов на выбор. Это позволяет вам создавать многофункциональные приложения, но также может быть сложной задачей выяснить, какой виджет использовать. Вот почему wxPython Demo полезен, так как в нем есть фильтр поиска, который вы можете использовать, чтобы помочь вам найти виджеты, которые могут применяться к вашему проекту.
Большинство приложений с графическим интерфейсом позволяют пользователю вводить текст и нажимать кнопку. Давайте добавим эти виджеты:
импорт wx класс MyFrame(wx.Frame): защита __init__(сам): super().__init__(parent=None, title='Hello World') панель = wx.Panel(я) self.text_ctrl = wx.TextCtrl (панель, позиция = (5, 5)) my_btn = wx.Button(panel, label='Нажми на меня', pos=(5, 55)) самовыражение() если __name__ == '__main__': приложение = wx.App() кадр = МойКадр() приложение.MainLoop()
Когда вы запускаете этот код, ваше приложение должно выглядеть так:
Первый виджет, который вам нужно добавить, называется wx.Панель
. Этот виджет не обязателен, но рекомендуется. В Windows вы фактически должны использовать панель, чтобы цвет фона рамки был правильным оттенком серого. Обход вкладок отключен без Panel в Windows.
Когда вы добавляете виджет панели во фрейм, и панель является единственным дочерним элементом фрейма, она автоматически расширяется, чтобы заполнить фрейм собой.
Следующим шагом является добавление wx.TextCtrl
на панель. Первым аргументом почти для всех виджетов является то, к какому родителю должен перейти виджет. В этом случае вы хотите, чтобы текстовый элемент управления и кнопка находились в верхней части панели, поэтому вы указываете родителя.
Вам также необходимо указать wxPython, где разместить виджет, что вы можете сделать, передав позицию через параметр pos
. В wxPython исходным местоположением является (0,0), что является левым верхним углом родителя. Итак, для текстового элемента управления вы сообщаете wxPython, что хотите расположить его верхний левый угол на расстоянии 5 пикселей слева (x) и 5 пикселей сверху (y).
Затем вы добавляете кнопку на панель и присваиваете ей метку. Чтобы виджеты не перекрывались, вам нужно установить координату y на 55 для положения кнопки.
Удалить рекламу
Абсолютное позиционирование
Когда вы указываете точные координаты положения вашего виджета, метод, который вы использовали, называется абсолютным позиционированием . Большинство инструментов GUI предоставляют эту возможность, но на самом деле это не рекомендуется.
По мере того, как ваше приложение становится все более сложным, становится трудно отслеживать расположение всех виджетов и необходимость их перемещения. Сброс всех этих позиций становится кошмаром.
К счастью, все современные инструменты GUI предоставляют решение для этой проблемы, о чем вы узнаете далее.
Измерители (динамическая калибровка)
Инструментарий wxPython включает сайзеров , которые используются для создания динамических макетов. Они управляют размещением ваших виджетов за вас и настраивают их при изменении размера окна приложения. Другие наборы инструментов с графическим интерфейсом будут ссылаться на сайзеры как на макеты, что и делает PyQt.
Вот основные типы сайзеров, которые чаще всего используются:
-
wx.BoxSizer
-
wx.GridSizer
-
wx.FlexGridSizer
Давайте добавим в ваш пример wx.
и посмотрим, сможем ли мы заставить его работать немного лучше: BoxSizer
импорт wx класс MyFrame(wx.Frame): защита __init__(сам): super().__init__(parent=None, title='Hello World') панель = wx.Panel(я) my_sizer = wx.BoxSizer(wx.VERTICAL) self.text_ctrl = wx.TextCtrl(панель) my_sizer.Add(self.text_ctrl, 0, wx.ALL | wx.EXPAND, 5) my_btn = wx.Button(panel, label='Нажми на меня') my_sizer.Add(my_btn, 0, wx.ALL | wx.CENTER, 5) панель.SetSizer(my_sizer) самовыражение() если __name__ == '__main__': приложение = wx.App() кадр = МойКадр() приложение.MainLoop()
Здесь вы создаете экземпляр wx.BoxSizer
и передаете ему wx.VERTICAL
, что является ориентацией, в которой виджеты добавляются к сайзеру.
В этом случае виджеты будут добавляться вертикально, то есть будут добавляться по одному сверху вниз. Вы также можете установить ориентацию BoxSizer на wx.
. Когда вы это сделаете, виджеты будут добавляться слева направо. HORIZONTAL
Чтобы добавить виджет в сайзер, вы будете использовать .Add()
. Он принимает до пяти аргументов:
-
окно
(виджет) -
пропорция
-
флаг
-
граница
-
данные пользователя
Аргумент окна
представляет собой добавляемый виджет, в то время как пропорция
устанавливает, сколько места относительно других виджетов в сайзере должен занимать этот конкретный виджет. По умолчанию он равен нулю, что указывает wxPython оставить пропорции виджета по умолчанию.
Третий аргумент флаг
. На самом деле вы можете передать несколько флагов, если хотите, если вы разделяете их вертикальной чертой: |
. Инструментарий wxPython использует |
, чтобы добавить флаги с помощью побитового ИЛИ.
В этом примере вы добавляете текстовый элемент управления с флагами wx.
и ALL
wx.EXPAND
. Флаг wx.ALL
сообщает wxPython, что вы хотите добавить границу со всех сторон виджета, в то время как wx.EXPAND
заставляет виджеты расширяться настолько, насколько они могут в сайзере.
Наконец, у вас есть параметр border
, который сообщает wxPython, сколько пикселей границы вы хотите вокруг виджета. Параметр userData
используется только тогда, когда вы хотите сделать что-то сложное с размером виджета, и на самом деле его довольно редко можно увидеть на практике.
Добавление кнопки в сайзер выполняется точно так же. Однако, чтобы сделать вещи немного интереснее, я пошел дальше и заменил wx.EXPAND
Флаг для wx.CENTER
, чтобы кнопка располагалась по центру экрана.
При запуске этой версии кода ваше приложение должно выглядеть следующим образом:
Если вы хотите узнать больше о сайзерах, в документации wxPython есть хорошая страница по этой теме.
Удалить рекламу
Добавление события
Хотя визуально ваше приложение выглядит интереснее, оно по-прежнему ничего не делает. Например, если вы нажмете кнопку, на самом деле ничего не произойдет.
Давайте поработаем над кнопкой:
импорт wx класс MyFrame(wx.Frame): защита __init__(сам): super().__init__(parent=None, title='Hello World') панель = wx.Panel(я) my_sizer = wx.BoxSizer(wx.VERTICAL) self.text_ctrl = wx.TextCtrl(панель) my_sizer.Add(self.text_ctrl, 0, wx.ALL | wx.EXPAND, 5) my_btn = wx.Button(panel, label='Нажми на меня') my_btn.Bind(wx.EVT_BUTTON, self.on_press) my_sizer.Add(my_btn, 0, wx.ALL | wx.CENTER, 5) панель.SetSizer(my_sizer) самовыражение() def on_press (я, событие): значение = self.text_ctrl.GetValue() если не значение: print("Вы ничего не вводили!") еще: print(f'Вы ввели: "{значение}"') если __name__ == '__main__': приложение = wx.App() кадр = МойКадр() приложение.MainLoop()
Виджеты в wxPython позволяют вам прикреплять к ним привязки событий, чтобы они могли реагировать на определенные типы событий.
Вы хотите, чтобы кнопка выполняла какие-либо действия, когда пользователь нажимает ее. Вы можете сделать это, вызвав метод кнопки .Bind()
. .Bind()
принимает событие, к которому вы хотите привязаться, обработчик, вызываемый при возникновении события, необязательный источник и пару необязательных идентификаторов.
В этом примере вы привязываете объект кнопки к wx.EVT_BUTTON
и скажите ему вызывать on_press()
, когда это событие сработает.
Событие запускается, когда пользователь выполняет событие, к которому вы привязаны. В этом случае событие, которое вы настроили, — это событие нажатия кнопки, wx.EVT_BUTTON
.
.on_press()
принимает второй аргумент, который вы можете вызвать событием
. Это по соглашению. Вы могли бы назвать это как-то иначе, если бы захотели. Однако параметр события здесь относится к тому факту, что при вызове этого метода его вторым аргументом должен быть какой-то объект события.
Внутри .on_press()
вы можете получить содержимое текстового элемента управления, вызвав его метод GetValue()
. Затем вы печатаете строку на стандартный вывод в зависимости от содержимого текстового элемента управления.
Теперь, когда вы разобрались с основами, давайте научимся создавать приложение, которое будет делать что-то полезное!
Создание рабочего приложения
Первый шаг при создании чего-то нового — понять, что вы хотите создать. В данном случае я взял на себя смелость принять это решение за вас. Вы узнаете, как создать редактор тегов MP3! Следующий шаг при создании чего-то нового — выяснить, какие пакеты могут помочь вам выполнить вашу задачу.
Если вы выполните поиск в Google для Python mp3 с тегом
, вы обнаружите, что у вас есть несколько вариантов:
-
mp3-теггер
-
глаз D3
-
мутаген
Я попробовал несколько из них и решил, что eyeD3 имеет хороший API, который можно использовать, не увязая в спецификации MP3 ID3. Вы можете установить eyeD3 , используя
pip
, например:
$ pip установить eyed3
При установке этого пакета на macOS вам может потребоваться установить libmagic
с помощью brew
. У пользователей Windows и Linux не должно возникнуть проблем с установкой eyeD3.
Проектирование пользовательского интерфейса
Когда дело доходит до дизайна интерфейса, всегда приятно просто набросать, как, по вашему мнению, должен выглядеть пользовательский интерфейс.
Вам нужно будет уметь делать следующее:
- Открыть один или несколько файлов MP3
- Показать текущие теги MP3
- Редактировать тег MP3
Большинство пользовательских интерфейсов используют меню или кнопку для открытия файлов или папок. Для этого вы можете использовать меню File . Поскольку вы, вероятно, захотите увидеть теги для нескольких файлов MP3, вам нужно будет найти виджет, который может сделать это удобным способом.
Что-то табличное со столбцами и строками было бы идеальным, потому что тогда вы можете пометить столбцы для тегов MP3. В наборе инструментов wxPython есть несколько виджетов, которые подходят для этого, два лучших из них следующие:0003
-
wx.grid.Grid
-
wx.ListCtrl
В этом случае вам следует использовать wx.ListCtrl
, поскольку виджет Grid
является излишним, и, честно говоря, он также немного сложнее. Наконец, вам нужна кнопка для редактирования выбранного тега MP3.
Теперь, когда вы знаете, чего хотите, вы можете это нарисовать:
Иллюстрация выше дает нам представление о том, как должно выглядеть приложение. Теперь, когда вы знаете, что хотите сделать, пришло время кодировать!
Удаление рекламы
Создание пользовательского интерфейса
Существует множество различных подходов к написанию нового приложения. Например, нужно ли вам следовать шаблону проектирования Model-View-Controller? Как вы делите классы? Один класс на файл? Таких вопросов много, и по мере накопления опыта в дизайне графического интерфейса вы будете знать, как на них отвечать.
В вашем случае вам действительно нужны только два класса:
- А
wx.Панель
класс - A
wx.Рама
класс
Вы могли бы поспорить и за создание модуля типа контроллера, но для чего-то подобного он вам действительно не нужен. Можно было бы также поместить каждый класс в отдельный модуль, но для компактности вы создадите один файл Python для всего своего кода.
Начнем с импорта и класса панели:
импорт глаз3 импортировать глобус импорт wx класс Mp3Panel(wx.Panel): def __init__(я, родитель): супер().__init__(родительский) main_sizer = wx.BoxSizer(wx.VERTICAL) self.row_obj_dict = {} self.list_ctrl = wx.ListCtrl( я, размер=(-1, 100), стиль = wx.LC_REPORT | wx.BORDER_SUNKEN ) self.list_ctrl.InsertColumn (0, «Исполнитель», ширина = 140) self.list_ctrl.InsertColumn(1, 'Альбом', ширина=140) self.list_ctrl.InsertColumn(2, 'Заголовок', ширина=200) main_sizer.Add(self.list_ctrl, 0, wx.ALL | wx.EXPAND, 5) edit_button = wx.Button(self, label='Edit') edit_button.Bind(wx.EVT_BUTTON, self.on_edit) main_sizer.Add(edit_button, 0, wx.ALL | wx.CENTER, 5) self.SetSizer(main_sizer) def on_edit (я, событие): печать('в on_edit') def update_mp3_listing (я, путь к папке): печать (путь_папки)
Здесь вы импортируете пакет Eyed3
, пакет Python glob
и пакет wx
для пользовательского интерфейса. Затем вы создаете подкласс wx.Panel
и создаете свой пользовательский интерфейс. Вам нужен словарь для хранения данных о ваших MP3-файлах, который вы можете назвать row_obj_dict
.
Затем вы создаете wx.
и устанавливаете его в режим отчета ( ListCtrl
wx.LC_REPORT
) с утопленной рамкой ( wx.BORDER_SUNKEN
). Элемент управления списком может принимать несколько других форм в зависимости от флага стиля, который вы передаете, но флаг отчета является наиболее популярным.
Чтобы ListCtrl
имел правильные заголовки, вам нужно будет вызвать .InsertColumn()
для каждого заголовка столбца. Затем вы указываете индекс столбца, его метку и ширину столбца в пикселях.
Последний шаг — добавить кнопку Изменить
, обработчик событий и метод. Вы можете создать привязку к событию и пока оставить метод, который оно вызывает, пустым.
Теперь вы должны написать код для фрейма:
класс Mp3Frame(wx.Frame): защита __init__(сам): супер().__init__(родительский=Нет, title='Редактор тегов MP3') self.panel = Mp3Panel(я) самовыражение() если __name__ == '__main__': приложение = wx.App (ложь) кадр = Mp3Frame() приложение.MainLoop()
Этот класс намного проще, чем первый, поскольку все, что вам нужно сделать, это установить заголовок кадра и создать экземпляр класса панели, Mp3Panel
. Когда вы все закончите, ваш пользовательский интерфейс должен выглядеть так:
Пользовательский интерфейс выглядит почти правильно, но у вас нет меню File . Это делает невозможным добавление MP3-файлов в приложение и редактирование их тегов!
Давайте исправим это сейчас.
Создание работающего приложения
Первый шаг к тому, чтобы ваше приложение заработало, — это обновить приложение, чтобы оно имело меню File , потому что тогда вы сможете добавлять файлы MP3 в свое творение. Меню почти всегда добавляются в класс wx.Frame
, так что это класс, который вам нужно изменить.
Примечание: Некоторые приложения отказались от меню в своих приложениях. Одним из первых, кто сделал это, был Microsoft Office, когда они добавили панель ленты. Инструментарий wxPython имеет пользовательский виджет, который можно использовать для создания лент в
wx.lib.agw.ribbon
.
Другим типом приложений, в которых в последнее время исчезли меню, являются веб-браузеры, такие как Google Chrome и Mozilla Firefox. Сейчас они просто используют панели инструментов.
Давайте узнаем, как добавить строку меню в наше приложение:
класс Mp3Frame(wx.Frame): защита __init__(сам): wx.Frame.__init__(self, parent=None, title='Редактор тегов MP3') self.panel = Mp3Panel(я) self.create_menu() самовыражение() определение create_menu (я): menu_bar = wx.MenuBar() file_menu = wx.Меню() open_folder_menu_item = file_menu.Append( wx.ID_ANY, «Открыть папку», «Открыть папку с MP3» ) menu_bar.Append(file_menu, '&Файл') само.Привязать( событие=wx.EVT_MENU, обработчик = self.on_open_folder, источник = open_folder_menu_item, ) self.SetMenuBar (меню_бар) def on_open_folder (я, событие): title = "Выберите каталог:" dlg = wx.DirDialog(я, заголовок, стиль=wx.DD_DEFAULT_STYLE) если dlg.ShowModal() == wx.ID_OK: self.panel.update_mp3_listing(dlg.GetPath()) длг.Уничтожить()
Здесь вы добавляете вызов .create_menu()
в конструкторе класса. Затем в самом .create_menu()
вы создадите экземпляр wx.MenuBar
и экземпляр wx.Menu
.
Чтобы добавить пункт меню в меню, вы вызываете экземпляр меню .Append()
и передаете ему следующее:
- Уникальный идентификатор
- Метка для нового пункта меню
- Строка справки
Далее вам нужно добавить меню в строку меню, поэтому вам нужно будет вызвать строку меню .Добавить()
. Он принимает экземпляр меню и метку для меню. Эта метка немного странная, поскольку вы назвали ее
&Файл
вместо Файл
. Амперсанд говорит wxPython создать сочетание клавиш Alt + F , чтобы открыть меню File
, используя только вашу клавиатуру.
Примечание: Если вы хотите добавить сочетания клавиш в свое приложение, вам нужно использовать экземпляр wx.AcceleratorTable
для их создания. Подробнее о таблицах ускорителей можно прочитать в документации wxPython.
Чтобы создать привязку события, вам нужно будет вызвать self.Bind()
, который привязывает кадр к wx.EVT_MENU
. Когда вы используете self.Bind()
для события меню, вам нужно не только указать wxPython, какой обработчик
использовать, но также и к какому источнику
привязать обработчик.
Наконец, вы должны вызвать фрейм .SetMenuBar()
и передать ему экземпляр строки меню, чтобы он был показан пользователю.
Теперь, когда вы добавили меню в свой фрейм, давайте рассмотрим обработчик событий пункта меню, который снова воспроизведен ниже:
определение on_open_folder (я, событие): title = "Выберите каталог:" dlg = wx.DirDialog(self, title, style=wx.DD_DEFAULT_STYLE) если dlg.ShowModal() == wx.ID_OK: self.panel.update_mp3_listing(dlg.GetPath()) длг.Уничтожить()
Поскольку вы хотите, чтобы пользователь выбирал папку, содержащую файлы MP3, вам следует использовать wxPython wx.DirDialog
. wx.DirDialog
позволяет пользователю открывать только каталоги.
Вы можете установить заголовок диалогового окна и различные флаги стиля. Чтобы отобразить диалог, вам нужно будет вызвать .ShowModal()
. Это приведет к тому, что диалоговое окно будет отображаться модально, а это означает, что пользователь не сможет взаимодействовать с вашим основным приложением, пока отображается диалоговое окно.
Если пользователь нажимает кнопку OK диалогового окна, вы можете получить выбор пути пользователя с помощью диалогового окна .
. Вам нужно будет передать этот путь классу вашей панели, что вы можете сделать здесь, вызвав ПолучитьПуть()
.update_mp3_listing() панели
.
Наконец, вам нужно закрыть диалоговое окно. Чтобы закрыть диалог, рекомендуется вызвать его .Destroy()
.
Диалоги имеют метод .Close()
, но он просто скрывает диалог, и он не уничтожит себя, когда вы закроете приложение, что может привести к странным проблемам, таким как ваше приложение теперь закрывается должным образом. проще позвонить .Destroy()
в диалоговом окне, чтобы предотвратить эту проблему.
Теперь давайте обновим ваш класс Mp3Panel
. Вы можете начать с обновления .update_mp3_listing()
:
def update_mp3_listing(self, folder_path): self.current_folder_path = путь_к_папке self.list_ctrl.ClearAll() self.list_ctrl.InsertColumn (0, «Исполнитель», ширина = 140) self.list_ctrl.InsertColumn(1, 'Альбом', ширина=140) self.list_ctrl.InsertColumn(2, 'Заголовок', ширина=200) self.list_ctrl.InsertColumn(3, 'Год', ширина=200) mp3s = glob.glob (путь_папки + '/*.mp3') mp3_objects = [] индекс = 0 для мп3 в мп3: mp3_object = eyed3.load(mp3) self.list_ctrl.InsertItem (индекс, mp3_object.tag.исполнитель) self.list_ctrl.SetItem (индекс, 1, mp3_object.tag.album) self.list_ctrl.SetItem (индекс, 2, mp3_object.tag.title) mp3_objects.append(mp3_object) self.row_obj_dict[index] = mp3_object индекс += 1
Здесь вы устанавливаете текущий каталог в указанную папку, а затем очищаете элемент управления списком. Это сохраняет элемент управления списком свежим и показывает только те MP3, над которыми вы сейчас работаете. Это также означает, что вам нужно снова вставить все столбцы.
Затем вы захотите взять папку, которая была передана, и использовать модуль Python glob
для поиска файлов MP3.
Затем вы можете зациклиться на MP3 и превратить их в объекты Eyed3
. Вы можете сделать это, позвонив по номеру 9.0062 .load() из Eyed3
. Предполагая, что MP3-файлы уже имеют соответствующие теги, вы можете добавить исполнителя, альбом и название MP3-файла в элемент управления списком.
Интересно, что метод добавления новой строки в объект управления списком заключается в вызове .InsertItem()
для первого столбца и SetItem()
для всех последующих столбцов.
Последний шаг — сохранить ваш объект MP3 в словаре Python, row_obj_dict
.
Теперь вам нужно обновить обработчик событий .on_edit()
, чтобы вы могли редактировать теги MP3:
по определению on_edit(я, событие): выбор = self.list_ctrl.GetFocusedItem() если выбор >= 0: mp3 = self.row_obj_dict[выбор] dlg = диалоговое окно редактирования (mp3) dlg.ShowModal() self.update_mp3_listing(self.current_folder_path) длг.Уничтожить()
Первое, что вам нужно сделать, это получить выбор пользователя, вызвав элемент управления списком 9.0062 .GetFocusedItem() .
Если пользователь ничего не выбрал в элементе управления списком, он вернет -1
. Предполагая, что пользователь что-то выбрал, вы захотите извлечь объект MP3 из своего словаря и открыть диалоговое окно редактора тегов MP3. Это будет пользовательский диалог, который вы будете использовать для редактирования тегов исполнителя, альбома и названия файла MP3.
Как обычно, показывать диалог модально. Когда диалоговое окно закроется, будут выполнены последние две строки в .on_edit()
. Эти две строки будут обновлять элемент управления списком, чтобы он отображал текущую информацию тега MP3, которую пользователь только что отредактировал, и уничтожает диалоговое окно.
Создание диалогового окна редактирования
Последняя часть головоломки — создание диалогового окна редактирования тега MP3. Для краткости мы не будем зарисовывать этот интерфейс, так как он представляет собой ряд строк, содержащих метки и текстовые элементы управления. Текстовые элементы управления должны иметь предварительно заполненную информацию о существующих тегах. Вы можете создать метку для текстовых элементов управления, создав экземпляры
wx.StaticText
.
Когда вам нужно создать пользовательский диалог, wx.Dialog 9Класс 0063 твой друг. Вы можете использовать это для разработки редактора:
класс EditDialog(wx.Dialog): def __init__(я, mp3): title = f'Редактирование "{mp3.tag.title}"' super().__init__(родительский=Нет, заголовок=заголовок) сам.mp3 = mp3 self.main_sizer = wx.BoxSizer(wx.VERTICAL) self.artist = wx.TextCtrl( я, значение = self.mp3.tag.artist) self.add_widgets('Художник', self.artist) self.album = wx.TextCtrl( я, значение = self.mp3.tag.album) self.add_widgets('Альбом', self.album) self.title = wx.TextCtrl( я, значение = self.mp3.tag.title) self.add_widgets('Заголовок', self.title) btn_sizer = wx.BoxSizer() save_btn = wx.Button(self, label='Сохранить') save_btn.Bind(wx.EVT_BUTTON, self.on_save) btn_sizer.Add(save_btn, 0, wx.ALL, 5) btn_sizer.Add(wx.Button( сам, id=wx.ID_CANCEL), 0, wx.ALL, 5) self.main_sizer.Add(btn_sizer, 0, wx.CENTER) self.SetSizer(self.main_sizer)
Здесь вы хотите начать с подкласса wx.Dialog
и присвоить ему собственное название на основе названия редактируемого MP3.
Далее вы можете создать размер, который вы хотите использовать, и виджеты. Чтобы упростить задачу, вы можете создать вспомогательный метод с именем .add_widgets()
для добавления виджетов wx.StaticText
в виде строк с экземплярами текстового элемента управления. Единственным другим виджетом здесь является кнопка Сохранить .
Давайте напишем add_widgets
следующий метод:
по определению add_widgets(self, label_text, text_ctrl): row_sizer = wx.BoxSizer(wx.ГОРИЗОНТАЛЬНО) label = wx.StaticText(self, label=label_text, размер = (50, -1)) row_sizer.Add (метка, 0, wx.ALL, 5) row_sizer.Add(text_ctrl, 1, wx.ALL | wx.EXPAND, 5) self.main_sizer.Add(row_sizer, 0, wx.EXPAND)
add_widgets()
принимает текст метки и экземпляр текстового элемента управления. Затем он создает горизонтально ориентированный BoxSizer
.
Далее вы создадите экземпляр wx.StaticText
, используя переданный текст в качестве параметра метки. Вы также установите его размер равным 50
пикселей в ширину, а высота по умолчанию будет равна -1
. Поскольку вам нужна метка перед текстовым элементом управления, вы сначала добавите виджет StaticText в свой BoxSizer, а затем добавите текстовый элемент управления.
Наконец, вы хотите добавить горизонтальный размерчик к вертикальному размерчику верхнего уровня. Вкладывая сайзеры друг в друга, вы можете создавать сложные приложения.
Теперь вам нужно создать обработчик события on_save()
, чтобы вы могли сохранить свои изменения:
def on_save(я, событие): self.mp3.tag.artist = self.artist.GetValue() self.mp3.tag.album = self.album.GetValue() self.mp3.tag.title = self.title.GetValue() self.mp3.tag.save() само.Закрыть()
Здесь вы устанавливаете теги для содержимого текстовых элементов управления, а затем вызываете объект eyed3
.save()
. Наконец, вы вызываете .Close()
диалогового окна. Причина, по которой вы звоните. Close()
здесь вместо .Destroy()
заключается в том, что вы уже вызываете .Destroy()
в .on_edit()
вашего подкласса панели.
Теперь ваше приложение готово!
Удалить рекламу
Заключение
Из этой статьи вы многое узнали о wxPython. Вы познакомились с основами создания приложений с графическим интерфейсом с помощью wxPython.
Теперь вы знаете больше о следующем:
- Как работать с некоторыми виджетами wxPython
- Как работают события в wxPython
- Сравнение абсолютного позиционирования с сайзерами
- Как создать каркас приложения
Наконец-то вы узнали, как создать работающее приложение, редактор тегов MP3. Вы можете использовать то, что вы узнали из этой статьи, чтобы продолжить совершенствовать это приложение или, возможно, создать замечательное приложение самостоятельно.
Инструментарий wxPython GUI надежен и полон интересных виджетов, которые можно использовать для создания кроссплатформенных приложений. Вы ограничены только своим воображением.
Дополнительное чтение
Если вы хотите узнать больше о wxPython, вы можете перейти по следующим ссылкам:
- Официальный сайт wxPython
- Руководство Zetcode по wxPython
- Мышь против Python Блог
Для получения дополнительной информации о том, что еще вы можете делать с Python, вы можете проверить, что я могу сделать с Python? Если вы хотите узнать больше о Python super()
, тогда суперзарядите свои классы с помощью Python super() может быть как раз для вас.
Вы также можете загрузить код приложения для редактирования тегов MP3, которое вы создали в этой статье, если хотите изучить его более подробно.
Python для начинающих: как создать приложение с графическим интерфейсом
До сих пор в нашей серии «Питон для начинающих» мы обсуждали многие аспекты Python, такие как списки, переменные, кортежи, функции, чтение текста из файлов и многое другое. более.
Единственным общим знаменателем всех учебных пособий на данный момент является то, что мы создаем только текстовые приложения. Эти приложения великолепны и могут оказаться очень полезными (особенно на компьютерах, на которых нет среды рабочего стола или которые вам нужны для работы в фоновом режиме). Вы даже можете подумать, что Python не способен создавать приложения с графическим пользовательским интерфейсом (GUI).
Угадайте, что? Это.
Эти приложения с графическим интерфейсом могут использовать такие вещи, как:
- переключатели
- контрольные списки
- меню
- выпадающих списков
- стоимость колеса
- столбцов значений
- и более
С небольшой помощью набора инструментов GUI вы можете создавать приложения с графическим интерфейсом на Python. Не верите мне? Позвольте мне показать вам, как это делается.
Я буду демонстрировать на Pop!_OS Linux, но это можно сделать с любым дистрибутивом, поддерживающим Python.
Установить PySimpleGUI
Прежде чем мы сможем создавать какие-либо приложения с графическим интерфейсом с помощью Python, мы должны установить библиотеку Python, которая объединяет различные библиотеки графического интерфейса (такие как Tkinter, Qt (pyside2), wxPython и Remi) в одном пакете, чтобы обеспечить быстрое и простое программирование графического интерфейса. По умолчанию PySimpleGUI по умолчанию использует Tkinter, но вы можете переключить его по мере необходимости.
Другими словами, установка PySimpleGUI дает вам все необходимое, чтобы начать создавать приложения с графическим интерфейсом с помощью Python.
Чтобы установить PySimpleGUI, вам понадобится машина, на которой уже установлен Python. Вам также понадобится pip для установки. Если вы еще не установили pip, сделайте это с помощью команды:
sudo apt-get install python3-pip -y
Теперь, когда Pip установлен, вы можете установить PySimpleGUI с помощью команды:
python3 -m pip установить pysimplegui
Теперь вы готовы приступить к созданию своего первого приложения с графическим интерфейсом.
Привет, новый стек!
Первое приложение с графическим интерфейсом, которое мы создадим, — всегда популярное приложение Hello, World (с нотками New Stack). Первое, что вы должны знать, это то, что библиотека PySimpleGUI должна быть импортирована в ваше приложение. Мы делали это раньше, так что это должно быть второй натурой.
Мы импортируем PySimpleGUI в наше приложение как sg со строкой:
импортировать PySimpleGUI как SG
импортировать PySimpleGUI как sg |
С помощью этой строки мы можем вызвать любую функцию PySimpleGUI всего с sg .
Следующая строка определяет расположение кнопки для приложения. Эта строка будет определять текст для кнопки как «Hello, New Stack» и размер кнопки как 30 x 4. Эта строка выглядит следующим образом:
layout = [[sg.Button('Привет, новый стек', size=(30,4))]]
layout = [[sg. |
Обратите внимание, что в строке используется кортеж (что внутри ()) и список (что внутри []) для рисования кнопки.
Наша следующая строка рисует фактическое окно приложения и выглядит так:
window = sg.Window('GUI SAMPLE', layout, size=(200,100))
window = sg.Window('GUI SAMPLE', layout, size=(200,100)) |
То, что вы видите выше, — это переменная (окно), которая использует функцию PySimpleGUI Window для рисования графического элемента с надписью GUI SAMPLE размером 200×100.
Наконец, мы используем функцию .read() (которая возвращает указанное количество байтов из файла. Значение по умолчанию равно -1, что означает весь файл) для действия по нажатию кнопки со строкой:
событие, значения = window.read()
событие, значения = window. |
Весь наш скрипт (с комментариями) выглядит так:
#Импорт PySimpleGUI импортировать PySimpleGUI как sg #Нарисовать кнопку layout = [[sg.Button('Привет, новый стек', size=(30,4))]] # Рисуем окно window = sg.Window('ОБРАЗЕЦ GUI', layout, size=(200,100)) #Определяем, что происходит при нажатии кнопки событие, значения = window.read()
1 2 3 4 5 6 7 8 9 10 11 | #Import PySimpleGUI import PySimpleGUI as sg
#Draw the button layout = [[sg.Button('Hello, New Stack', size=(30,4))]] 3 02 32 3 |
Сохраните этот файл как hello_world. py . Запустите программу с помощью команды:
python3 hello_world.py
После этого вы должны увидеть небольшое окно с нажимаемой кнопкой ( Рисунок 1 ).
Рисунок 1: Наше приложение Python Hello, World с графическим интерфейсом.
Нажмите кнопку Hello, New Stack, и окно закроется.
Принятие пользовательского ввода
На этот раз мы создадим графический интерфейс, который принимает пользовательский ввод. На этот раз мы импортируем пакет Tkinter (который был установлен с PySimpleGUI), чтобы выполнить тяжелую работу. Назовем этот файл input_gui.py . Первая строка импортирует Tkinter и выглядит так:
импортировать ткинтер как тк
импорт tkinter как tk |
Далее мы собираемся импортировать simpledialog от Tkinter с:
из tkinter import simpledialog
из tkinter import simpledialog |
Затем мы определяем корневое окно с помощью:
КОРЕНЬ = tk. Tk()
КОРЕНЬ = tk.Tk() |
После определения корневого окна мы можем затем определить диалоговое окно ввода (назвав окно «Проверка ввода») и предложить пользователю ввести свое имя с помощью:
USER_INP = simpledialog.askstring(title="Проверка ввода", prompt="Введите свое имя:")
USER_INP = simpledialog.askstring(title="Input Test", prompt="Введите ваше имя:") |
Наконец, мы выводим пользовательский ввод обратно в окно терминала с помощью строки:
print("Hello", USER_INP)
Все наше приложение выглядит так:
# Импортируем tkinter и simpledialog
импортировать tkinter как tk
из tkinter импортировать простой диалог # Определяем корневое окно
КОРЕНЬ = tk.Tk() # Определить диалог ввода
КОРЕНЬ.снять() # Определяем диалог ввода
USER_INP = simpledialog. askstring(title="Проверка ввода",
prompt="Введите свое имя?:") # Распечатать пользовательский ввод
печать ("Здравствуйте", USER_INP)
1 2 3 4 5 6 7 8 10 11 12 13 14 15 16 | # Import Tkinter и Simpledialog Импорт Tknter As TK из Thkinter Import Simpledialog # Определите корневое окно root = tk.tk () # Define входной диаграммы ROOT.WITHDRAK. () # Определите диалог ввода user_inp = simpledialog.askstring (title = "test Test", rample = "Введите свое имя ?:") # Печать пользовательского ввода Print (") Привет", USER_INP) |
Сохраните и закройте файл. Запустите приложение с помощью:
python3 input_gui.py
Вы увидите небольшое окно с графическим интерфейсом, запрашивающее ваше имя с кнопками OK и Cancel ( Рисунок 2 ).
Рисунок 2: Наш графический интерфейс для пользовательского ввода.
Введите свое имя и нажмите OK, чтобы увидеть сообщение, напечатанное в окне терминала.
И вот… вы создали свое первое приложение с графическим интерфейсом на Python. Как видите, этот удобный язык не ограничивается только текстовыми приложениями. На самом деле Python довольно универсальный язык, что делает его еще более полезным.
Группа, созданная с помощью Sketch.Запуск приложений Linux с графическим интерфейсом с помощью WSL
- Статья
- 4 минуты на чтение
Подсистема Windows для Linux (WSL) теперь поддерживает запуск приложений Linux с графическим интерфейсом (X11 и Wayland) в Windows в полностью интегрированном рабочем столе.
WSL 2 позволяет приложениям Linux с графическим интерфейсом чувствовать себя родными и естественными для использования в Windows.
- Запуск приложений Linux из меню «Пуск» Windows
- Закрепление приложений Linux на панели задач Windows
- Используйте Alt-Tab для переключения между приложениями Linux и Windows
- Вырезать + Вставить в приложениях Windows и Linux
Теперь вы можете интегрировать приложения Windows и Linux в свой рабочий процесс, чтобы обеспечить бесперебойную работу рабочего стола.
Установка поддержки графических приложений для Linux
Предварительные условия
Вы должны быть на Windows 11 Build 22000 или более поздней версии для доступа к этой функции.
Установленный драйвер для vGPU
Чтобы запускать приложения Linux с графическим интерфейсом, сначала необходимо установить драйвер, соответствующий вашей системе, указанный ниже.
Это позволит вам использовать виртуальный графический процессор (vGPU), чтобы вы могли воспользоваться аппаратным ускорением рендеринга OpenGL.
- Драйвер графического процессора Intel для WSL
- Драйвер графического процессора AMD для WSL
- Драйвер графического процессора NVIDIA для WSL
Новая установка — без предварительной установки WSL
Теперь вы можете установить все необходимое для запуска подсистемы Windows для Linux (WSL), введя эту команду в PowerShell администратора или в командной строке Windows, а затем перезагрузив компьютер.
wsl --установить
После завершения перезагрузки компьютера установка продолжится, и вам будет предложено ввести имя пользователя и пароль. Это будут ваши учетные данные Linux для дистрибутива Ubuntu.
Теперь вы готовы начать использовать приложения Linux с графическим интерфейсом на WSL!
Для получения дополнительной информации проверьте установку WSL.
Существующая установка WSL
Если на вашем компьютере уже установлен WSL, вы можете выполнить обновление до последней версии, включающей поддержку графического интерфейса Linux, выполнив команду обновления из командной строки с повышенными привилегиями.
Выберите Пуск , введите PowerShell , щелкните правой кнопкой мыши Windows PowerShell и выберите Запуск от имени администратора .
Введите команду обновления WSL:
wsl --обновление
Вам потребуется перезапустить WSL, чтобы обновление вступило в силу. Вы можете перезапустить WSL, выполнив команду shutdown в PowerShell.
wsl --выключение
Примечание
Приложения Linux с графическим интерфейсом поддерживаются только с WSL 2 и не будут работать с дистрибутивом Linux, настроенным для WSL 1. Узнайте, как изменить дистрибутив с WSL 1 на WSL 2.
Запуск приложений Linux с графическим интерфейсом
Вы можете запустить следующие команды с терминала Linux, чтобы загрузить и установить эти популярные приложения Linux. Если вы используете дистрибутив, отличный от Ubuntu, он может использовать другой менеджер пакетов, чем apt. После установки приложения Linux вы можете найти его в меню Start под именем дистрибутива. Например: Ubuntu -> Microsoft Edge
.
Примечание
Поддержка приложений с графическим интерфейсом пользователя в WSL не обеспечивает полноценного рабочего стола. Он зависит от рабочего стола Windows, поэтому установка инструментов или приложений, ориентированных на рабочий стол, может не поддерживаться. Чтобы запросить дополнительную поддержку, вы можете зарегистрировать проблему в репозитории WSLg на GitHub.
Обновите пакеты в дистрибутиве
sudo apt update
Установить Gedit
Gedit — это текстовый редактор по умолчанию для среды рабочего стола GNOME.
sudo apt установить gedit -y
Чтобы запустить файл bashrc в редакторе, введите: gedit ~/.bashrc
Установите GIMP
GIMP — это бесплатный редактор растровой графики с открытым исходным кодом, используемый для обработки и редактирования изображений, рисования произвольной формы, перекодирование между различными форматами файлов изображений и более специализированные задачи.
sudo apt установить gimp -y
Для запуска введите: gimp
Установите Nautilus
Nautilus, также известный как GNOME Files, представляет собой файловый менеджер для рабочего стола GNOME. (Аналогично проводнику Windows).
sudo apt установить nautilus -y
Для запуска введите: nautilus
Установите VLC
VLC — это бесплатный кроссплатформенный мультимедийный проигрыватель с открытым исходным кодом и фреймворк, который воспроизводит большинство мультимедийных файлов.
sudo apt установить vlc -y
Для запуска введите: vlc
Установить приложения X11
X11 — это оконная система Linux, представляющая собой разнообразный набор приложений и инструментов, поставляемых вместе с ней, таких как xclock, калькулятор xcalc, xclipboard для вырезания и paste, xev для тестирования событий и т. д. Дополнительную информацию см. в документации x.org.
sudo apt install x11-apps -y
Для запуска введите название инструмента, который хотите использовать. Например:
-
xcalc
,xclock
,xeyes
Установите Google Chrome для Linux
Чтобы установить Google Chrome для Linux:
- Перейдите во временную папку:
cd /tmp
- Используйте wget для загрузки:
sudo wget https://dl.google.com/linux/direct/google-chrome-stable_current_amd64.deb
- Получить текущую стабильную версию:
sudo dpkg -i google-chrome-stable_current_amd64.deb
- Исправьте пакет:
sudo apt install --fix-broken -y
- Настройте пакет:
sudo dpkg -i google-chrome-stable_current_amd64.deb
Для запуска введите: google-chrome
Установите Microsoft Teams для Linux
Чтобы установить Microsoft Teams для Linux:
- Перейдите во временную папку:
cd /tmp
- Используйте curl для загрузки пакета:
sudo curl -L -o ".
/teams.deb" "https://teams.microsoft.com/downloads/desktopurl?env=production&plat=linux&arch=x64&download=true&linuxArchiveType=deb"
- Используйте apt для его установки:
sudo apt install ./teams.deb -y
Для запуска введите: team
Установить браузер Microsoft Edge для Linux
Информацию о том, как установить браузер Microsoft Edge для Linux с помощью командной строки, можно найти на сайте Edge Insider. Выберите Получить инструкции в разделе Установка из командной строки на странице.
Для запуска введите: microsoft-edge
Устранение неполадок
Если у вас возникли проблемы с запуском приложений с графическим интерфейсом, сначала ознакомьтесь с этим руководством: Диагностика проблем типа «не удается открыть дисплей» с помощью WSLg
Git — клиенты с графическим интерфейсом
Git поставляется со встроенными инструментами с графическим интерфейсом для фиксации (git-gui) и просмотра (gitk), но есть несколько сторонних инструментов для пользователей, которым нужны возможности для конкретной платформы.
Если вы хотите добавить в этот список еще один инструмент с графическим интерфейсом, просто следуйте инструкциям.
Все Окна Мак линукс Андроид iOS
0 линукс Графические интерфейсы показаны ниже ↓
Рабочий стол GitHub
Платформы : Mac, Windows Цена: Бесплатно Лицензия: MIT
Исходное дерево
Платформы : Mac, Windows Цена: Бесплатно Лицензия: Собственность
ЧерепахаGit
Платформы : Windows Цена: Бесплатно Лицензия: GNU GPL
Git-расширения
Платформ: Linux, Mac, Windows Цена: Бесплатно Лицензия: GNU GPL
GitKraken
Платформы : Linux, Mac, Windows Цена: бесплатно / $59+/пользователь в год Лицензия: Собственность
Магит
Платформы : Linux, Mac, Windows Цена: Бесплатно Лицензия: GNU GPL
СмартГит
Платформы : Linux, Mac, Windows Цена: Бесплатно для некоммерческого использования / 59 долларов США за пользователя в год Лицензия: Собственность
Башня
Платформы : Mac, Windows Цена: $69+/пользователь в год (бесплатная 30-дневная пробная версия) Лицензия: Собственность
MeGit (на основе EGit)
Платформы : Linux, Mac, Windows Цена: Бесплатно Лицензия: EPL2.
0
Возвышенное слияние
Платформы : Linux, Mac, Windows Цена: 99 долларов США за пользователя / 75 долларов США за пользователя в год (бесплатная пробная версия) Лицензия: Собственность
GitUp
Платформы : Mac Цена: Бесплатно Лицензия: GNU GPL
Вилка
Платформы : Mac, Windows Цена: $49,99 (бесплатная пробная версия) Лицензия: Собственность
GitAhead (больше не находится в активной разработке)
Платформы : Linux, Mac, Windows Цена: Бесплатно Лицензия: MIT
гит
Платформы: Linux, Windows Цена: Бесплатно Лицензия: GNU GPL
негит
Платформы : Linux, Mac, Windows Цена: Бесплатно Лицензия: MIT
Беглец
Платформы : Linux, Mac, Windows Цена: Бесплатно Лицензия: Vim
LazyGit
Платформы : Linux, Mac, Windows Цена: Бесплатно Лицензия: MIT
Гитара
Платформы : Linux, Mac, Windows Цена: Бесплатно Лицензия: GNU GPL
Карманный Гит
Платформы : Android Цена: 2,49 €/$1,99 Лицензия: Собственность
Анкорпойнт
Платформы : Mac, Windows Цена: Бесплатно / 20 € Лицензия: Собственность
Рабочая копия
Платформы: iOS Цена: Бесплатно / $19,99 Лицензия: Собственность
Гитфокс
Платформы : Mac Цена: 39,99 евро за пользователя в год / 79,99 евро (бесплатная 30-дневная пробная версия) Лицензия: Собственность
гит-кола
Платформы : Linux, Mac, Windows Цена: Бесплатно Лицензия: GNU GPL
GitUI
Платформы : Linux, Mac, Windows Цена: Бесплатно, но приветствуются пожертвования Лицензия: MIT
хихикать
Платформы : Linux Цена: Бесплатно Лицензия: GNU GPL
Золото
Платформ: Linux, Mac, Windows Цена: Бесплатно Лицензия: Собственность
SnailGit
Платформы : Mac Цена: Бесплатно (ограничено) / $9,99 Лицензия: Собственность
RepoZ
Платформы : Mac, Windows Цена: Бесплатно Лицензия: MIT
Конг
Платформы : Windows Цена: Бесплатно Лицензия: Собственность
ГитДрайв
Платформы: iOS Цена: Бесплатно / $6,99 Лицензия: Собственность
GitFiend
Платформы : Linux, Mac, Windows Цена: Бесплатно Лицензия: Собственность
GitAtomic
Платформы : Windows Цена: $17,99+/пользователь в год (бесплатная 30-дневная пробная версия) Лицензия: Собственность
НитроГит
Платформы : Windows Цена: Бесплатно для некоммерческого использования / 20€/пользователь Лицензия: Собственность
GitFinder
Платформы : Mac Цена: бесплатно (ограничено) / 29,95 долларов США (бесплатная 30-дневная пробная версия) Лицензия: Собственность
Вершд
Платформы : Linux, Mac, Windows Цена: Бесплатно для некоммерческого использования / $37/пользователь в год Лицензия: Собственность
GitVine
Платформы : Linux, Mac, Windows Цена: Бесплатно Лицензия: Собственность
ПолиГит
Платформы: iOS Цена: Бесплатно (ограничено) / 11,99 долл.
США в год / 39,99 долл. США Лицензия: Собственность
Гитгуи
Платформы : Linux, Mac, Windows Цена: Бесплатно Лицензия: MIT
Гиттюп
Платформы : Linux, Mac, Windows Цена: Бесплатно Лицензия: MIT
Git-клиент
Платформы : Linux Цена: Бесплатно Лицензия: GNU GPL
GitViewer
Платформы: Mac, iOS Цена: бесплатно / 6,99 долл.
США (бесплатная 7-дневная пробная версия) Лицензия: Собственность
CommandGit
Платформы : Windows Цена: $5,99/мес (бесплатная 14-дневная пробная версия) Лицензия: Собственность
гитонический
Платформы : Linux, Mac, Windows Цена: Бесплатно Лицензия: AGPL-3.0 или выше
Гитнуро
Платформы : Linux, Mac, Windows Цена: Бесплатно Лицензия: GNU GPL
Есть и другие отличные инструменты с графическим интерфейсом. Взгляните на список интерфейсов, интерфейсов и инструментов в Git Wiki.
MATLAB GUI — MATLAB & Simulink
Графические пользовательские интерфейсы (GUI), также известные как приложения, обеспечивают управление программными приложениями методом «укажи и щелкни», избавляя других от необходимости изучать язык или вводить команды для запуска приложение. Вы можете обмениваться приложениями как для использования в MATLAB, так и в качестве автономных настольных или веб-приложений.
Вы можете выбрать один из следующих трех способов создания приложения в MATLAB:
- Преобразование сценария в простое приложение: Выберите этот вариант, если вы хотите поделиться сценарием со студентами или коллегами и разрешить им изменять переменные с помощью интерактивных элементов управления.
- Создание приложения в интерактивном режиме : выберите этот вариант, если вы хотите создать более сложное приложение, используя среду перетаскивания для построения пользовательского интерфейса.
- Создать приложение программно: Выберите этот вариант, если хотите создать пользовательский интерфейс приложения, самостоятельно написав код.
Преобразование сценария в простое приложение
Используйте Live Editor для преобразования сценария в простое приложение с интерактивными элементами управления, позволяющими другим экспериментировать с переменными в вашем коде. Добавляйте ползунки, раскрывающиеся списки, поля редактирования и кнопки без написания кода. Укажите, какие части скрипта будут выполняться при изменении значения. Скройте код для создания простых приложений и информационных панелей.
Живой скрипт с интерактивным управлением.
Вы можете поделиться своим live-скриптом с другими, чтобы использовать его в MATLAB или MATLAB Online.
Интерактивные элементы управления хороши для создания простого интерфейса для живого скрипта. Если вы хотите разработать более сложный пользовательский интерфейс или хотите лучше контролировать поведение приложения, вам следует рассмотреть возможность создания автономного приложения с помощью App Designer.
Узнать больше
- Интерактивные элементы управления в Live Editor (2:15) - Видео
- Живой редактор MATLAB - Обзор
- Галерея живых сценариев - Примеры живых сценариев от сообщества
- Совместное использование и совместная работа с помощью MATLAB Drive - Документация
Интерактивное создание приложения
App Designer — это интерактивная среда, объединяющая две основные задачи создания приложения: размещение визуальных компонентов и программирование поведения приложения. Это позволяет быстро переключаться между визуальным дизайном на холсте и разработкой кода в редакторе MATLAB.
Интерфейс дизайнера приложений.
Вы можете поделиться своим приложением с другими, чтобы использовать его в MATLAB на рабочем столе или в веб-браузере с помощью MATLAB Online. Приложения App Designer также могут быть упакованы для установки на вкладке MATLAB Apps. Чтобы поделиться с пользователями, не являющимися пользователями MATLAB, вы можете скомпилировать приложения в автономные настольные и веб-приложения с помощью компилятора MATLAB.
App Designer удобен для интерактивного проектирования вашего макета и программирования его поведения в одной среде. При желании вы можете самостоятельно запрограммировать все приложение, включая пользовательский интерфейс.
Узнать больше
- Дизайнер приложений MATLAB - Обзор
- Начало работы с конструктором приложений (4:49) - Видео
- Галерея компонентов - Обзор
- Совместное использование и совместная работа с помощью MATLAB Drive - Обзор
- Пакет приложений в App Designer - Документация
- Начало работы: автономные приложения с использованием компилятора MATLAB (3:58) - Видео
- Совместное использование с сервером MATLAB Web App
Программное создание приложения
Для дополнительного контроля над дизайном и разработкой вы также можете использовать функции MATLAB для определения макета и поведения вашего приложения. В этом подходе вы создаете фигуру, которая служит контейнером для вашего пользовательского интерфейса, и программно добавляете к ней компоненты.
Пользовательское приложение с графическим интерфейсом в MATLAB.
Вы можете поделиться своим приложением с другими, чтобы использовать его в MATLAB на рабочем столе или в веб-браузере с помощью MATLAB Online. Приложения также могут быть упакованы для установки на вкладке MATLAB Apps. Чтобы поделиться с пользователями, не являющимися пользователями MATLAB, вы можете скомпилировать свои приложения в автономные настольные приложения с помощью компилятора MATLAB.
Узнать больше
- Программная разработка приложений с использованием uifigure - Документация
- Совместное использование и совместная работа с помощью MATLAB Drive - Обзор
- Пакет приложений из панели инструментов MATLAB
- Начало работы: автономные приложения с использованием компилятора MATLAB (3:58) - Видео
Дополнительные ресурсы
- Что такое приложения MATLAB? (3:35) - Видео
- Написание приложений в MATLAB - Статья
- Пользовательские приложения с пользовательским графическим интерфейсом - Обмен файлами
- Создание графических пользовательских интерфейсов обработки изображений с помощью модульных инструментов - Документация
- Визуализация данных и пользовательские интерфейсы - Консалтинговые услуги
- Сравнение GUIDE и App Designer - Обзор
- Разработка приложений на основе фигур
- Совместное использование с сервером MATLAB Web App
- Объектно-ориентированное программирование в MATLAB
См. также: компилятор MATLAB, Приложения MATLAB
Stack Builders — создание приложения с графическим интерфейсом на языке Haskell
В этом руководстве показано, как создать графический интерфейс пользователя (GUI) приложение на Haskell с привязкой к GTK+. Во время работы на калькуляторе программе мы рассмотрим следующие темы:
- Терминология GTK+
- Написание обработчиков, обрабатывающих действия пользователя (нажатие кнопки и т.п.)
- Введение глобального состояния
- Ручное создание форм и создание форм с помощью Glade
Когда вы закончите обучение, у вас будет четкое представление о том, как
чтобы двигаться дальше, прочтите документацию пакет gtk3
и выполнить
ваши задачи.
Руководство не предполагает каких-либо знаний Haskell, за исключением очень
базовое понимание того, как работать с IO
монада. Привязка GTK+
очень прямолинейна и императивна по своей природе. Это можно рассматривать как
недостатком, но я думаю, что это также может облегчить жизнь новичкам.
Программирование на Haskell с императивным фоном.
Доступные библиотеки
Прежде чем мы начнем с привязок GTK+, разумно спросить, существует ли лучшее/альтернативное решение. Действительно, несколько библиотек доступны для создать графический интерфейс в Haskell:
wx
— крепления к wxвиджеты. Несколько слов об этом пакете Нахожу подозрительным: 1) у него были задержки в развитии, когда на пару лет не выпускалось новой версии, 2) ее до сих пор нет на Stackage. Практический вывод из пункта 2 - он не очень популярен в настоящее время, или, по крайней мере, не многие хаскеллеры начинают писать какое-либо приложение с ним, иначе он уже был бы добавлен.X11
— прямой перевод привязка C к графической библиотеке X11 (цитата взята из пакета описание). «Прямой перевод» означает, что вы передаете указатели.Да, в коде Haskell. Документацию авторы предлагают посмотреть здесь (хотя пикши не пустые либо). Последний выпуск был в мае 2014 года.
hsqml
— Хаскель привязки к QT Quick. Отсутствует в Stackage. Релизы, кажется, происходят раз в год.флэтхс
— Хаскель привязки к библиотеке FLTK GUI. пакет кажется довольно новым, и я лично не вижу никакой выгоды в используя его вместо более зрелых решений.
Что касается GTK+, то вроде:
Стоит отметить, что Haskell разработал гораздо более сильную экосистему в отношении веб-разработки, чем разработка графического интерфейса и настольных компьютеров в целом. Для получения дополнительной информации о состоянии автономных приложений с графическим интерфейсом в Хаскелл, см.:
Установка
См. эту статью для Установка Gtk2Hs. В нем есть инструкции для Windows, Linux, Mac и FreeBSD.
Первые шаги
Приложение калькулятора было выбрано, потому что его логика очень
просто, и мы можем сосредоточиться на работе с инфраструктурой GTK+ без
много отвлечения, сохраняя при этом разумную практичность учебника.
Давайте начнем с импорта некоторых модулей:
импортировать Control.Monad импортировать Control.Monad.IO.Class импорт Data.IORef import Graphics.UI.Gtk скрытие (Action, Backspace)
Как я уже сказал, привязки GTK+ очень важны. Весь код привязки живет в IO
monad, за исключением некоторых случаев, которые мы вскоре рассмотрим.
основной :: IO () главное = делать пустой initGUI -- (1) окно <- новое окно -- (2) -- (3) Окно widgetShowAll -- (4) основнойGUI -- (5)
Первое, что нам нужно сделать в любой программе, использующей GTK+, это вызвать функция
initGUI
. Эта функция выделяет некоторые ресурсы и подготавливает GTK+ к работе, а также ищет аргументы командной строки, относящиеся к GTK+, анализирует их и возвращает все не проанализированные аргументы. За для наших целей нам не нужны аргументы командной строки, так что давайте обернем их снедействителен
.Далее нам нужно окно для построения интерфейса нашего калькулятора внутри Это. Чтобы создать новое окно верхнего уровня, мы используем действие
newWindow
. Это возвращает непрозрачное значениеWindow
, которое можно использовать для управления окно.После создания нового окна мы обычно хотим изменить некоторые параметры, а затем визуализировать его. Сейчас мы просто визуализируем окно «как есть», но в следующем разделе мы увидим, как настраивать виджеты с помощью атрибуты .
widgetShowAll
работает с любым виджетом. Он выполняет все необходимые выделения и делает виджет переданным ему в качестве аргумента виден вместе со всеми его дочерними виджетами.mainGUI
— основной цикл. Цикл прослушивает такие события, как кнопка щелчок и движение указателя мыши и запуск соответствующих обработчиков.
Примечание о нитях. Убедитесь, что все действия GTK происходят в одной и той же ОС.
thread (обратите внимание, это отличается от облегченных потоков Haskell). Это
важно только при компиляции с многопоточной средой выполнения, но кто знает,
возможно, необходимость в параллельном выполнении возникнет позже, поэтому мой совет:
хранить весь код, связанный с GTK, в одном потоке, и самый простой способ сделать это —
держать все это основной поток. Для получения дополнительной информации о
многопоточные графические интерфейсы с GTK+ см. здесь.
Если мы скомпилируем и запустим программу, мы увидим следующее:
Ничего особенного. Одна неприятная деталь заключается в том, что когда мы закрываем окно, программа
продолжает работать. Это связано с тем, что обработчик по умолчанию для щелчка по
Кнопка «закрыть» окна просто делает его невидимым, а основной цикл mainGUI
продолжает работать. посмотрим как поступить в этой ситуации
правильно скоро.
Атрибуты
Атрибуты позволяют настраивать виджеты, например наше окно. Есть два
методы для указания атрибутов виджета:
Установите их с помощью действия
set
.Используйте Glade для разработки пользовательского интерфейса.
Второй вариант мы коснемся позже, а пока давайте познакомимся
с действием установить
. Типичное использование набора
следующее:
установить виджет [ атрибутA := значениеA, атрибутB := значениеB, … ]
Модули GTK структурированы по типу виджета, и каждый модуль обычно
есть раздел «атрибуты». Вот как узнать, какие атрибуты мы
можно подправить. например Окно
имеет следующее:
-
Заголовок окна
-
оконный тип
-
окноИзменяемый размер
…и многие другие. Давайте изменим заголовок нашего окна и сделаем его без изменения размера:
основной :: IO () главное = делать пустой initGUI окно <- новое окно установить окно [ windowTitle := "Калькулятор" , окноРесайзеабле := Ложь , ширина окна по умолчанию: = 230 , высота окна по умолчанию: = 250] окно виджетаПоказать все основнойGUI
Похоже, работает:
Контейнеры
Тем не менее, даже неизменяемое окно с заголовком скучно. Что мы хотели бы
нужно поместить что-нибудь в это окно. Это подводит нас к GTK+
понятие контейнер . Контейнер — это виджет, который может содержать другой
виджеты внутри. Есть два типа контейнеров:
Внутренние виджеты обычно называются дочерними элементами , в то время как внешний виджет называется позвонил родителю .
Наиболее важные действия, которые вы захотите выполнить с контейнерами:
containerAdd parent child
to addchild
widget toparent
widgetcontainerRemove parent child
to removeдочерний
виджет изparent
виджетcontainerGetChildren
для получения всех дочерних элементов виджета контейнераcontainerForeach
для выполнения действия над всеми дочерними элементами контейнера
Сейчас нам понадобится нередактируемая текстовая область, где мы покажем число вводится и результат вычислений:
основной :: IO () главное = делать … отображать <- записьНовый установить отображение [entryEditable: = False , entryXalign := 1 -- выравнивает содержимое по правому краю , текст записи := "0" ] …
Мы используем виджет Entry
для отображения чисел, но его нельзя редактировать и
выровненный по правому краю. Height — количество строк, которые будет охватывать дочерний элемент
-> ввод-вывод ()
gridNew
и gridSetRowHomogeneous
не требуют пояснений. gridAttach
позволяет вставлять виджеты в сетку, контролируя их
положение и размер. Это очень удобно для нашего приложения-калькулятора, давайте
использовать его:
основной :: IO () главное = делать … сетка <- gridNew -- (1) gridSetRowHomogeneous grid True -- (2) let attach x y w h item = gridAttach элемент сетки x y w h -- (3) прикрепить 0 0 5 1 отображение -- (4) mkBtn "MC" >>= прикрепить 0 1 1 1 -- (5) mkBtn "MR" >>= прикрепить 1 1 1 1 mkBtn "MS" >>= прикрепить 2 1 1 1 mkBtn "M+" >>= прикрепить 3 1 1 1 mkBtn "M–" >>= прикрепить 4 1 1 1 mkBtn "←" >>= прикрепить 0 2 1 1 mkBtn "CE" >>= прикрепить 1 2 1 1 mkBtn "C" >>= прикрепить 2 2 1 1 mkBtn "±" >>= прикрепить 3 2 1 1 mkBtn "√" >>= прикрепить 4 2 1 1 mkBtn "7" >>= прикрепить 0 3 1 1 mkBtn "8" >>= прикрепить 1 3 1 1 мкБтн"9" >>= прикрепить 2 3 1 1 mkBtn "÷" >>= прикрепить 3 3 1 1 mkBtn "%" >>= прикрепить 4 3 1 1 mkBtn "4" >>= прикрепить 0 4 1 1 mkBtn "5" >>= прикрепить 1 4 1 1 mkBtn "6" >>= прикрепить 2 4 1 1 mkBtn "*" >>= прикрепить 3 4 1 1 mkBtn "1/x" >>= прикрепить 4 4 1 1 mkBtn "1" >>= прикрепить 0 5 1 1 mkBtn "2" >>= прикрепить 1 5 1 1 mkBtn "3" >>= прикрепить 2 5 1 1 mkBtn "–" >>= прикрепить 3 5 1 1 mkBtn "=" >>= прикрепить 4 5 1 2 mkBtn "0" >>= прикрепить 0 6 2 1 мкБтн "." >>= прикрепить 2 6 1 1 mkBtn "+" >>= прикрепить 3 6 1 1 containerДобавить оконную сетку -- (6) …
gridNew
создает новую сетку.gridSetRowHomogeneous grid При значении True
все строки имеют одинаковую высоту.Здесь мы определяем вспомогательную функцию
attach
. Он прикрепляет данный виджет к нашасетка
. Порядок аргументов этой функции помогает использовать ее с(>>=)
.Прикрепляем созданный ранее дисплей
сетка
. Так и будет занимают весь верхний ряд.Здесь мы используем комбинацию помощника
mkBtn
иприсоединения
для быстрого создайте кнопки и разместите их на сетке. Я покажу, что такоеmkBtn
в момент.Теперь саму сетку нужно вставить в
окно
, чтобы она была видна. Это делается с помощью упомянутой выше функцииcontainerAdd
.
mkBtn
- помощник для создания кнопки, сейчас это очень просто:
mkBtn :: Строка -> Кнопка ввода-вывода метка mkBtn = сделать btn <- кнопкаНовый установить кнопку [метка_кнопки:= метка] вернуть бтн
Создаем новую кнопку, устанавливаем ее атрибуты (в нашем случае просто метку) и вернуть кнопку.
Сигналы и события
Приложение выглядит как калькулятор, но пока не ведет себя как калькулятор. К исправить это, нам нужно узнать о сигналах и события .
Сигнал — это название того, что может произойти в форме. Почти всегда сигналы связаны с действиями пользователя. Пример сигнала фокус — момент, когда виджет становится активным на форме.
Чтобы выполнить некоторый код на сигнале, мы используем помощник на
:
on :: object -> Обратный вызов объекта Signal -> callback -> IO (объект ConnectId)
Здесь объект
интересующий виджет, обратный вызов
— это действие, которое мы
хочу выступить. Функция
на
возвращает ConnectId
, параметризованный поверх тип объекта
(поэтому мы не можем перепутать идентификаторы соединения для разных
виды объектов). Это идентификатор обработчика сигнала и его единственный
цель состоит в том, чтобы дать вам возможность отключить обработчик сигнала, если вам когда-либо понадобится
Это. Вы можете использовать функцию отключить
из System.Glib.Signals
, чтобы сделать
что.
Каждый сигнал диктует тип, который 9Функция обратного вызова 0062 будет иметь. наиболее часты следующие случаи:
Just
IO ()
: информация обработчику не передается и не ожидал вернуть что-либо. Пример такого сигнала:showSignal
.Обработчики, которым заданы аргументы:
a -> IO Bool
. Пример такого сигналаfocus
, чьи обработчики имеют типDirectionType -> IO Bool
. Еще одна интересная вещь здесь — это возвращаемое значение типа 9.0062 Бул . Этот это соглашение в GTK+, позволяющее отключать обработку по умолчанию некоторых сигналы. Если мы вернем
True
, обработка по умолчанию будет отключена, аFalse
будет держать его активным, выполняя наш обработчик и по умолчанию как Что ж.
Есть еще один способ получить некоторую информацию из
обработчик. Некоторые сигналы диктуют, что обработчик должен находиться в специальной монаде.
называется EventM
вместо обычного ИО
. Сигналы, которым нравятся их обработчики
быть в EventM
называются событиями.
Что такое монада EventM
? На самом деле это синоним типа простой монады.
стек с IO
внизу:
тип EventM t = ReaderT (Ptr t) IO
Это всего лишь монадный преобразователь считывателя поверх IO
. t
определяет
тип информации, которую мы можем извлечь, и какую вспомогательную функцию мы можем использовать
внутри EventM
монада. Они разные для каждого события. Например,
configureEvent
позволяет извлекать информацию о размере окна, а Событие keyPressEvent
предоставляет информацию о ключе, который был
нажата, какая клавиша-модификатор была нажата в это время и так далее. Тип
система не позволяет пытаться извлечь информацию об этом конкретном событии
не обеспечивает.
Я хотел бы процитировать документы, чтобы подчеркнуть важность возвращенного логического значения значение:
Обратите внимание, что обработчик события всегда должен возвращать
True
, если событие было обработано илиFalse
, если событие должно быть обработано другим событием обработчик. Например, обработчик нажатия клавиши должен возвращатьFalse
, если нажатая клавиша не из тех, на которые реагирует виджет. В этом случай, когда событие передается родительским виджетам. Это гарантирует, что нажатие, скажем,Alt-F
открывает меню файла, даже если текущий фокус ввода находится в виджете ввода текста.Для облегчения написания обработчиков, которые может прервать обработку события, этот модуль предоставляет функцию
попытка события
. Эта функция перехватывает исключения соответствия шаблону и возвращаетFalse
. Если signal успешно доходит до конца, он возвращаетTrue
.
Зная все это, мы можем написать простой обработчик, который будет запускаться при активации кнопки.
Глядя на раздел «сигналы» в Graphics.UI.Gtk.Buttons.Button
, buttonActivated
выглядит как наш друг здесь:
-- | Испускается, когда кнопка была активирована (нажата и отпущена). buttonActivated::ButtonClass self => Signal self (IO())
Просто для теста, давайте перепишем mkBtn
, чтобы прикрепить обработчик, который будет обновлять
дисплей с названием нажатой кнопки (всего мы еще не знаем
сделать рабочий калькулятор):
mkBtn :: Строка -> Вход -> Кнопка ввода-вывода Отображение метки mkBtn = сделать btn <- кнопкаНовый установить кнопку [метка_кнопки:= метка] btn кнопка `on` активирована $ установить отображение [entryText := label] вернуть бтн
И нам нужно передать отображение
на mkBtn
вот так:
… mkBtn Отображение "MC" >>= прикрепить 0 1 1 1 mkBtn "MR" дисплей >>= прикрепить 1 1 1 1 …
Еще одна вещь, с которой мы можем сейчас разобраться, это правильное закрытие нашего
заявление. Для этого нам нужен способ вызова функции
mainQuit
:
-- | Выход из основного цикла событий. mainQuit::IO()
Как вы уже догадались, удобное место для установки mainQuit
функция при закрытии окна
. Событие, которое мы ищем,
позвонил удалить событие
:
-- | Сигнал deleteEvent генерируется, если пользователь запрашивает, чтобы -- окно закрыто. Обработчик по умолчанию для этого сигнала уничтожает окно. -- Вызов 'widgetHide' и возврат 'True' при получении этого сигнала -- вместо этого скрыть окно, чтобы позже его можно было показать снова -- без реконструкции. deleteEvent :: WidgetClass self => Signal self (EventM EAny Bool)
В нашем случае мы просто хотим его закрыть, поэтому:
… контейнерДобавить оконную сетку window `on` deleteEvent $ do -- обработчик, запускаемый при уничтожении окна liftIO mainВыход вернуть ложь окно виджетаПоказать все основнойGUI
Обратите внимание, что deleteEvent
параметризует тип EventM
с помощью тега уровня типа EAny
. Его описание:
-- | Тег для событий, не несущих никакой информации, относящейся к конкретному событию. данные EAny
Несмотря на то, что он не содержит никакой информации о конкретном событии, многие
можно извлечь полезную информацию, например, текущее время в момент, когда
событие запущено ( время события
). См. полный список помощников в разделе «Accessor
функции для информации о событиях» раздела Graphics.UI.Gtk.Gdk.EventM
.
модуль.
Я рекомендую вам скомпилировать и запустить приложение, чтобы убедиться, что оно отвечает для активации кнопки и закрывается должным образом.
Использование
IORef
s для состояния приложенияКнопки могут динамически менять отображение, но этого недостаточно, чтобы сделать наш калькулятор действительно полезен. Для этого (как и для большинства других приложений) нам нужно какое-то государство.
Создатели привязки GTK+ не дали нам слишком много вариантов, потому что
тип монады-обработчика фиксирован: это либо обычный IO
, либо EventM
, который,
как мы уже знаем, это всего лишь ReaderT (Ptr t) IO
. Мы ничего не можем вернуть
нестандартные от обработчиков, поэтому единственный способ общаться с внешними
мир через изменяемые ссылки.
Есть два наиболее очевидных варианта:
TVar
s, вероятно, излишни, если вы не выполняете сложную параллельную работу. Что такое
хорошо использовать TVar
s заключается в том, что мы можем обновлять их атомарно. Это может быть
не очень важно для некоторых приложений, но я рекомендую строить с
параллелизм в виду с самого начала. А вот IORef
s можно поменять
атомарно, а также с помощью atomicModifyIORef
.
Теперь мы подошли к вопросу, как смоделировать логику калькулятора. Поскольку реальная логика не является нашей главной задачей в этом уроке, мы пойдем простым путем.
-- | «Значение» содержит текстовое представление первого аргумента в обратном порядке и -- "Действие" применить к нему, см. Значение данных = Строка значения (возможно действие) -- | Действие, применяемое к первому аргументу и текстовому представлению второго -- аргумент перевернут (если применимо).данные Действие = Строка добавления | Строка вычитания | Строка умножения | Строка разделения
Значение
- это наше состояние, оно содержит текстовое представление первого аргумента
и, возможно, представление действия, которое должно быть выполнено над ним. String
s, представляющие аргументы, меняются местами, потому что так быстрее
чтобы добавить/удалить символ в конце строки. Мы изменим
строки обратно, когда пришло время превратить их в Double
s.
Нам также понадобится пара вспомогательных функций. Вот они:
-- | Измените второй аргумент внутри «Действия». mapAction :: (Строка -> Строка) -> Действие -> Действие mapAction f (дополнение x) = дополнение (f x) mapAction f (вычитание x) = вычитание (f x) mapAction f (умножение x) = умножение (f x) mapAction f (Раздел x) = Раздел (f x) -- | Получить второй аргумент от «Действия». getSndArg :: Действие -> Строка getSndArg (дополнение x) = x getSndArg (вычитание х) = х getSndArg (Умножение х) = х getSndArg (Деление x) = x -- | Визуализировать заданное «Значение».renderValue :: Значение -> Строка renderValue (значение x действие) = g x ++ f a ++ (если значение null y, то "", иначе g y) куда (а, у) = иск по делу Ничего -> ("", "") Просто (дополнение arg) -> ("+", arg) Просто (аргумент вычитания) -> ("–", аргумент) Просто (аргумент умножения) -> ("*", аргумент) Just (Деление аргумент) -> ("÷", аргумент) ф "" = "" ж л = " " ++ л ++ " " г "" = "0" г хз = реверс хз
Первые два помогают изменить и извлечь второй аргумент в Действие
, а renderValue
делает все возможное, чтобы отобразить текущее состояние калькулятора. Имея renderValue
, легко написать функцию, которая бы обновляла
дисплей калькулятора:
-- | Сделать так, чтобы на дисплее калькулятора отображалось заданное «Значение». updateDisplay::Entry -> Value -> IO() отображаемое значение updateDisplay = установить отображение [entryText:= значение renderValue]
Наконец-то вместо 9Результирующий объект кнопки Метка отображения mkButton st mutateState = do btn <- кнопкаНовый установить кнопку [метка_кнопки:= метка] btn `on` buttonActivated $ do -- (1) value <- atomicModifyIORef st $ \x -> let r = mutateState x in (r, r) -- (2) отображаемое значение updateDisplay -- (3) вернуть бтн
Как и прежде, мы регистрируем обработчик, который будет срабатывать при нажатии кнопки активация.
atomicModifyIORef
изменяет данныйIORef
атомарно. Обратный вызов должен возвращать кортеж, первый элемент — это новое значение, которое нужно поместить вIORef
, второе значение — это возвращаемое значение действия. В этом случае мы хотите, чтобы значения были равны.Мы вызываем
updateDisplay
, чтобы сделать результаты последнего действия видимыми для пользователь.
Теперь мы можем определить помощника с именем mkBtn
в main
:
основной :: IO () главное = делать st <- newIORef (Value "" Ничего) -- (1) пустой initGUI окно <- новое окно установить окно [ windowTitle := "Калькулятор" , размер окна := Ложь , ширина окна по умолчанию: = 230 , высота окна по умолчанию: = 250] отображать <- записьНовый установить отображение [entryEditable: = False , entryXalign := 1 -- выравнивает содержимое по правому краю , текст записи := "0" ] сетка <- сеткаНовая gridSetRowHomogeneous grid True пусть прикрепит x y w h item = gridAttach элемент сетки x y w h mkBtn = дисплей mkButton st -- (2) прикрепить 0 0 5 1 показать mkBtn "MC" id >>= прикрепить 0 1 1 1 -- (3) mkBtn "MR" id >>= прикрепить 1 1 1 1 …
Нам нужно создать
IORef
, чтобы сохранить там состояние программы.Значение "" Ничего.
- его начальное значение.Вспомогательная функция
mkBtn
использует ранее написанныйmkButton
и просто избавляет нас от шаблонного прохожденияst
иотображения
снова и снова.Несколько примеров использования
mkBtn
. Путем передачиid
в качестве функции изменения состояния мы делаем кнопки бесполезными, но все механизмы для фактической работы уже на месте.
Единственное, что осталось, — это функции изменения состояния для каждой кнопки. Здесь я покажет некоторые из них:
-- | Изменение состояния, как если бы была введена точка. enterDot :: Значение -> Значение enterDot (значение x действие) = пусть f xs = если '.' `elem` xs, затем xs еще '.' : хз в случае действия Ничего -> Значение (f x) Ничего Just a -> Value x (Просто $ mapAction f a) -- | Измените состояние, как если бы был введен определенный символ (цифра).enterDigit::Char -> Значение -> Значение enterDigit ch (значение x действие) = иск по делу Ничего -> Значение (ch:x) Ничего Просто a -> Значение x (Просто $ mapAction (ch:) a) -- | Изменить состояние, как если бы последний символ текущего аргумента был удален. backspace :: Значение -> Значение backspace (значение x действие) = иск по делу Ничего -> Значение (выпадение 1 x) Ничего Just a -> Value x (Just $mapAction (drop 1) a) -- | Применить данный оператор к текущему состоянию. Если какое-то действие уже полностью -- построено, сначала оцените его. оператор :: (Строка -> Действие) -> Значение -> Значение значение операции оператора = пусть (значение x действие) = равно значению в стоимости x $ Просто $ иск по делу Ничего -> оп "" Просто -> op (getSndArg a) -- | Изменить состояние, как если бы текущий аргумент был удален. clearEntry :: Значение -> Значение clearEntry (значение x действие) = иск по делу Ничего -> Значение "" Ничего Просто -> если ноль (getSndArg а) затем значение "" Ничего else Значение x (Просто $ mapAction (const "") a) -- | Изменить состояние, вернув его к значению по умолчанию.
clearAll :: Значение -> Значение clearAll = const (Значение "" Ничего) -- | Оценить текущее состояние калькулятора, поставив результат вместо первого -- аргумент. равно :: Значение -> Значение равно (значение x действие) = иск по делу Ничего -> Значение х Ничего Просто -> если ноль (getSndArg а) затем значение x действие else Значение Результат Ничего куда g :: Строка -> Двойной г "" = 0 г ('.':xs) = г ('0':'.':xs) g xs = читать (обратный xs) х' = г х у' = г (getSndArg а) результат = обратный. показать $ случай Сложение _ -> х' + у' Вычитание _ -> х' - у' Умножение _ -> х' * у' Деление _ -> х'/у'
Калькулятор не идеален, но достаточно хорош для наших целей. Скомпилировать,
запустите его и посмотрите, как он работает. Реализация остального функционала
оставлено в качестве упражнения для читателя.
Использование Glade для создания форм
Возможно, вы заметили, что ручное создание форм довольно немного шаблонного кода в нашем коде. Это может стать еще хуже, когда ваши формы становиться более сложным. В связи с этим, я думаю, пришло время попробовать свои силы в современный дизайнер пользовательского интерфейса для GTK+ под названием Glade.
Glade прост в установке и использовании. Откройте приложение, вы видеть панели с различными виджетами: объекты верхнего уровня (например, окно), контейнеры и элементы управления (например, кнопки).
Вот план воссоздания формы нашего калькулятора с помощью Glade:
Выберите кнопку окна на самой верхней палитре, и окно появится на рабочая зона.
Введите «Калькулятор» в поле заголовка.
Не забудьте заполнить атрибут «ID» каждого виджета, вот как вы получите доступ к виджетам в своей форме в коде Haskell.
Создать сетку с идентификатором
сетка
.На вопрос о количестве строк и столбцов, выберите 7 × 5. Установите флажок «Однородный» под заголовком «Строки».
Вставьте запись, используйте кнопку «Перетаскивание и изменение размера виджетов в рабочей области» на верхнюю панель инструментов, чтобы она занимала всю верхнюю строку.
Вставьте кнопки, чтобы они соответствовали нашему существующему дизайну.
(Вот увеличенное изображение.)
Подсказка: полная форма Glade нашего калькулятора доступна по адресу Учебный репозиторий Stack Builders.
Чтобы использовать форму в коде Haskell, нам нужен Builder
, который находится в Модуль Graphics.UI.Gtk.Builder
. Объект Builder
помогает в создании
Пользовательский интерфейс из файлов XML на лету.
Вот как мы могли бы использовать это в нашей программе:
… строитель <- строительНовый -- (1) builderAddFromFile построитель "calc.glade" -- (2) btn0 <- builderGetObject построитель castToButton "btn_0" -- (3) …
Нам нужно создать новый билдер.
Загружаем в него нашу форму из файла. Есть и другие варианты, например загрузка текста формы (
String
,Text
) и так далее. Обратитесь к документам для Дополнительная информация.Теперь интересно то, что мы можем получить фактический объект кнопки, зная его идентификатор. Например, здесь я получаю кнопку, которая вводит нули, он имеет идентификатор
"btn_0"
в моей форме.castToButton
приводит абстрактные представление объекта в его типизированную форму. Есть многоcastToSomething
функции, по одной на виджет (например, у нас естьcastToWindow
для окон).
Наличие фактического объекта, такого как эта кнопка или само главное окно,
легко действовать так же, как с созданной вручную формой, чтобы начать
основная петля.