Софт и утилиты
Конструктор сайтов - uCoz
Приветствую Вас, Пробегающий мимо · RSS 21.07.2017, 10:42
Главная » Статьи » Утилиты » Графика

QtDesigner + NGL embedded, Widgets.

QtDesigner/NGL Widgets

    Итак хотелось бы рассмотреть виджеты которые доступны в python пакете ngl-utils и как с ними работать. Давайте посмотрим, запустим скрипт ngldes из пакета ngl-utils набрав в консоли

> ngldes

После запуска QtDesigner видим следующие виджеты:

  • NGL_Button
  • NGL_Bitmap
  • NGL_CheckBox
  • NGL_FillBar
  • NGL_GraphScale
  • NGL_Label
  • NGL_Line
  • NGL_Rect
  • NGL_SeekBar

 

NGL_Button

    В браузере свойств объекта видим 3 категории разделенные по родителям виджета - QObject, QWidget, NGL_Base, и непосредственно уникальные свойства NGL_Button. В QObject у нас только имя объекта, в QWidget координаты, размер, таблица стиля и т.п. Таблица стилей для NGL_Button определяет цвет фона кнопки и цвет текста, значение по умолчанию:

background-color: rgb(192, 0, 0);
color: rgb(64, 64, 64);

    В группе NGL_Base находятся общие свойства для всех виджетов NGL, свойство layer сейчас на стадии альфа, поэтому не обращаем на него внимания и не трогаем пока. Объекты будут отрисовыватся в порядке установленном в QtDesigner, то есть объекты добавленные на форму ранее будут слоем ниже добавленных позже, также нужно учесть что статические объекты будут отрисованны всегда ранее "динамических", порядок в каждой группе объектов определяется так как указано ранее. Свойсвто eventsEnabled определяет будет ли сгенерированно событие нажатия или другой активации виджета, если да то для объекта будет сгенерированна функция обработчик события в файле страницы к которой принадлежит объект, например:

static void btnControls_click(void)
{
}

    Также в объявлении структуры объекта будет проставлен указатель на эту функцию, связывающий объект и обработчик. Если же eventsEnabled выключено, то обработчик не будет сгенерирован, а в объекте указатель на обработчик будет равен указателю на ноль - (void*)0. Свойство clickEventName отвечает за имя функции обработчика события, таким образом можно связать несколько объектов с одним событием.
    Теперь рассмотрим группу свойств NGL_Button, уникальных для виджета NGL_Button. styleType, бывает 4 типов:

  • text  --  просто текст
  • fill  --  обычная, залитая фоном, прямоугольная кнопка
  • ico  --  кнопка иконка, больше ничего
  • ico_text -- иконка плюс текст 

    На скриншоте выше кнопка имеет тип fill, пример NGL_Button типа ico_text можно посмотреть здесь.
Свойство font отвечает за используемый шрифт, text - текст кнопки, text_sx/text_sy - эксперементальные, можно не обращать внимания. gradient отвечает за то как будет залита кнопка в режиме fill, если включено, то кнопка будет залита от цвета указанного в таблице стилей, до более светлого того же оттенка, если выключено, то кнопка будет просто залита одним цветом. icon - иконка кнопки, имеет значение только если кнопка типа ico или ico_text, iconSize - отвечает за размер иконки.

Структура кнопки в NGL:

/* NGL UI Button type */
typedef struct {
    const uint16_t X; // Left X coordinate
    const uint16_t Y; // Down Y coordinate
    const uint16_t Width; // Button width (X1 = X0 + Width)
    const uint16_t Height; // Button height (Y1 = Y0 + height)
    const NGL_ButtonType Type; // Type of button
     uint16_t Color; // Forecolor for "Fill" type
     uint16_t SelectedColor; // Forecolor selected button for "Fill" type
    const FunctionalState ColorShift; // Forecolor shift for "Fill" type
    const NGL_Image *ICO; // Icon/bitmap
    const NGL_Font *Font; // Font for text
    const int16_t TextOffset_X; // Text X offset
    const int16_t TextOffset_Y; // Text Y offset
     uint16_t TextColor; // Color for text
     char* Text; // Text
    const NGL_ReClickState ReClickState; // Enable or disable repeated clicks events
     FunctionalState Visible; // Visible state
     FlagStatus Enabled; // Enabled state, if RESET button not active and not request all clicks events
 
    const pEvent ClickEvent; // Click event function pointer
} NGL_Button;
 
 

