реклама на сайте
подробности

 
 
4 страниц V   1 2 3 > »   
Reply to this topicStart new topic
> Embedded GUI, Что поизучать?
haker_fox
сообщение Sep 7 2012, 06:45
Сообщение #1


Познающий...
******

Группа: Свой
Сообщений: 2 963
Регистрация: 1-09-05
Из: г. Иркутск
Пользователь №: 8 125



Добрый день, коллеги!

Посоветуйте, пожалуйста, что можно почитать по принципу создания, проектирования GUI?

Возник соблазн написать что-то свое. На Си++.

Требования к интерфейсу: работа на ARM7+, где-то (с усечениями) на AVR8, разрешение от 128x64 до 1024x768, от монохрома до 8-8-8. Как-то так. Высокая сложность не требуется, хотя я расчитываю, что с Си++ сложность нарастить будет не сложно)))

Знаю, что есть готовые системы. Но хочу поупражнятся сам.

Спасибо!


--------------------
Выбор.
Go to the top of the page
 
+Quote Post
Lotor
сообщение Sep 7 2012, 08:19
Сообщение #2


Местный
***

Группа: Свой
Сообщений: 476
Регистрация: 3-07-07
Из: Санкт-Петербург
Пользователь №: 28 866



Тоже для общего развития хотелось бы почитать какую-нибудь литературу по организации собственного gui на ООП. Наверняка до винды людей волновал этот вопрос и была литература соответствующая. Самое лучшее, что нагуглилось - IMGUI. Может кто из форумчан знает книги по теме?

PS: я в курсе, что самое правильное - взять готовую отлаженную библиотеку. sm.gif


--------------------
Ковырял чукча отверткой в ухе, звук в телевизоре и пропал.
Go to the top of the page
 
+Quote Post
haker_fox
сообщение Sep 7 2012, 10:49
Сообщение #3


Познающий...
******

Группа: Свой
Сообщений: 2 963
Регистрация: 1-09-05
Из: г. Иркутск
Пользователь №: 8 125



QUOTE (Lotor @ Sep 7 2012, 17:19) *
PS: я в курсе, что самое правильное - взять готовую отлаженную библиотеку. sm.gif

Ну для кого же правильное? Вот для нас с Вами похоже уже не совсем правильное.

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


--------------------
Выбор.
Go to the top of the page
 
+Quote Post
Lotor
сообщение Sep 7 2012, 11:14
Сообщение #4


Местный
***

Группа: Свой
Сообщений: 476
Регистрация: 3-07-07
Из: Санкт-Петербург
Пользователь №: 28 866



Цитата(haker_fox @ Sep 7 2012, 14:49) *
Готовое - это уже чужая идеология. Хочется свою попробывать. Хотя да, можно начинать с изучения чужой идеологии по исходникам и документации. Но лучше бы почитать теорию, каковая должна иметься)

Готовое - это в первую очередь отлаженная протестированная идеология. sm.gif
Свой gui есть в моих девайсах, но хочется именно что-то почитать по теме для расширения кругозора.

PS: Если нужен аккуратный оконный графический интерфейс со всякими сглаживаниями, то имхо писать свой велосипед слишком накладно.


--------------------
Ковырял чукча отверткой в ухе, звук в телевизоре и пропал.
Go to the top of the page
 
+Quote Post
kolobok0
сообщение Sep 7 2012, 19:40
Сообщение #5


практикующий тех. волшебник
*****

Группа: Участник
Сообщений: 1 190
Регистрация: 9-09-05
Пользователь №: 8 417



Цитата(haker_fox @ Sep 7 2012, 10:45) *
...что можно почитать по принципу создания, проектирования GUI?...


Тут такое дело.
Если смотреть на форточки, то прослеживается два уровня.
1) апи ядра, уходящее корнями в железо, ускорители и прочую лабуду.
2) юзерс интерфейс, с попыткой вычленить сущности удобные для повтоного юзанья.

если брать это за основу, то по первому можно почитать книги включающие в себя справочные данные (чуть ли не МСДН перепечатанный). основные тезисы - быстрая передача в(из) ядро оси, задействование по максимуму железо.

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

Это если про стандартный гуи. игры - отдельно обычно. там ниже уровень и плотнее с железом.

где то так.
смотря, что нужно. и наверное задача. вряд-ли вас преследует идея универсализма и стандартизации для стороннего разработчика sm.gif
Go to the top of the page
 
