Что сейчас актуально для создания GUI?
Осваиваю Visual C++ и, собственно, задался этим вопросом с целью найти оптимальное решение с прицелом на межплатформенность. Начал довольно странно, а именно с Qt 🙂 . Потом вспомнил о «чуде» под названием MFC, немножко поковырявшись в нем сложилось впечатление, что MFC это творчество душевнобольного человека. Возможно я неправ и меня испортил Qt .
К чему я это все? Просто хочу узнать ваше мнение. Что сейчас актуально для создания GUI ? Можно ли предположить, что Win32 API + MFC это отмирающие (знать конечно нужно для общего развития, но не более), а Qt и wxWidgets это актуальное настоящее и за подобными межплатформенными разработками будущее ? Так как, разработчик должен тратить львиную часть своего времени на написание логики, а не на создание визуальных эффектов. Также не стоит ограничивать себя одной платформой, но это опять таки мое скромное мнение.
PS: Есть еще парочка вопросов:
1. Как обстоят дела с СОМ технологиями ?
2. Посоветуйте учебники по написанию сетевых приложений в С++ и C# .
Подобається Сподобалось 0
До обраного В обраному 0
39 коментарів
Маленький офтоп. Для тех, кто мучится с установкой Qt для Visual Studio Windows 7:
1. Требования Qt для Windows:doc.qt.nokia.com/. ements-win.html или doc.crossplatform.ru/. ements-win.html . В итоге у вас должно быть: Microsoft’s DirectX Software Development Kit, Microsoft’s Windows Server 2003 R2 Platform SDK, Microsoft Windows SDK for Windows 7, ActivePerl и все обновления для Windows 7 (и в частности для Visual Studio). Также не забываем о Qt Visual Studio Add-in.
2. Установка Qt для Windows: для Visual Studio doc.qt.nokia.com/. nstall-win.html (русский аналог doc.crossplatform.ru/. nstall-win.html ). Для Visual Studio 2010 www.cyberforum.ru/. read340639.html (использование jom спорно, вполне можно обойтись nmake)
3. Если у вас при посещении Visual Studio Command Prompt есть ошибка «ERROR: Cannot determine the location of the VS Common Tools folder.» Лечится так: в установках переменных окружения в переменную среды PATH добавляем С:\windows\system32
Насчет параметров ввода configure. Если у вас все запросы пункта 1 удовлетворены, то выполняем команду: configure -debug-and-release -opensource -platform win32-msvc2010 (вместо 2010 ваша версия Visual Studio) и не паримся.
Еще раз повторюсь, что очень важно удовлетворить требования Qt для Windows (1 пункт) иначе рискуете получить ошибки на этапе компиляции Qt, а затем долго и нудно искать на форумах решение этих проблем (которое приведет вас в итоге к 1 пункту 😀 ).
PS: Надеюсь, что мой «мануал» кому то сэкономит время и нервы : ) .
найти оптимальное решение с прицелом на межплатформенность.
хєх. 15 лет назад я задавался этим вопросом и так ничего не решилось , была надежда на mono и порт Forms но они решили двигаться через gtk, хотя это не с++
с си — wxWidgets внутри очень похож на MFC — дефайны и все такое, хотя некоторые проги выглядят очень даже, таже audacity
qt — ну вы сами знаете,
есть еще xul (недавно выпиляный из файрфокса) — например в VirtualBox пользуется и движек OpenOffice
но вообще выбор зависит от задач — если нужен гуй гармонично вписанный в систему, то тут на родном будет легче, вплоть до написания под каждую ось своей морды (как тот же файрфокс)
если просто более менее — то qt и wx — вполне
1. Как обстоят дела с СОМ технологиями ?
COM технологию уже лет как убил и закопал NET, если вы не собираетесь поддерживать старый код, то забудте про нее.
2. Посоветуйте учебники по написанию сетевых приложений в С++ и C# .
Тут больше зависит от системы , где ты буш писать эти приложения. Если под виндой на том же C#, то это набор NET классов и к укровню сокетов тебя фиг кто допустит (при желании конечно можно поковыряться, но это если есть необходимость).
Под тем же линухом, у тебя выбор поболее, ты можешь работать с сетью чрез сетевой интерфейс той же Qt например или мудохаться с уровнем сокетов (сетевой уровень TCP/IP) напрямую, можешь заюзать какуе то модную либу — курл, например, васе зависит от целей и задач.
На счет ГУИ под виндой тут счас ситуация довольно таки запутанная, основной выбор прогерров — C#/NET. Есть люди, которые юзают С++/Qt. Такой свзяки как C++/NET не существуюет.
По последнему пункту — мелкософт, по каким то причинам, поступило довольно по скотски.
а) — Есть висул студия «с поддержкой языка С++»
б) — Есть , довольно мощная, платформа NET
Так вот, в висуале, ты можешь писать на С++, но при этом нельзяю юзать NET либы (тот же гуи)
Или ты можешь писать с использованием NET, но при этом мелкософт тебе подсовывает язык программирования — «C++/CLI» — эт такая хренька, которая, при ближайшем рассмотрении, ничего обзщего (или очень мало общего) имеет с языком программирования С++.
Вот, вобщем таки вот пироги.
COM технологию уже лет как убил и закопал NET, если вы не собираетесь поддерживать старый код, то забудте про нее.
Частично не соглашусь, если нужно делать специфические вещи, связаные с виндой, часто без COM не обойтись.
Согласен, но с оговоркой, если уже говорить о специфических вещах, то не обойтись и без WinAPI, все эти — NET, Qt да и то же MFC — это очень модно(это не про МФЦ), красиво и быстро в плане разработки, но когда речь заходит о (очень специфические вещи) то без WiaAPI, в некоторых случаях того же СОМ — не обойтись.
COM технологию уже лет как убил и закопал NET, если вы не собираетесь поддерживать старый код, то забудте про нее.
не убил и не закопал. Как ты напишеш например тулбар к IE? .net тут помощет, но без понимания комовских интерфейсов все равно не обойдешся
Спс за информацию, пока буду учить Qt, C#.NET. Потом займусь как нибудь API и COM.
Повеселила фраза про
MFC это творчество душевнобольного человека
У меня в универе было точно такое же впечатления после того как посмотрел на него после джавовского свинга. Хотя свинг тоже не особо любят, но по сравнению с MFC это конфетка 🙂
Когда он только появился — то впечатление было у масс другое 🙂
Ибо тогда не было Qt (родился на три года позже), не было .Net, не было даже wtl %), а был WinAPI — по сравнению с ним MFC оказался более чем крут.
Ну а сейчас писать на MFC — однозначно изврат. Это то же самое, что пытаться запрячь лошадь в автомобиль. Конечно можно, если постараться.
Ну и микрософт специально и придумала C++/CLI для тех, кто хочет писать на С++, но не хочет учить С# (.Net правда учить все равно придется — но ничего не бывает просто так). Ну или там, где технически С# не подходит для каких либо задач. А вообще С+±нику начать писать на C#/.Net — это достаточно просто. У нас ни у кого из ребят проблем при переходе не было.
Когда он только появился — то впечатление было у масс другое 🙂
Ибо тогда не было Qt (родился на три года позже), не было .Net, не было даже wtl %), а был WinAPI — по сравнению с ним MFC оказался более чем крут.
Ну а сейчас писать на MFC — однозначно изврат. Это то же самое, что пытаться запрячь лошадь в автомобиль. Конечно можно, если постараться.
Ну и микрософт специально и придумала C++/CLI для тех, кто хочет писать на С++ (все же что-то общее у них есть %), но не хочет учить С# (.Net правда учить все равно придется — но ничего не бывает просто так). Ну или там, где технически С# не подходит для каких либо задач. А вообще С+±нику начать писать на C#/.Net — это достаточно просто. У нас ни у кого из ребят проблем при переходе не было. Да и в принципе можно микшировать языки в проекте — но только если это оправдано.
Я это знаю и радует что прогресс не стоит на месте 🙂
C++/CLI скорее служит как bridge между native и managed code, потому что от C++ он отличается довольно таки сильно.
Для шаблонного и простого ГПИ подойдет Qt. Но если вам нужен особенный и индивидуальный ГПИ, то однозначно нужно использовать средства платформы: WPF, Cocoa, GTK. WinAPI используется там где есть время на нем писать, в старых проектах и в таких проектах как Evernote. На Qt так же можно писать красивые интерфейсы используя QSS.
В целом вам нужно ориентироваться на рынок на котором вы планируете продавать свои услуги. Если это Украина, то вакансий по Qt вы найдете не много. Насколько я знаю, Qt сейчас используется в Materialize в разработке мед. программ, в GlobalLogic в разработке муз. программы от Avid и все. C# используется практически везде, в том смысле, что вакансий очень много. Так же не мало вакансий требующих знаний Cocoa под Макинтош.
Если вы прицелены на заграницу, то нужно изучать спрос на зарубежных сайтах по работе. Так, Autodesk Maya 2011 портирована на Qt.
GTK+ это в основном ведь Linux ? Для С++ это gtkmm, а С#.NET это Gtk# . В Cocoa на С#.NET это NObjective и Cocoa Sharp. Как тут с ними?
Да, GTK это для Линукса, в основном под оболочку Gnome. В KDE используется Qt.
Я не слышал, что бы кто то использовал NObjective и Cocoa Sharp в серьёзных проектах. Для Мака используется язык Objective C и Сосоа АПИ. C# это только для Виндоуз.
А ещё для Linux и Mac OS.
Давайте будем реалистами: Ц№ не для винды — это извращение. Речь не о языке, а о платформе.
А какая среда разработки под win для qt сейчас популярна ? Кроме Microsoft Visual Studio, целый день убил на установку Qt libraries под vs2005-2010.Так нечего и не вышло . Как с Qt Creator ?
Вам сложно, потому что вы начинающий. Когда разберетесь, то сможете за 10 минут настроить Visual Studio для работы с библиотеками Qt. Не забывайте про Qt Visual Studio Add-in. Читайте, разбирайтесь, в интернете много информации. Правда в основном на английском.
Qt Creator, по-моему, еще редко где используется. В основном в небольших открытых проектах.
У меня траблы на этапе компиляции библиотеки, в основном трабла с qmake. Я все форумы обегал в писке решения, буду изучать qt в Qt Creator.
а зачем ее компилировать? там есть готовые бинарники.
скомпилить новичку ее полностью будет очень тяжело. Например понадобится скачать и поставить либы/хиадере к mysql чтобы соответсвующий коннектор скомпилить, еще понадобится DirectX. Вообщем нужно ставить сдк и не парится.
Ну я качаю Qt libraries 4.7.4 for Windows, далее все как в инструкции doc.qt.nokia.com/. nstall-win.html . Все форумы уже обходил и разные комбинации попробовал. Итог один — Building qmake failed, return code 2 . В конечном счете скачал их Qt SDK и учу Qt Creator.
Изначально ругается на Microsoft’s DirectX Software Development Kit, хотя он у меня стоит. Как и MW SDK 7.1 и все возможные обновления, даже ActiveState Perl поставил .
почитай доку, как это билдать под видной. Думаю тебе достаточно будет запускать configure не с параметрами по-умолчанию, а отключить phonon. Хотя сакральный смысл «побилдать»в ситуации когда доступны все нужные библиотеки до меня не доходит.
Насколько я знаю, Qt сейчас используется в Materialize в разработке мед. программ
Вы правы:) Год назад наша команда внедрила Qt в проект(www.materialise.com/mimics) над которым я сейчас работаю. На данный момент мы единственная команада в Materialise, котрая использует Qt и уже сейчас к нам подходят люди с других команд и интересуются Qt, так как эта технология полностью себя оправдала:
1) хорошо продуманный дизайн и архитектура
2) по сравнению с MFC экономит много времени при создании GUI
3) можно без проблем миксить Qt и MFC, сажать Qt контролы на MFC и наоборот. Для нас это был очень важный критерий так как приложение реализовано на MFC и его расширениях, переписать все на Qt сразу просто нереально.
4) Qt это не только GUI билиотека — есть функционал по работе с базамы данных, сетями, мультимедиа и т.д. Вообщем еще много очень вкусного.
5) Отличная документация
6) Можно бесплатно использовать в комерческих целях с одним ограничением: можно использовать только динамические библиотеки Qt(я так понимаю своего рода реклама) и нельзя изменять исходники. Нашему продукту эти ограничения абсолютно не мешают. Вероятность того, что нужно что-то менять или фиксить в Qt очень маленькая.
7) Без проблем интегрируется в MS Visual Studio 2005 — 2010
Вообще мы рассматривали много технологий для ускорения разработки GUI и Qt оказался лучшим выбором.
Дать простой ответ на ваш вопрос необычайно сложно. Тут дело не в выборе конкретного средства разработки UI, а скорее, это выбор вашего будущего пути, как программиста.
C++ до сих пор используется для разработки кроссплатформенных приложений и приложений, которым нужен полный контроль над памятью и другими ресурсами системы. Скорость работы приложения — вот главный критерий выбора С++ как основного языка разработки. Кроме того, существует множество успешных проектов, которые создавались заокеанскими разработчиками около 8 — 10 лет назад. Тогда альтернативы С++ не было, но многие из этих проектов сейчас передаются в Украину на аутсорс, так что С++ разработчики будут ценится еще долго.
Если вы сконцентрируетесь на изучении С++, и конкретно под Windows, то вам будет необходимо хорошо владеть WinAPI и COM. Скорее всего это понадобится и для кроссплатформенной разработки, только вам еще будет необходимо знать и устройство Linux\Mac.
Про MFC и WTL может пока забыть, если понадобится — то это дело учится довольно легко.
Чуть не забыл, на С++, вам придется писать сравнительно много кода, чтобы добиться конкретного результата.
.NET (C#) и Java — эти языки созданы для упрощения программирования бизнес задач. Позволяют добиваться необходимых задач меньшим количеством строк кода и без изобретения велосипедов. GUI приложения на Java выглядят довольно плачевно. На C# вы можете использовать технологии WinForms или WPF, которые позволят быстро создавать десктопные приложения. При помощи WPF вы можете очень просто делать чудеса. Но, гарантированно работать это будет только под Windows.
.NET (ASP.NET) и Java одинаково хороши на серверной стороне. Например, серьезные банковские приложения, использующие несколько серверов, предпочитают работать больше с Java, но и .NET тут не уступает, и все больше и больше серьезных корпоративных приложений пишутся на .NET.
Но, «порог входа» в эти технологии довольно высок. Именно поэтому очень много вакантных мест и специалисты по этим технологиям получают в среднем высокие зарплаты.
Ну, и если мы говорим о серверных приложениях, то тут необходимо упомянуть такие языки, как Perl, PHP, Python, Ruby. В основном они используются для разработки веб приложений и делают веб разработку простой. Тут то и используется HTML+Javscript+CSS для UI.
Я бы посоветовал вам попробовать все по чуть-чуть и понять что вам больше по вкусу.
Все верно, только вы забыли про Silverlight. В принципе, это тот же WPF, только для выполнения в браузере. И в отличие от WPF, поддерживается, хотя и полуофициально, на других системах тоже (по крайней мере, полная поддержка SL приложений на Linux это их декларируемая цель). Также есть возможность делать Out-of-browser приложения (не требуют браузера).
Ну, тогда еще стоит упомянуть про Adobe Flex и Adobe Air. Хорошо работает на всех платформах, кроме iPhone ;).
Есть рынок разработки. Только вот, Adobe Flex и Adobe Air обычно идет с серверной Java (J2EE). Но, можно и приложения для вконтактов и фейсбуков писать, что успешно люди и делают.
GUI с нуля за час. Ищем решения типовых задач при создании графического интерфейса
Lead iOS-разработчик в neoviso Игорь Шавловский в материале «Давайте напишем Windows!» предложил «зажигать пиксели один за другим». Теперь переходим к рендеру и разбираем код из репозитория на GitHub. Для её запуска используйте класс CustomApplication.
Давайте подумаем, как именно будет организована работа приложения. Для этого зададим правильные вопросы: кто, когда, где и что должен рисовать?
Так как корневой элемент интерфейс — это рабочий стол, рисовать следует именно его, при этом команды должны уходить на драйвер устройства (VideoDevice). Допустим, устройство есть, рабочий стол тоже. Но как их связать вместе? Нужен посредник (Application), который будет готовить девайс и через графический контекст передавать на него команды рендера с рабочего стола. Когда он должен это делать
Постоянно, ведь интерфейс рисуется синхронно с частотой обновления монитора, для этого стоит выделить отдельный поток с бесконечным UI-циклом, где и будет непрерывно происходить рендер. После того как все элементы отрисуются в драйвер устройства, ему необходимо дать команду на отображение полученного изображения на матрице монитора. Это будет ещё одна операция для UI-цикла.
Как работает GUI-приложение
Что ещё может происходить в UI-цикле? Если нам надо переместить окно на рабочем столе или сменить текст в лейбле, добавить дочерний элемент, можем ли мы сделать это во время отрисовки? Очевидно, эти операции могут быть небезопасными. Например, можно добавить элемент в массив childs в тот момент, когда он находится в процессе перечисления, что вызовет ошибку. И это не единственное тонкое место — изменение размеров элементов, текста, цвета и других параметров во время отрисовки могут создать проблемы в коде рендера.
Правильным решением здесь будет синхронизация процесса рендера и модификации параметров элементов интерфейса. Поскольку подобные операции (назовём их invoke) в GUI происходят довольно часто, хорошим решением будет просто выполнять их в том же потоке, что и рендер, непосредственно перед ним. Для этого сделаем очередь операций и выберем метод добавления операции в очередь (invokeLater).
Программист, который хочет провести модификацию иерархии/параметров элементов, должен делать это только внутри таких операций. Кроме того, события ввода (например, с мыши и клавиатуры) также должны обрабатываться в этой очереди. Теперь мы имеем представление о том, как работает GUI-приложение.