NGL_Bitmap

    Это совсем простой виджет, кроме базовых свойств QObject/QWidget/NGL_Base у данного виджета есть только свойство ico - файл или ресурс изображения. Структура в NGL:

/* NGL Image type */
typedef struct {
    const uint16_t Width; // Picture Width
    const uint16_t Height; // Picture Height
    const uint8_t Compressed; // Copressed flag, 0 - NonCompressed, 1- RLE, 2 - picoJPG
    const uint8_t ColorBits; // color bit per pixel
    const uint8_t DataBits; // bitmap data array value bits
    const uint32_t DataArraySize; // Last index of bitmap data array
    const void *Data; // data pointer
} NGL_Image;
 
 

NGL_СheckBox

    Свойство checked отвечает за начально состояние checkbox-а, boxcolor - цвет прямоугольной области, цвет шрифта задается в таблице стилей, например на скриншоте задано - color: rgb(128, 0, 128);. text и font задают текст, и каким шрифтом он будет отрисован. Структура в NGL:

/* NGL UI CheckBox type */
typedef struct {
    const uint16_t X0, Y0, X1, Y1;
     FunctionalState Checked;
    const NGL_Font* Font;
    const char* Text;
     uint16_t Color;
     uint16_t TextColor;
    const pEvent ClickEvent;
} NGL_CheckBox;

 

NGL_FillBar

    NGL_FillBar может быть использован как индикация прогресса того или иного выполняемого действия, или для индикации значения различных параметров, например напряжения, давления, и т.п. Свойство level - уровень в относительных еденицах, не может быть больше максимума - maximum, и меньше минимума - minimum, то есть если level - 50, minimum - 0, maximum - 100, то виджет будет залит до своей геометрической середины по X или Y, в зависимости от ориентации, которая задается свойством orientation, и может принимать два значения - Horizontal / Vertical. logaritmic - логарифмическая шкала заливки, при тех же условиях (lvl - 50, min - 0, max - 100) "уровень" заливки будет расчитан по формуле (пример для горизонтального fillbar):

Level_dB = fullscale_dB - 20*log10( ( maximum - minimum ) / level )
fiil_width = level_dB * ( ( X1 - X0 ) / fullscale_dB )

    Выделенный, на скриншоте, виджет NGL_FillBar, как раз имеет тип logaritmic, остальные свойства также схожи с приведеным примером. Если свойство logaritmic выключено, то уровень заливки будет линеен между максимумом и минимумом. fullscale_dB - имеет значение только если у виджета установлено свойство logaritmic в true, задает полную шкалу в дБ. orientation - Horizontal / Vertical, горизонтальная или вертикальная ориентация, border - отрисовывать ли прямоугольник вокруг границ виджета или нет. markers / markers_color - "маркеры" в начале и в конце шкалы, их цвет. Структура в NGL:

/* NGL UI FillBar type */
typedef struct {
    const uint16_t X0, Y0, X1, Y1;
    const NGL_VertHoriz_Type Orientation;
    const uint16_t Level_MIN, Level_MAX;
     uint16_t Level;
     uint16_t sfX1, sfY1;
     FunctionalState Logarithmic;
     uint16_t FullScale_dB;
     FunctionalState Border;
     FunctionalState Markers;
     uint16_t MarkersColor;
     uint16_t Color;
} NGL_FillBar;

 

NGL_GraphScale

    Может использоватся как шкала к NGL_Fillbar или например к графикам, на приведенном скриншоте вверхний горизонтальный NGL_GraphScale имеет шкалу 0 - 25 А , у красного NGL_Fillbar сразу под ним установлено - minimum = 0, maximum = 25, level = 15, как видим все совпадает со шкалой. У второй "группы" NGL_GraphScale / NGL_Fillbar шкала в дБ, и у NGL_Fillbar установлено - minimum = 0, maximum = 100, level = 25, logarithmic = true, fullscale_dB = 90, все опять совпадает.