+Quote Post
Lotor
сообщение Sep 7 2012, 20:17
Сообщение #6


Местный
***

Группа: Свой
Сообщений: 476
Регистрация: 3-07-07
Из: Санкт-Петербург
Пользователь №: 28 866



Цитата(kolobok0 @ Sep 7 2012, 23:40) *
Если смотреть на форточки, то прослеживается два уровня.

Вы, конечно, всё правильно говорите, но зачем рассматривать подход в форточках для embedded? Если и брать за ориентир готовую библиотеку для изучения, то лучше тот же Micrium µC/GUI, а не QT или MFC.

PS: Кстати крайне удобная штука у Micriumа - возможность нарисовать/прикинуть гуй на ПК.


--------------------
Ковырял чукча отверткой в ухе, звук в телевизоре и пропал.
Go to the top of the page
 
+Quote Post
_Pasha
сообщение Sep 8 2012, 02:35
Сообщение #7


;
******

Группа: Участник
Сообщений: 5 646
Регистрация: 1-08-07
Пользователь №: 29 509



FTK
Go to the top of the page
 
+Quote Post
dxp
сообщение Sep 8 2012, 04:29
Сообщение #8


Adept
******

Группа: Свой
Сообщений: 3 469
Регистрация: 6-12-04
Из: Novosibirsk
Пользователь №: 1 343



QUOTE (haker_fox @ Sep 7 2012, 17:49) *
Готовое - это уже чужая идеология. Хочется свою попробывать. Хотя да, можно начинать с изучения чужой идеологии по исходникам и документации. Но лучше бы почитать теорию, каковая должна иметься)

Готовой теории не найдёте, поэтому не тратьте время на это. Начните делать что-то сами - только в процессе делания и придёт понимание и осознание. Посмотреть, как сделано в других системах - полезно. Но именно посмотреть, как сделано то или иное. GUI в каждом случае индивидуален. Тот, что идёт на РС, обычно плохо подходит для embedded систем. Поэтому целиком его оттуда заимствовать достаточно плохая идея. Если взять какой-то готовый типа uCGUI, то придётся оставаться в рамках его идеологии. Не всегда она может хорошо подойти для вашего устройства.

Разработать GUI "по месту" не такая сложная задача (много сложнее разработать универсальный GUI, чтобы он хорошо подходил под разные устройства). Начните с самых основ. В этом деле есть, так сказать, "три кита":

  1. Обработка/обслуживание ввода. Это обработка сигналов от органов управления - кнопки, энкодеры и т.п.
  2. Виджеты и их иерархия. Вся совокупность элементов графического интерфейса, их взаимосвязь и отображение.
  3. Вывод. Связь с дисплеем через HAL (набор функций/объектов для управления устройством визуализации и передачи на него видеоинформации).

Первый и третий пункты достаточно ординарны, тут не требуются какие специальные познания в организации этих частей. Собственно графическая часть GUI - виджеты - могут организовываться по различным схемам - тут на вкус и цвет, как говорится. Если хотите реализовывать на С++, то безусловно нужно заюзать ООП: выстроить иерархию классов-виджетов. Я делал два разных GUI для разных устройств, внешне они совершенно не похожи, и виджеты (их набор и реализация) тоже очень отличаются. Но принципы там одни и те же, и приёмы программирования тоже очень сходны. Позволю себе дать несколько советов по построению такой иерархии (в контексте С++, ессно sm.gif).

Первое, о чём стоит подумать при построении иерархии виджетов, - это то, как они будут получать информацию от устройств ввода. Т.е. как будет построен механизм обработки сигналов управления и отображение реакции в виде изменения набора и состояния виджетов на экране дисплея. Ведь виджетов может быть очень много и нужно как-то упорядочить механизм передачи им информации, по которой они должны реагировать. Одним из простых и эффективных способов для этого является создание специального служебного объекта, который будет держать фокус на виджете - именно этот виджет "под фокусом" и будет получать информацию от устройств ввода. Этот вариант позволяет легко организовать переходы по цепочке виджетов и обратно - для этого достаточно будет создать очередь объектов "фокус". Тип этого объекта "фокус" должен быть типом базового класса виджета, чтобы можно было его "сфокусировать" на любой объект виждета.