За пределами приложения лежат устройства ввода-вывода, которые симулированы классами из пакета by.dev.gui.driver, а «виртуальной машиной» является простой JFrame, который получает от «видеоустройства» картинку (Image) и посылает события мыши в соответствующее «устройство» ввода.
Монитор представляет собой буфер пикселей, в который и рисуется интерфейс, а в конце каждого UI-цикла созданная им видеостраница посылается на «матрицу».
Для управления буфером пикселей создан класс Texture. Ещё вы могли заметить, что GraphicsContext потерял свойство offset и теперь всегда рисует в текстуру, начиная с верхнего левого угла (это изменение будет объяснено ниже при рассмотрении алгоритмов полупрозрачности), у него появился метод fill () для монохромной заливки прямоугольной области, а также наследник SafeGraphicsContext. Дело в том, что дочерние элементы зачастую могут выходить за границы своих родителей, следовательно, их пиксели могут отрисоваться в несуществующие области текстуры. Чтобы не производить проверку попадания в границы родителя каждый раз, проще всего делать её на стороне графического контекста.
Барабанная дробь! Вот мы и создали все инструменты, чтобы всё вышесказанное обрело хоть какой-то практический смысл.
Пишем собственные элементы интерфейса и рисуем их
Начнём с рабочего стола (Desktop). Это будет просто область, залитая одним цветом, с инструментом для управления окнами приложений. Фактически всё, что нужно для нашего примера, — это механизм выбора и контроля текущего активного окна, а также доставки событий мыши до элементов интерфейса, над которыми они произошли.
Окно приложения (Window) — тоже залитый прямоугольник с границей и заголовком, на котором лежит кнопка закрытия окна. Кнопка (Button) — это прямоугольная область, которая меняет цвет при нажатии на неё и посылает событие (callback) по окончанию нажатия.
И мышь! Возьмите её в руки, повертите, определите, что вы можете с ней сделать: мышь можно перемещать и нажимать на ней кнопки. Отлично, значит это и будет интерфейсом нашего драйвера. Поскольку мышь — устройство ввода, то для него мы не отправляем управляющие команды и лишь принимаем их через MouseDeviceCallback. Отметим, что для драйвера мыши могут существовать и команды управления: установка позиции курсора, чувствительности и т. д.
Осталось доставить входящие в приложение события мыши (MouseEvent) до их конечных получателей — элементов интерфейса. Первым делом надо решить, кто будет управлять этой доставкой — это должен быть класс, который имеет доступ ко всей иерархии элементов, а в нашем случае это как раз рабочий стол, приложение будет сообщать ему о новом событии мыши, вызывая метод onMouseEvent, остальное будет на его совести. Что же именно он должен делать?
Сначала надо придумать алгоритм поиска элемента, который находится в точке, в которой произошло событие мыши — nodeForMouseEvent (). Для этого надо посмотреть на рабочий стол, навести мышь на какую-нибудь кнопку и подумать, как найти именно её, зная только список элементов, лежащих на рабочем столе. И также держать в голове, что в случае, если поверх вашей кнопки лежит окно, оно перехватит событие, и кнопка его не получит. Значит событие получает тот элемент, который лежит выше всех в этой точке. Учитывая порядок отрисовки дочерних элементов в методе draw (), можно понять, что чем выше индекс элемента в массиве childs, тем позже он рисуется. В том числе если положить кнопку А на кнопку В, то кнопка А является получателем события мыши только в том случае, если нажатие не попадает в область кнопки В и попадает в область кнопки А. Так как нарисованный последним элемент лежит выше всех, искать получателя события надо рекурсивно, начиная с родительского элемента в порядке убывания индекса элемента.