font - шрифт меток шкалы, gradientText - эксперементальная, пока игнорируется, maximum / minimum / scale_cent  - отвечают за максимальное/минимальное значения шкалы и цену деления, labels - метки шкалы, задаются строкой через запятые, принимаются только числовые значения. units - еденица измерения шкалы. showLabels / showLines - отрисовывать или нет метки / шкалу.
orientation / flip - горизонтальная или вертикальная ориентация, инвертирование вокруг "оси". Структура в NGL:

/* NGL UI  GraphScale type */
typedef struct {
    const uint16_t X0, Y0, X1, Y1;
     int MIN, MAX;
     int Cent;
    const int Labels[20];
     uint8_t LabelsCount;
     char *Units;
     FunctionalState ShowLabels;
     FunctionalState ShowLines;
     FunctionalState Flip;
    const NGL_VertHoriz_Type Orientation;
     NGL_Font* Font;
     uint16_t Color;
} NGL_GraphScale;

 

NGL_Label

    NGL_Label имеет всего 3 уникальных свойств, font / text - шрифт и текст метки, static отвечает за то каким образом метка будет "представлена" на странице, если параметр установлен в true, то метка будет отрисована один раз при отрисовке страницы, в групе статических объектов, иначе будет сгенерирована структура NGL_Label и указатель на нее добавлен в структуру страницы, таким образом становится возможным легко отрисовывать и главное - обновлять метку, для этого служат функции:

void NGL_GUI_DrawLabel(const NGL_Label *Label);
void NGL_GUI_UpdateLabel(const NGL_Label *Label, char *NewText);

   Обновляется только изменившийся текст, это дает минимум мерцаний и большую скорость, но это же привносит недостаток - при необходимости обновить метку, без изменения текста, другим цветом, функция NGL_GUI_UpdateLabel не сделает ничего. В этих случаях, в качестве исключения, необходимо вызвать полную отрисовку метки -  NGL_GUI_DrawLabel. В общем намного экономичней по ресурсам использовать статические метки, если не предполагается изменения их текста, и/или отдельной от общей перересовки. Структура в NGL:

/* NGL Label type */
typedef struct {
    const uint16_t X; // Left X coordinate
    const uint16_t Y; // Down Y coordinate
    uint16_t Color; // Text color
    const NGL_TransparentState Transparent; // Transparent state
    char* Text; // Text
    const NGL_Font *Font; // Label font
} NGL_Label;

 

NGL_Line

    Координаты NGL_Line определяют свойства Geometry его родителя QWidget и собственные координаты начала и конца отрезка, эти координаты задаются "внутри" прямоугольной области определенной Geometry, с началом координат в 0, 0

 

NGL_Rect

    Тут совсем все просто, геометрия прямоугольника определяется в Geometry, свойсвто fill - закрашен или нет.

 

NGL_SeekBar

    Предназначен для изменения каких либо параметров, генерирует событие нажатия, level / minimum / maximum определяют значение переменной level объекта в зависимости от положения ползунка. orientation - горизонтальная или вертикальная ориентация, show_progress - более светлая отрисовка от нуля до ползунка если включено. slidersize / slidercolor - размер и цвет ползунка. Структура в NGL:

/* NGL UI SeekBar type */
typedef struct {
    const uint16_t X0, Y0, X1, Y1;
    const uint16_t SliderSize;
     uint16_t old_posX, old_posY;
    const NGL_VertHoriz_Type Orientation;
    const int16_t Level_MIN, Level_MAX;
     int16_t Level;
     FunctionalState ShowProgress;
     uint16_t Color;
     uint16_t SliderColor;
    const pEvent ClickEvent;
} NGL_SeekBar;
 

    Это все виджеты доступные сейчас в пакете ngl-utils, их вполне достаточно для разнообразных простых и компактных по ресурсам интерфейсов. Открытый исходный код библиотеки и ngl-utils, а также инструментов Qt, дает широкие возможности для кастомизации, расширения и любой другой модификации библиотеки, или инструментария.

 