Самая база содержит абстрактный класс и базовый класс виджета типа такого:
CODE
namespace gui
{
    //--------------------------------------------------------------------------
    //
    //     Main object types hierarchy
    //
    class TObject
    {
    public:
        virtual void on_message(TBaseMsgWrapper *msg_wrp) = 0;

    };
    //--------------------------------------------------------------------------
    class TWidget : public TObject
    {
    public:
        TWidget() : Pos(), Visible(true), Selected(false) { }
        TWidget(TPoint pos, bool visible = true) : Pos(pos), Visible(visible), Selected(false) { }
        
        virtual void on_message(TBaseMsgWrapper *msg_wrp);
        
        virtual void draw()      { }

        // keys
        virtual void enter()     { }
        virtual void back()      { }
        virtual void help()      { }

        // encoder
        virtual void next()      { }
        virtual void prev()      { }
      
        void   set_pos(const TPoint pos)     { Pos = pos;  }
        void   set_pos(const int_fast16_t x,
                       const int_fast16_t y) { Pos.x = x; Pos.y = y;  }

        TPoint pos    () const               { return Pos; }
    
        void set_visible(bool x) { Visible = x;    }
        bool visible    () const { return Visible; }
          
        void set_selected(bool x) { Selected = x;    }
        bool selected() const     { return Selected; }
        
    protected:
        TPoint Pos;
        bool   Visible;
        bool   Selected;
    };

    ... //
}


