В прошлой статье кратко описан состав библиотеки и показан пример добавления в библиотеку контроллера ЖК HX8352, «сегодня» будем строить интерфейсы в QtDesigner и использовать их совместно с библиотекой NGL. Почему QtDesigner? Ну потому что это мощный, универсальный и легко расширяемый инструмент.
Итак, первое что нам понадобится это установленный Python 3 и Qt5.4.1, установка под Windows (под Linux все в принципе аналогично) займет несколько этапов, но мы ведь не боимся трудностей :)
Установка Python, Qt
С установкой Python 3 все просто:
А вот на втором пункте нужно сделать замечание, если устанавливать версию Qt выше 5.4.1 то при сборке PyQt у нас ничего не выйдет из-за изменений в лицензии Qt, придется собирать из исходников и Qt, в случае же 5.4.1 можно просто скачать офф. релиз и установить его, какой путь выбрать решать вам, мне было проще использовать 5.4.1 и пропустить этот шаг.
Path
Перед сборкой необходимо прописать в Path две переменные:
C:\Qt\Qt5.4.1\5.4\mingw491_32\bin\
C:\Qt\Qt5.4.1\Tools\mingw491_32\bin\
Перезагружаемся.
Сборка SIP
Качаем исходники SIP - https://www.riverbankcomputing.com/software/sip/download , распаковываем, в терминале набираем:
python configure.py –platform win32-g++
и затем:
mingw32-make install
Сборка PyQt5
Аналогично, качаем исходники PyQt5.4.1, распаковываем, в консоли набираем:
python configure.py --spec win32-g++
Соглашаемся с лицензией:
Далее набираем:
mingw32-make install
И идем пить чай пока все не соберется :)
Установка ngl utils
Это последний шаг нашего вооружения инструментарием :) , тут все просто, в консоли:
pip install ngl_utils
Или качаем последние исходники с GitHub, распаковываем и:
python setup.py install
На этом все, инструментарий готов!
Cначала пройдемся по ngl utils и посмотрим чего там есть, а есть там несколько утилит:
ngluic - утилита конвертации файлов ui из QtDesigner, это наш основной инструмент.
ngldes - скрипт запуска QtDesigner с плагинами из пакета ngl utils
nglfcn - конвертер шрифтов, позволяет конвертировать любой системный шрифт в исходники понятные NGL.
nglfed - редактор шрифтов NGL, открывает сгенерированные утилитами ngluic и nglfcn СИ файлы, можно отредактировать любой символ/символы шрифта.
Ну вот теперь можем приступит строить дизайны :), запускаем QtDesigner, в консоли (можно и ярлыком сделать при желании) :
ngldes
После запуска QtDesigner видим плагины NGL, на даный момент это:
- NGL_Button
- NGL_Bitmap
- NGL_CheckBox
- NGL_FillBar
- NGL_GraphScale
- NGL_Label
- NGL_Line
- NGL_Rect
- NGL_SeekBar
Этот список легко расширить добавив свои виджеты, но это пока мы отложим на закуску, как и краткое описание уже имеющихся.
Не буду останавливаться на самом процессе работы в QtDesigner, в сети полно инструкций, видео, и т. п., Раставляем виджеты, редактируем, при желании используем Layout и компоновку, все просто (: . Вот как у нас будет выглядеть тестовый дизайн - ui file:
Интерефейс готов, сохраняем и из этой папки набраем:
ngluic -u test.ui --verbose
(полный список ключей доступен по ngluic -h или ngluic --help)
После окончания работы конвертера в папке должна появится следующая структура подпапок и файлов:
code
bitmaps
файлы сгенерированных шрифтов
fonts.h
fonts
файлы сгенерированных изображений
bitmaps.h
pages
mainpage
mainpage.c
заголовочные файлы объектов
pages.h
Можно вручную задать куда ложить сгенерированный код указав это параметром -d, например:
ngluic -u test.ui -d C://projects//ngl_test//ngl//outcode --verbose
Параметр --bmp-cmprs [ NONE, RLE, JPG, AUTO ] отвечает за то в каком формате будут сгенерированные изображения из ресурсов проекта QtDesigner, сжатие RLE может быть эффективней на небольших и малотоновых изображениях по сравнению с JPG, на больших конечно же предпочтительней использовать сжатие JPG. Для автоматического выбора метода сжатия под оптимальный размер достаточно указать --bmp-cmprs AUTO, в этом случае утилита сама определит как сжимать то или иное изображение исходя из оптимального размера. К слову метод сжатия RLE используется несколько модифицированный по сравнению с "классикой" - wiki, кодируются не только серии повторяющихся объектов, но и серии не повторяющихся, это дает в некоторых случаях большее сжатие за счет уменьшения дополнительной информации в закодированном изображении, в худшем сравнивается по эффективности с "классикой". Использовать RLE можно и отдельно в своих программах на python, просто имопртировав ngl_utils.rle, например:
from ngl_utils.rle import rlem_encode, rlem_decode
Кодировать можно не только списки байт/слов/текста но и любых других списков произвольных объектов.
Для сжатия JPG используется инструментарий Qt, дополнительный ключ --bmp-jpg 50 установит качество 50. Ключ --verbose "заставит" утилиту выдавать больше информации о ходе конвертации, там же будет и отчет по каждому изображению и чем оно сжато.
Теперь разберемся что нам нагенерировала утилита и как это использовать, структуру папок и файлов уже видели, посмотрим на mainpage.c.
/**
******************************************************************************
* @file MainPage.c
* @author Neil Lab :: Left Radio
* @version v1.0.0
* @date 2015-11-27 19:09:01.983739
* @brief NGL Page MainPage sourse
******************************************************************************
**/
/* Includes ------------------------------------------------------------------*/
#include "NGL.h"
#include "fonts.h"
#include "bitmaps.h"
#include "mainpage_labels.h"
#include "mainpage_graphscales.h"
#include "mainpage_buttons.h"
#include "mainpage_seekbars.h"
#include "mainpage_fillbars.h"
/* Private typedef -----------------------------------------------------------*/
/* Private define ------------------------------------------------------------*/
/* Private macro -------------------------------------------------------------*/
/* Extern functions ----------------------------------------------------------*/
/* Private function prototypes -----------------------------------------------*/
static void MainPage_Draw(void);
static void MainPage_Click(Coordinate data, NGL_TouchType type);
/* Private variables ---------------------------------------------------------*/
NGL_Page MainPage = {
{ 0, 0, 480, 320 }, // [X0, Y0, X1, Y1]
0, // ID
0x18c3, // BackColor
TRUE, // Exit allowed
/* Objects pointers array (Buttons, Labels, FillBars, etc.) */
{
mainpage_buttons, 4,
mainpage_labels, 19,
mainpage_fillbars, 8,
mainpage_seekbars, 1,
mainpage_graphscales, 2,
},
MainPage_Draw, // Page draw function
MainPage_Click, // Page click (or index change) function
};
/* Private functions ---------------------------------------------------------*/
/**
* @brief MainPage_Draw
* Draw page objects function
* @param None
* @retval None
*/
static void MainPage_Draw(void)
{
/* Clear all screen */
NGL_LCD_Clear_AllScreen(0x18c3);
/* Draw all static graphics primitive, labels, etc. */
NGL_GP_DrawFillRect(5, 6, 119, 26, 0x83, DRAW, 0x83);
NGL_Font_DrawString(20, 9, 0xf904, (NGL_Font*)&ms_shell_dlg_2_8_normal, Transparent, "NeilLab :: leftradio");
NGL_Font_DrawString(60, 22, 0xe79f, (NGL_Font*)&ms_shell_dlg_2_9_normal, Transparent, "v 1.5.2");
NGL_Font_DrawString(12, 21, 0xe79f, (NGL_Font*)&ms_shell_dlg_2_12_normal, Transparent, "NT11");
NGL_Font_DrawString(5, 253, 0xffff, (NGL_Font*)&ms_shell_dlg_2_8_normal, Transparent, "Lf:");
NGL_Font_DrawString(5, 241, 0xffff, (NGL_Font*)&ms_shell_dlg_2_8_normal, Transparent, "Rf:");
NGL_GP_DrawFillRect(5, 295, 475, 315, 0x106, DRAW, 0x106);
NGL_Font_DrawString(5, 227, 0xffff, (NGL_Font*)&ms_shell_dlg_2_8_normal, Transparent, "Lf:");
NGL_Font_DrawString(5, 215, 0xffff, (NGL_Font*)&ms_shell_dlg_2_8_normal, Transparent, "Rf:");
NGL_Font_DrawString(5, 200, 0xffff, (NGL_Font*)&ms_shell_dlg_2_8_normal, Transparent, "Lf:");
NGL_Font_DrawString(5, 188, 0xffff, (NGL_Font*)&ms_shell_dlg_2_8_normal, Transparent, "Rf:");
NGL_Font_DrawString(5, 172, 0xffff, (NGL_Font*)&ms_shell_dlg_2_8_normal, Transparent, "Lf:");
NGL_Font_DrawString(5, 160, 0xffff, (NGL_Font*)&ms_shell_dlg_2_8_normal, Transparent, "Rf:");
NGL_GP_DrawLine(415, 279, 415, 54, 0xc000);
NGL_GP_DrawLine(5, 44, 475, 44, 0xc000);
NGL_Font_DrawString(415, 307, 0xf79f, (NGL_Font*)&ms_shell_dlg_2_8_normal, Transparent, "Channels");
NGL_Font_DrawString(235, 307, 0xf79f, (NGL_Font*)&ms_shell_dlg_2_8_normal, Transparent, "Frequency");
NGL_Font_DrawString(355, 307, 0xf79f, (NGL_Font*)&ms_shell_dlg_2_8_normal, Transparent, "Bits");
/* Draw objects */
NGL_GUI_DrawPageObjects();
}
/**
* @brief MainPage_Click
* Common click page objects
* @param None
* @retval None
*/
static void MainPage_Click(Coordinate data, NGL_TouchType type)
{
}
/**
* @brief btnControls_click
* Item/Items click event
* @param None
* @retval None
*/
static void btnControls_click(void)
{
}
/**
* @brief btnVisual_click
* Item/Items click event
* @param None
* @retval None
*/
static void btnVisual_click(void)
{
}
/**
* @brief btnSettings_click
* Item/Items click event
* @param None
* @retval None
*/
static void btnSettings_click(void)
{
}
/**
* @brief btnSourse_click
* Item/Items click event
* @param None
* @retval None
*/
static void btnSourse_click(void)
{
}
/**
* @brief nglSeekBar_2_click
* Item/Items click event
* @param None
* @retval None
*/
static void nglSeekBar_2_click(void)
{
}
/*********************************************************************************************************
END FILE
*********************************************************************************************************/
Как видно объявляется структура страницы с параметрами в полях, заготовки событий. в функции MainPage_Draw происходит отрисовка статичных элементов и "динамики" типа кнопки, прогрессбар и т.п. через вызов NGL_GUI_DrawPageObjects(), для того что бы это работало нужно сперва установить "активную" страницу вызвав NGL_GUI_SelectPage и передав в нее указатель на страницу, то есть отрисовка любой страницы должна иметь подобный вид:
/* Draw MainPage */
NGL_GUI_SelectPage(&MainPage);
NGL_GUI_GetSelectedPage()->Draw();
На данный момент NGL поддерживает только тачскрин, далее мы эти воспользуемся в качестве примера использования событий. В остальных сгенерированных файлах находятся структуры шрифтов, изображений и т.п. Объявление типов этих структур можно посмотреть в NGL_types.h.
Для проверки я буду использовать CoocoxIDE и МК STM32F407, а также 480х320 ЖК на контроллере R61581, МК и ЖК соеденены по FSMC 16 бит. Создадим пустой проект в Coocox IDE и добавляем все сгенерированные файлы в проект, также подключим библиотеку NGL.a и файлы NGL.h / NGL_types.h.
Компилируем и запускаем, если все сделано правильно то должны увидить следующее:
Основное место на flash занимают изображения и шрифты, сама по себе библиотека вполне компактна. Также размер увеличивает зависимость от стандартной библиотеки С, этот "недостаток" планировал исправить в следующем коммите NGL. Для примера с отрисовкой только "статических" "объектов" (линии, надписи и т.д.) и одного шрифта ms_shell_dlg_2_8 прошивка занимает:
text |
data |
bss |
9508 |
204 |
2140 |
Прошу извинить за качество фото :( , заливка всего экрана (очистка) и отрисовка интерфейса заняла 17149 мкс, или ~17 мс, весьма шустро, ~ 50 кадров/сек.
На сим пока все, спасибо всем за внимание, сожалею правда что так кратко. Продолжение следует...
print( [ln.format() + '\n' for ln in links] )
|
|