Имея этот алгоритм, мы сможем, например, найти кнопку, которая соответствует событию нажатия кнопки мыши и выполнить её действие. Однако просто проброса события до элемента, который находится под курсором мыши, недостаточно.
Как можно реализовать drag-n-drop для окон?
Речь идёт о механизме перетаскивания окна зажатием мыши на его заголовке. Допустим, событие нажатия мыши происходит над заголовком конкретного окна. Окно запоминает, что его в данный момент «тянут» и ждёт событий перемещения мыши и отжатия кнопки. Однако эти события дойдут до окна только в том случае, если пользователь перемещает мышь исключительно в пределах элемента, отвечающего на это событие, то есть заголовка окна. Если же мышь выйдет за его пределы, то nodeForMouseEvent уже не найдёт его как получатель события, и перемещение окна прекратится. Более того, если окно не получит события отпускания кнопки мыши, оно так и останется навсегда в режиме перетаскивания.


Подобные артефакты часто можно увидеть в видеоиграх, когда перетаскиваемый предмет «прилипает» к курсору, если другая программа, например, антивирус, забрала фокус у активного окна непосредственно в момент перетаскивания, и отпускание мыши так и не было доставлено до элемента.
Скажу больше: отдельные элементы в силу своей специфики могут реагировать на события мыши, даже если они не находятся прямо под курсором (курсор за границами элемента), или находятся, но перекрыты другими элементами. Например, если вы тянете файл с рабочего стола в корзину, на события мыши тут будут реагировать сразу два элемента интерфейса: перетаскиваемый файл и сама корзина, которая подсветится при поднесении к ней файла. Причём два элемента — это не предел, их может быть намного больше. Отсюда вывод: события мыши должны получать все элементы интерфейса, и уже какой-то конкретный механизм определяет, как они будут делить это событие между собой.
Можно придумать несколько таких механизмов, но для реализации нашей задачи (событие кнопки при отпускании мыши и перетаскивании окон) можно обойтись малой кровью — подходом с запоминанием активного элемента. Это элемент, который в данный момент эксклюзивно отвечает на события мыши. Пока он активен, рабочий стол будет направлять события исключительно ему, независимо от того, находится ли мышь над элементом или элемент в границах своего родителя. Пока активного элемента нет, рабочий стол будет предлагать событие элементу под курсором, вызывая метод doMouseEvent (). Метод должен возвращать boolean, который говорит, готов ли элемент стать активным. Как только один из элементов вернёт true, он станет активным и будет перехватывать все события мыши. Продолжаться это будет до тер пор, пока doMouseEvent () не вернёт false, что означает — элемент более не активен, и все другие опять могут получать события мыши. Этого простого и немного костыльного подхода хватит, чтобы удовлетворить наши потребности.
Создайте приложение сами!
Имея эти элементы, события мыши и класс Application, мы можем создать простое приложение. Предлагаю написать его с точки зрения разработчика, то есть используя написанный нами GUI как фреймворк. Код приложения вы можете найти в классе CustomApplication.
Усложняем задачу и добавляем полупрозрачность
Напоследок предлагаю усложнить задачу и добавить полупрозрачность. Это типовое задание, которое встречается при разработке интерфейса. Однако без аппаратного ускорения подобная задача становится сравнительно сложной. Давайте разбираться вместе.
Всегда помните — начинаем с малого, с частного, вычленяем простые операции, задаём нужные вопросы. И главный вопрос в каждой задаче — а в чём же она состоит, что такое полупрозрачность? И опять всё сводится к одному пикселю: оригинальный пиксель, лежащий «снизу», переписывается новым пикселем, но при этом не полностью, а в какой-то степени, называемой alpha. Alpha обычно измеряется в тех же единицах, что и каналы цвета, то есть в нашем случае — числом от 0 до 255.
Теперь надо «поиграть» с alpha и понять, какая математика за этим стоит. Техническим языком эта математика называется blending, то есть способ наложения двух цветов. Можно открыть Photoshop и посмотреть как результирующий цвет меняется в зависимости от показателя прозрачности и способа смешивания.
Но нам нужен универсальный и простой способ смешивания. Проще всего понять его в мысленном эксперименте. Представляем себе чёрный квадрат и кладём поверх белый, только полностью прозрачный. Чёрный квадрат останется чёрным, потому что белый не сможет на него повлиять. Теперь представляем, что alpha белого квадрата максимальна, то есть теперь он полностью перепишет чёрный цвет своим. А сейчас мысленно погоняйте в голове прозрачность от минимуму к максимуму и наоборот. Промежуточные цвета будут серыми, то есть все каналы равномерно будут перетекать от 0 к 255, выдавая в результате градиент серого, и чем больше прозрачность белого, тем более тёмный серый мы получаем. Теперь надо увидеть правило, согласно которому всё это работает. Фактически мы имеем простое параметрическое уравнение:
color = source + (dest — source) * (alpha / alphaMax);
То есть для примера с белым и чёрным цветами по каждому каналу уравнение будет выглядеть так:
red = green = blue = 0 + (255 — 0) * (alpha / 255);
Всегда проверяйте свои формулы, подставляя значения из известных предельных случаев!
0 + (255 — 0) * (0 / 255) = 0 (при полной прозрачности чёрный остаётся нулём);
0 + (255 — 0) * (255 / 255) = 255 (при нулевой прозрачности цвет становится белым белый).
Итак, мы поняли, как смешать два пикселя с заданным коэффициентом. Следующий этап — понять, как это смешивание встроить в наш рендер. Во-первых, добавим к Node свойство alpha. Во-вторых, подумаем над самым простым случаем, когда над рабочим столом рисуется одна полупрозрачная кнопка. Сама кнопка может менять цвет в зависимости от своего состояния, на ней может находиться текст, картинка, то есть внешний вид кнопки определяется только ей самой, он не зависит от родителя. Значит альфа должна быть применена в момент рисования уже «готовой» кнопки на рабочий стол.
Сработает ли наш старый подход, при котором сначала отрисуется рабочий стол, а поверх — кнопка? В момент рисования пикселя кнопки она возьмёт текущее значение цвета этого пикселя и прибавит к нему собственный цвет с альфой по описанной сверху формуле и запишет результат поверх исходного цвета. Всё выглядит нормально.
Но что если эта полупрозрачная кнопка будет лежать на полупрозрачном окне? Тогда сначала опять же отрисуется рабочий стол, потом поверх его окно. И вроде всё хорошо? Но рисование кнопки всё испортит. Дело в том, что кнопка относительно рабочего стола полупрозрачна не только на свою полупрозрачность, но и на полупрозрачность окна, которая складывается мультипликативно (так как альфа окна «наследуется» всеми его элементами). Даже если мы сложим альфу кнопки с альфой окна и используем её для отрисовки элемента, мы не получим правильный результат. Результатом отрисовки дочернего элемента на родителя с полупрозрачностью будет исключительно смесь цветов самого элемента и родителя, независимо от более верхних уровней иерархии. Их сумма в свою очередь уже будет рисоваться на следующий слой таким же образом.
Это отлично видно, если мы представим, что альфа окна равна 50%, а кнопка не прозрачна вообще. В этом случае теоретически все пиксели окна, покрытые кнопкой, в результате должны быть лишь смесью половины рабочего стола и половины кнопки, но в момент рисования кнопки эти пиксели уже «загрязнены» окном. Математически это выглядит так:
C = Cdt*(1 — Aw) + Cw * Aw;
Cw = Cw * (1 — Ab) + Cb * Ab;
C = Cdt*(1 — Aw) + (Cw * (1 — Ab) + Cb * Ab)* Aw;
Если Ab = 1 и Aw = 0.5, то
C = 0.5 * Cdt + 0.5 * Cb;
C — цвет результата, Cdt, Cw, Cb, Aw, Ab — цвета и альфа элементов (dt — desktop, w — window, b — button).
Как можно решить эту проблему? Трудность заключается в том, что мы можем лишь корректно нарисовать один полупрозрачный элемент поверх статичной картинки, но на момент отрисовки конкретного элемента его цвет зависит не только от него самого, но и от его детей. Предлагаю читателям подумать над решением, перед тем как читать следующий абзац.
А что если мы полностью где-то отрисуем элемент до того, как врисовывать его в родителя? Но для этого надо иметь отрисованные дочерние элементы, а они, в свою очередь, должны знать своих детей и т. д. В этом случае сначала отрисуются элементы, лежащие в вершинах дерева иерархии, потом — их родители, а в самом конце — на рабочем столе появятся готовые отрендеренные окна. Куда же надо их рендерить? А что, если каждому элементу иметь свою текстуру такого же размера, как и он сам? Тогда задачей рисования элемента будет только рендер самого себя и отрисовка дочерних элементов. Именно поэтому из графического контекста пропало свойство отступа — оно не требуется, все элементы теперь рисуют исключительно в свою текстуру в своей же системе координат. Давайте взглянем на код!
Осталось запустить приложение!
И убедиться, что всё работает корректно. Конечно, можно заметить, что всё работает очень медленно, но это не удивительно: мы рисуем пиксель за пикселем, не используя ни возможности быстрого копирования в памяти, ни аппаратное ускорение. Скорость алгоритмов не была целью. Главное — найти чистые алгоритмы путём анализа, и мы с этим справились.
Напоследок сделам минимальную оптимизацию: не надо перерисовывать элементы при каждом цикле рендера, особенно, если учитывать, что в данный момент все они — лишь залитые прямоугольники. Для этого у элемента вводим свойство needsRedraw, которое и будет индикатором того, что его текстуру следует перерисовать. Это свойство должно выставляться в true при каждом изменении свойств, влияющих на внешний вид элемента. Более того, это должно происходить не только с самим элементом, но и со всеми его родителями, так как их текстуры зависят от внешнего вида всех дочерних элементов.
Если вы начинающий программист, пожалуйста, напишите в комментариях, была ли вам полезна эта статья и интересна ли тема алгоритмизации и поиска решений.
Универсальный GUI
Здравствуйте! Меня зовут Халитов Кирилл, я аспирант из МГУДТ (Московский государственный университет дизайна и технологии (МГУДТ) ). В моей диссертации возникла задача упростить процесс создания интерфейса для локального и веб-приложения и в итоге получился сабж.
Введение
В настоящее время любая современная мониторинговая система включает в себя прикладное программное обеспечение (ПО) для визуализации данных. Как правило, запуск этого ПО предполагает наличие рекомендуемой операционной системы (ОС), в большинстве своих случаев ОС компании Microsoft. Однако сейчас наблюдается тенденция использования кроссплатформенных средств для разработки ПО. В результате этого появляется возможность запуска готового программного продукта на разных ОС, включая и мобильные ОС.
Кроме того, в связи с бурным распространением интернета популярным направлением разработки ПО стала разработка веб-приложений или веб-сервисов. Веб-приложение является полезным дополнением к клиентской прикладной программе (приложению). Обычно веб-приложение даёт возможность удалённого использования мониторинговой системы. Это означает, что пользователь не привязан к месту расположения аппаратной части мониторинговой системы и может использовать её из любой точки мира, где есть рекомендуемое интернет-соединение. Важно заметить, что разработка веб-приложений в значительной степени отличается от разработки клиентских приложений и это в свою очередь создаёт некоторые проблемы. В частности, это проблема создания универсального графического интерфейса пользователя (GUI). Чтобы клиентское приложение и веб-приложение были реализованы в едином графическом стиле, необходимо приложить достаточно усилий как разработчику интерфейса клиентского приложения, так и разработчику интерфейса веб-приложения. В конечном счёте величина усилий одного или другого разработчика будет зависеть от того, интерфейс какого приложения будет задавать общий стиль.
Современные способы построения интерфейсов
Рассмотрим наиболее популярные в настоящий момент способы построения интерфейсов клиентских приложений на языке 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. Можно ли запатентовать этот способ, чтобы на защите было чем козырнуть кроме свидетельства о регистрации ПО?
Как создать GUI на чистом C?
Освоил язык С в той мере, в которой предлагает мой IT-ВУЗ, считаю, что понимаю его вполне неплохо.
В связи с этим возникает желание можернизировать некоторые свои программы, добавив в них GUI.
В интернетах очень мало советов по этому поводу, поэтому и написал сюда:
может кто-нибудь писал программы на С с качественным графическим интерфейсом и как это делается?
- Вопрос задан более трёх лет назад
- 31520 просмотров
2 комментария
Оценить 2 комментария