Очень важная фукнция on_message() - именно она является каналом передачи информации от органов управления и других частей программы (например, приходит сообщение по UART'у с требованием что-то сделать). Поскольку у каждого объекта GUI есть такая фукнция, то он может реагировать соответствующим образом. Подробно тут останавливаться на реализации этой функции не буду, это можно обсудить отдельно, если есть интерес.

Далее, класс TWidget являет собой базу для любого виджета в данном системе - меню, пункты меню, скроллбары, диалоговые окна сообщений и т.п.. Он содержит минимальный набор данных - позиция, и два свойства: видимый или нет и выделенный или нет. Понятно, что в другой системе свойства могут быть другими - вместо этих будут что-то своё. Ну, и интерфейс для работы этим представлением. TPoint - это простая структура, реализующая функционал объекта "точка на экране", содержащая координаты и функции для работы с ними, там всё тривиально. Набор виртуальных функций важен. Функция draw() нужна всегда - это отрисовка виджета, она всегда индивидуальна. Остальные функции завязаны на целевое устройство. В данном случае у нас есть несколько кнопок и энкодер. Реакция каждого виджета на органы управления тоже, понятное дело, индивидуальна, поэтому эти функции у каждого виджета свои.

Для создания любого виджета, ясно, нужно отнаследоваться от TWidget, расширить определение и добавить функциональность, в том числе переопределив методы (виртуальные функции). Рассказывать подробнее тут смысла нет - надо пробовать, понимание, если его ещё нет, придёт сразу.

Обработка ввода и управление GUI выглядит в данном примере выглядит примерно так. Есть главный цикл GUI, в котором и осуществляется вся динамика этого процесса:
CODE
    ... //
    for(;;)
    {
        Input.handle();
        timer();
        sleep(40);
        
    }

В данном примере цикл работы движка GUI составляет 40 мс + время работы собственно движка. Input - это объект, который отвечает за обработку органов управления (кнопки, энкодер), timer - функция, которая генерирует сообщения о временных отметках - некоторые виджеты требуют таких сообщений, чтобы отрабатывать свой функционал - например, часы или таймер, которые отображают изменяющееся время на экране. Сюда можно добавить ещё подобных элементов, чтобы расширить функциональность - например, как уже говорилось выше, передавать информацию, поступающую по последовательному порту от другого устройства, данные от АЦП и т.д.

Передача собственно информации осуществляется с помощью передачи сообщения объекту под фокусом. Выше есть объявление:
CODE
TWidget                      *Focus;
stack<gui::TWidget *, 8>      FocusHistory;

Здесь есть указатель на виджет и групповой объект (на 8 элементов), для хранения фокусов.

Передача информации осуществляется следующим образом. Когда, например, сигналы от органов управления обработаны и есть информация о том, что та или иная кнопка нажата/отжата/удерживается или был осуществлён поворот энкодера, формируется тело сообщения и посылается объекту под фокусом:
CODE
    ... //  опрос кнопок и формирование результата опроса: KeyPattern описывает какие кнопки были нажаты,
    ... //   KeyEventKind - тип события - нажато/отпущено/удерживается

    if(  ( KeyPattern == ENTER && KeyEventKind == TKeyEvent::PRESSED ) ) // кнопка Enter нажата
    {
        TInputMessage Msg = gui::imENTER;             // тело сообщения, в данном случае простой объект перечислимого типа
        send_message<gui::TInputMessage>(&Msg, Focus); // передача сообщения текущему виджету
    }
    
    if( KeyPattern == BACK && KeyEventKind == TKeyEvent::PRESSED )
    {
        TInputMessage Msg = gui::imBACK;
        send_message<gui::TInputMessage>(&Msg, Focus);
    }
    ... //

Аналогично обрабатываются остальные органы управления и передаются соответствующие сообщения. Приём сообщения выглядит так:
CODE
void gui::TWidget::on_message(TBaseMsgWrapper *msg_wrp)
{
    gui::TInputMessage *msg = check_msg<gui::TInputMessage>(msg_wrp);   // проверяется соответствие типа сообщения, 0 возвращает, если не соответствует
    
    if(msg)
    {
        switch(*msg)
        {
        case gui::imENTER : enter(); break;
        case gui::imBACK  : back();  break;
        case gui::imHELP  : help();  break;
        case gui::imNEXT  : next();  break;
        case gui::imPREV  : prev();  break;
        default           : print("error: unknown message");
        }
    }
}

Здесь проверяется соответствие типа сообщения - если не соответствует, то сообщение игнорируется. Если соответствует, что в соответствии с телом сообщения вызывается соответствующий метод виджета под фокусом. Таким образом, управление всеми виджетами осуществляется единообразно и централизовано (что устраняет проблему совместного доступа) достаточно простым способом. В данном примере показана обработка сообщения базовым классом виджетов - такое поведение будет у всех виджетов по умолчанию. Если нужно для какого-то виджета обрабатывать сообщение как-то иначе, чем в этом примере, то достаточно для этого виджета переопределить функцию on_message(). Т.е. такая схема не фиксирует реакцию виджета на сообщение: есть общее для всех поведение по умолчанию (и оно подходит для подавляющего большинства виджетов), но в отдельных случаях можно без труда, и ничего не сломав, расширить функционал отдельных виджетов (и даже иерархий), где это необходимо. Необходимо помнить, что если сообщение в переопределённой функции не было обработано (перехвачено) то его нужно переправить дальше по цепочке, иначе другие сообщения не будут обрабатываться.

Может показаться, что идея с передачей сообщений несколько избыточна, ведь почему бы, например, сразу напрямую не вызывать соответствующий метод для виджета под фокусом. На самом деле смысл есть: такое построение "развязывает" модуль генерации событий (сообщений) и их обработку, что позволяет легко расширить как перечень событий, так и логику их обработки, не привязываясь к конкретным виджетам. В частности, в данном примере показана передача разнокачественной информации (о событиях на кнопках и от таймера) единообразным способом. Такой подход позволяет легко расширить как перечень передаваемой информации, так и селективность её обработки разными виджетами. Накладные расходы тут минимальны.

Подобный принцип используется во многих GUI движках, в частности в Qt очень похожая схема с объектами событий (QEvent).

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

Если что-то не ясно, готов ответить на любые вопросы.

P.S. Хотел написать три строчки, пару общих советов, а получилось...


--------------------
«Отыщи всему начало, и ты многое поймёшь» К. Прутков
Go to the top of the page
 
+Quote Post
AlexandrY
сообщение Sep 8 2012, 08:13
Сообщение #9


Ally
******

Группа: Модераторы
Сообщений: 6 232
Регистрация: 19-01-05
Пользователь №: 2 050



Цитата(haker_fox @ Sep 7 2012, 09:45) *
Посоветуйте, пожалуйста, что можно почитать по принципу создания, проектирования GUI?
...
Возник соблазн написать что-то свое. На Си++.


Берите Microchip Graphics Library и все получите с избытком.

Microchip отличается очень компактным и простым кодом.
Очень ясный подход к взаимодействию экранных элементов.
Все централизовано и использует связный список объектов.
Сделать новый widget можно элементарно не вспоминая от кого он там должен наследоваться и какие методы надо переопределить.

Как раз будет работенка все усложнить и перевести ее на C++. wink.gif

Мощный оконный интерфейс с виртуальными окнами, масштабируемостью под любой экран, редактором ресурсов, TTF шрифтами и т.д. конечно не получите, как в uc/GUI , но будет точно то же, что предложил dxp biggrin.gif
Go to the top of the page
 
+Quote Post
Lotor
сообщение Sep 8 2012, 09:10
Сообщение #10


Местный
***

Группа: Свой
Сообщений: 476
Регистрация: 3-07-07
Из: Санкт-Петербург
Пользователь №: 28 866



Цитата(dxp @ Sep 8 2012, 08:29) *
P.S. Хотел написать три строчки, пару общих советов, а получилось...

Получился очередной шедевральный и полезный многим пост. sm.gif Спасибо!

PS: Жаль, что у движка форума нету возможности добавлять в избранное понравившееся темы или сообщения. И жаль, что нету FAQ, в котором подобные интересные сообщения собраны, а не теряются среди холиваров или флуда.


--------------------
Ковырял чукча отверткой в ухе, звук в телевизоре и пропал.
Go to the top of the page
 
+Quote Post
haker_fox
сообщение Sep 8 2012, 14:09
Сообщение #11


Познающий...
******

Группа: Свой
Сообщений: 2 963
Регистрация: 1-09-05
Из: г. Иркутск
Пользователь №: 8 125



В общем по-маленьку начал кропать свой ГУИ. Пока инетерс не угас))) Оглядываюсь на мэтров (uc/GUI, Microchip GUI и т.д.).