NGL_Greed

    На момент написания пакет ngl-utils не содержит такого плагина, предлагаю взять его в качестве примера создания своего виджета, я выбрал "сетку" потому что это достаточно показательный и простой объект, но заодно и полезный, может пригодится для тех же графиков/осциллограмм. Итак, если еще небыли скачаны исходники ngl-utils, то необходимо сделать это - репозиторий. Смотрим в папку nplugins видим две интересующие нас папки - python и widgets, в python лежат файлы "интерфейсов" виджетов к QtDesigner-у, в них описывается имя, иконка и т.п. Для каждого виджета должен быть соответсвующий файл "интерфейса" в котором объявлен класс плагина наследующий NGL_BasePlugin, который в сою очередь наследует QPyDesignerCustomWidgetPlugin. В папке widgets находятся сами виджеты которые могут использоватся как и обычные виджеты PyQt, то есть перед проверкой в QtDesigner их можно добавлять в свои приложения и проверить, или запускать как отдельное окно только с этим виджетом, по мере написания виджета "сетки" мы этим воспользуемся.

Создаем файл ngl_greed.py, в нем пишем следующее.


    Сетка будет иметь 4 своих свойства - отрисовка центральных линий и их цвет, размер ячейки по X и по Y. Для каждого свойства должен быть объявлен setter/getter для того что QtDesigner "подхватил" его и вывел в браузере свойств объекта. setter/getter для переменной типа bool будет выглядеть подобным образом:

    @pyqtProperty(bool)
    def central_lines(self):
        return self._central_lines
 
    @central_lines.setter
    def central_lines(self, state):
        self._central_lines = state
        self.update()

    Сразу и проверим! В SublimeText просто нажиамем F7, или в консоли набираем - python ngl_greed_plugin.py

    Как видим все предельно просто, и все работает, но центральные линии привязаны к геометрическому центру виджета, а сетка к началу координат. Из-за этого как видно есть как на скриншоте, для устранения этого "недостатка" нужно привязать сетку также к геометрическому центру виджета, смотрим модифицированный вариант.

Проверяем...


Отлично, теперь создадим "интерфейсный" файл ngl_greed_plugin.py и объявим в нем класс NGL_GreedPlugin - результат.


    Все готово к проверке в самом QtDesigner, сохраняем оба файла в соответсвующие папки - python / widgets, и запускаем скрипт setup.py, из корневой папки скаченного пакета ngl-utils.

> python setup.py install

Запускаем Qtdesigner скриптом ngldes:

   Остается только написать метод генерации кода под наш виджет, для этого создадим в папке templates текстовый файл с расширением ntp - greed.ntp с следующим содержимым:

/* {pageName} {itemName} item */
NGL_Greed {itemName} = {{
    {x},
    {y},
    {width},
    {height},
    {central_lines},
    {central_lines_color},
    {cell_widht},
    {cell_height},
    {color}
}};
 

Это, как наверно уже понятно, просто шаблон, последнее - модифицируем файл ngl_greed.py - окончательный результат.


    Еще раз собираем пакет, для того что бы внесенные изменения "отразились" на всех связаных компонентах пакета:

> python setup.py install

теперь можно запускать ngluic, предварительно создав и сохранив файл greed_test.ui, с добавленным на форму виджетом NGL_Greed, кому лень - вот готовый.

> ngluic -u greed_test.ui --verbose

 

На выходе - страница,


объявление структуры NGL_Greed


весь сгенерированный код одним архивом.

   

    Практически можно пользоватся (:, так как пока сама библиотека NGL ничего не знает о структуре типа NGL_Greed, но об этом чуть позже...

 

 

 print( [ln.format() + '\n' for ln in links] )


 

Категория: Графика | Добавил: LeftRadio (05.12.2015)
Просмотров: 437 | Рейтинг: 4.0/2
Всего комментариев: 0
Добавлять комментарии могут только зарегистрированные пользователи.
[ Регистрация | Вход ]