Есть успехи?
nadom @nadom Автор вопроса
Решения вопроса 3
Знаю JS, PHP, C++, C#
Ещё есть visual c++ (на дотнете основан, можно юзать Windows Forms или Windows Presentation Foundation), который отлично стыкуется с обычным c++ через #pragma managed и #pragma unmanaged
Ответ написан более трёх лет назад
AlexP11223 @AlexP11223
@KOLANICH Visual C++ не основан ни на каком дотнете, это обычный компилятор С/С++. На дотнете C++/CLI (но его не стоит использовать, лучше уж C# тогда).
спасибо, действительно, язык называется c++/cli. Шарп — хорошая штука, но с native c++ плохо и неудобно стыкуется.
OpenGL лучше всего в данном случае подойдет.
Ну или библиотечку какую-нибудь использовать вроде lesstif.
Ответ написан более трёх лет назад
Комментировать
Нравится Комментировать
На голом си не так уж много GUI библиотек. Пожалуй самая навороченная из кросс-платформенных, свободных это Gtk++.
Ну если вам только под винду то можно конечно взять WinAPI, хотя имхо это самый проигрышный вариант.
Ответ написан более трёх лет назад
Комментировать
Нравится Комментировать
Ответы на вопрос 4
Full-stack developer (Symfony, Angular)
Берете Qt, осваиваете C++ а на сях пишите только библиотеки.
p.s. сишные программы должны быть только под консоль, ибо это тру.
Ответ написан более трёх лет назад
Нравится 6 2 комментария
nadom @nadom Автор вопроса
почему под консоль?
@nadom потому что тру?
PostgreSQL DBA
Раскуриваете API той графической оболочки, под которую пишете, и создаёте гуй.
На сколько помню свои эксперименты десятилетней давности — одно только создание пустого окна на WinAPI — порядка 200 строк кода.
Ответ написан более трёх лет назад
Нравится 3 2 комментария
Да ладно, двухсот строк.
#include long CALLBACK wndproc(HWND hwnd,ui msg,ui wp,long lp) < return DefWindowProc(hwnd,msg,wp,lp); >int main()
@jcmvbkbc , тогда прошу прощения. Наверное, там было или не пустое окно, а хоть с чем-то управляющим или странный бредокод (что более вероятно для в те времена школьника).
Не сохранилось и с тех пор с программированием под win не сталкивался.
Push Pull @deadbyelpy
Интересно что значит с «качественным», полагаю что «хорошесть» интерфейса — его удобство, а если вы про удобную разработку, так хм, ну как придется.
есть iUP,GTK+, и еще другие, вам нужна кроссплатформенность?, а рисовать вы желаете системные контролы — доки по этому есть, или собственные? — копайте Qt например, там свои контролы рисуются.
Ответ написан более трёх лет назад
Комментировать
Нравится 3 Комментировать
Важно определиться под какую платформу.
Если винда то можно использовать Visual Studio и Windows Forms.
Правда надо будет хорошо знать WinAPI, тк VS рассчитан на работу с с++.
И многие вещи придется делать руками. Окошко с кнопочками в VS создается без проблем, а вот с подключением к ним событий намучаетесь.Тк язык си может лишь иммитировать ооп, а как это делать это отдельная сложная тема.
Можно использовать Qt Creator. Он тоже представляет возможности создать gui. Но эта ide тоже заточена под с++ и ООП парадигму. Хотя писать в ней на си можно и прилажухи с gui, но с костылями.
Сейчас для создания gui на чистом си используют визуальный дизайнер интерфейсов Glade gtk. Он сам целиком и полностью написан на си. В нём используется библиотка виджетов GTK+ которая тоже написана на чистом си.
Проект поддерживается GNOME Foundation.
Описание визуально создаваемого разработчиком интерфейса сохраняется в файлах формата XML, которые затем могут быть подключены к программам во время исполнения с использованием объекта GtkBuilder.
Для работы с си использую Code Blocks IDE, она у меня установлена и в винде и в линуксе.
При создании проекта к нему подключается библиотека GTK+ и файл xml c описанием виджетов созданных в Glade.