Осмысливаю рекомендации уважаемого dxp... тяжело мне пока во все вникнуть, но подход мне нравится!


--------------------
Выбор.
Go to the top of the page
 
+Quote Post
andrewlekar
сообщение Sep 10 2012, 04:55
Сообщение #12


Знающий
****

Группа: Участник
Сообщений: 837
Регистрация: 8-02-07
Пользователь №: 25 163



Цитата(dxp @ Sep 8 2012, 09:29) *
Разработать GUI "по месту" не такая сложная задача

Довольно-таки неплохо спроектированый GUI. Хорошая работа.
Go to the top of the page
 
+Quote Post
haker_fox
сообщение Sep 10 2012, 14:23
Сообщение #13


Познающий...
******

Группа: Свой
Сообщений: 2 963
Регистрация: 1-09-05
Из: г. Иркутск
Пользователь №: 8 125



QUOTE (dxp @ Sep 8 2012, 13:29) *
Подобный принцип используется во многих GUI движках, в частности в Qt очень похожая схема с объектами событий (QEvent).

Если что-то не ясно, готов ответить на любые вопросы.

Посольку работаю в контектсе scmRTOS, очень удобным кажется передавать такие события через объект OS::channel. Это правильно? rolleyes.gif


--------------------
Выбор.
Go to the top of the page
 
+Quote Post
dxp
сообщение Sep 10 2012, 15:43
Сообщение #14


Adept
******

Группа: Свой
Сообщений: 3 469
Регистрация: 6-12-04
Из: Novosibirsk
Пользователь №: 1 343



QUOTE (haker_fox @ Sep 10 2012, 21:23) *
Посольку работаю в контектсе scmRTOS, очень удобным кажется передавать такие события через объект OS::channel. Это правильно? rolleyes.gif

Если это вопрос о передаче информации объектам GUI, то нет, там используется иной механизм (могу рассказать подбробнее). А OS::channel можно использовать для передчи сообщений в главный цикл GUI из других процессов и обработчиков прерываний.


--------------------
«Отыщи всему начало, и ты многое поймёшь» К. Прутков
Go to the top of the page
 
+Quote Post
mdmitry
сообщение Sep 10 2012, 21:15
Сообщение #15


Начинающий профессионал
*****

Группа: Свой
Сообщений: 1 215
Регистрация: 25-10-06
Из: СПб
Пользователь №: 21 648



Цитата(dxp @ Sep 10 2012, 19:43) *
Если это вопрос о передаче информации объектам GUI, то нет, там используется иной механизм (могу рассказать подбробнее). А OS::channel можно использовать для передчи сообщений в главный цикл GUI из других процессов и обработчиков прерываний.

Весьма интересно узнать, какие идеи заложены в Вашем решении.


--------------------
Наука изощряет ум; ученье вострит память. Козьма Прутков
Go to the top of the page
 
+Quote Post

4 страниц V   1 2 3 > » 
Reply to this topicStart new topic
1 чел. читают эту тему (гостей: 1, скрытых пользователей: 0)
Пользователей: 0

 


RSS Текстовая версия Сейчас: 30th June 2025 - 08:43
Рейтинг@Mail.ru


Страница сгенерированна за 0.01529 секунд с 7
ELECTRONIX ©2004-2016