Продолжим знакомство с svg-виджетами для tcl/tk. Напомним, что рассматриваемые примеры, сам пакет svgwidgets и интерпретаторы tcl/tk с необходимыми пакетами можно найти на github-е. После выхода первой статьи все они претерпели изменения. Начнем мы статью с рассмотрения примера скрипт_button_PACK.tcl:

$/usr/local/bin64/tclexecomp140_svg_Linux64 скрипт_button_PACK.tcl

В этом примере добавлена кнопка для запуска интерпретатора tclexecomp. При нажатии на эту кнопку появляется окно консоли, а кнопка перепрофилируется в кнопку скрытия консоли:

Если щелкнуть по любой из кнопок (кроме кнопки управления консоли), то в консоли будет напечатан идентификатор объекта кнопки. Итак, щелкаем по кнопке Эллипс и в консоли получаем следующий результат:

% 
Эллипс=::oo::Obj61 Левый фрейм=::oo::Obj58
%

Посмотрим заливку объекта «левый фрейм»:

%::oo::Obj58 config -fillnormal
snow
%

Поменяем заливку фрейма с цвета снега (snow) на голубую (cyan):

%::oo::Obj58 config –fillnormal cyan

Мы видим, что виджеты не прямоугольной формы имеют прямоугольное обрамление с заливкой отличной от цвета виджета, в котором они размещены. Это обрамление имеет цвет холста, на котором размещен виджет:

% [::oo::Obj61 canvas] configure -background
-background background Background #d9d9d9 snow
%

Это уже знакомый нам цвет снега snow. Чтобы все привести в порядок необходимо наследование заливки -background для стандартных виджетов или –fillnormal для svg-виджетов. В нашем примере это можно сделать следующим образом:

% set colframe [::oo::Obj58 config -fillnormal]
cyan
% foreach wincan [pack slaves [::oo::Obj58 canvas]] {$wincan configure -background $colframe }
%

А что будет, если заливку cyan заменить на градиентную заливку?

Для начала создадим градиентную заливку для нашего фрейма:

% set gradCloud [[::oo::Obj58 canvas] gradient create linear -method pad -units bbox -stops { { 0.05 "#87ceeb" 1.00} { 0.17 "#ffffff" 1.00} { 0.29 skyblue 1.00} { 0.87 "#ffffff" 1.00} { 1.00 skyblue 1.00}} -lineartransition {1.00 0.00 0.75 1.00} ]
gradient5
%

После создания градиента зальем им наш холст:

% ::oo::Obj58 config -fillnormal gradient5
%

Мы снова столкнулись с той же проблемой, что и при смене просто цвета заливки, но разрешить эту проблему тем же способом не удастся. Кстати, такая же проблема возникает при использовании для размещения виджеты компоновщика place. И тут нам на помощь приходит пакет treectrl, в котором есть функция loupe.

Эта функция позволяет делать снимок любого участка экрана, а при желании, и масштабировать его. Отсюда и название функции loupe:

loupe <имя image> <x> <y> <w> <h> [<zoom>], где поле <имя image> содержит идентификатор изображения, создаваемого командой

image create photo –width <ширина> -height <высота>

Координаты x и y задают центр снимаемой области (подчеркиваю, ЦЕНТР), w – это ширина области, а h – высота снимаемой области.

Таким образом, функция loupe снимает (делает скриншот) участок  со следующими координатами:

X0 = x – w/2, y0 = y – h/2

X1 = x + w/2, y1 = y + h/2

Для решения вышеуказанной проблемы был реализован в каждом классе svg-виджетов метод fon. Задачей этого метода является сделать снимок участка экрана, на котором будет размещен svg-виджет и разместить этот снимок на нижнем слое холста виджета.

Если внимательно посмотреть на команду foreach, то можно заметить, что для виджета ::Прямоугольник метод fon не применялся. Для прямоугольных виджетов его можно не применять, картинка будет закрыта самим виджетом. Но тут есть нюанс. Этот нюанс связан с прозрачностью виджета. SVG-виджеты могут быть прозрачными. Прозрачность svg-виджетов задается через опцию –fillopacity, которая может принимать значение от 0 (полностью прозрачный виджет) до 1 (непрозрачный виджет). Прозрачность позволяет видеть либо цвет холста виджета (параметр -background), либо просматривать фон, на котором лежит виджет и который создается при вызове метода fon. Посмотрим на прозрачность на примере кнопки «Эллипс». Для начала установим его значение равным 1 (По умолчанию это значение не определено и виджет непрозрачен), а затем установим значение 0.5, т.е. сделаем полупрозрачным:

Для полной прозрачности svg-виджеты опция –fillopacity устанавливается в 0. Кстати, окантовка виджетов тоже может быть прозрачной (опция -strokeopacity).

Если вы попробуете изменить размеры окна (обратите внимание на стрелку в правом нижнем углу скриншота), то может быть нарушена градиентная заливка на холстах вложенных виджетов:

Чтобы исправить ситуацию, нужно повторно обратиться к методу fon:

%foreach obj "Прямоугольник ::oo::Obj95 ::oo::Obj96 ::oo::Obj97" {$obj fon}
%

А можно ли избежать этих недостатков? Да, можно. Все, что для этого нужно, так это размещать svg-виджеты на одном холсте с указанием координат каждого размещаемого виджета. Итак, создаем холст, на котором будем размещать необходимые нам svg-виджеты:

% set mainfr [cframe new .mainf -type frame -fillnormal yellow -rx 0 -strokewidth 0 -stroke ""]
::oo::Obj108
% ::oo::Obj108 pack -fill both -expand 1
%

По умолчанию для такого холста (класс cframe и тип frame) установлена обработка события <Configure>:

%bind .mainf <Configure>
::oo::Obj151 scaleGroup .mainf %w %h %x %y;::oo::Obj151 resize %w %h 0
%

На период разработки gui (отладки) можно отключить эту обработку, а по завершении ее можно будет восстановить:

%set bindorig [bind .mainf <Configure>]
% bind .mainf <Configure> {}
#разработка gui
#Восстановление обработки
% bind .mainf <Configure> $bindorig
%

Теперь на созданном холсте (.mainf или [::oo::Obj108 canvas]) можно размещать svg-виджеты, например:

%set went [cframe new .mainf -type centry -rx 2m -height 7m  -x 25m -y 10m -width 10c]   

При создании виджетов на уже существующем холсте необходимо явно указывать его коордитаты (опции –x и –y), а также высоту и длину виджета (опции –height и -width. Если опции –x и –y не указаны, то виджет размещается с координатами равными нулю. В этом случае для размещения виджета в нужном месте потребуется метод move (переместить):

<obj> move <dx> <dy>,

где dx и dy задают сдвиг по оси X и Y.

Если dx и dy равны 0, то метод возвращает дескриптор объекта:

%::oo::Obj065 move 0 0
canvasbObj65
%

Продвинутые юзеры могут его использовать для низкоуровнего конфигурирования svg-виджета.

Можно не только перемещать виджет, но и менять его размеры:

<obj> config [–width <новая ширина>] [-height <новая высота>]

При размещении svg-виджетов непосредственно на существующем холсте необходимость в методах fon, place, pack и grid отпадает, они в этом случае не используются.

Иногда бывает полезным скрыть (сделать невидимым) тот или иной виджет:

<obj> config –state hidden

Возврат виджета в нормальное состояние выполняется командой:

<obj> config –state normal

В примерах на github-е лежит скрипт скрипт_button_Холст.tcl. Если вы запустите его, то получите следующую картинку:

Как работает обработка события <Configure> можно увидеть, меняя размеры главного окна мышкой (стрелка в правом нижнем углу) или выполнением команды wm geometry:

Проект находится в начале пути, но уже сегодня с ним вполне можно создавать различные приложения с gui.

Кто-то может спросить, а что со средой разработки. На мой взгляд, графика tcl/tk настолько проста в использовании, что имея под рукой интерпретатор типа freewrap или его клон tclexecomp, можно достаточно быстро создать прототип графического интерфейса. Кстати, вместо freewrap и tclexecomp можно использовать и пакет tkcon.

Но все же, в голове сидит: "А почему бы не написать конструктор графического интерфейса?"

И вот параллельно с самим проектом потихоньку создается плагин (windowMegaWidgets.tcl), который можно будет использовать и в vTcl, и в TkProE, и даже в графическом редакторе tksvgpaint:

А там, глядишь, svg-виджеты перекочуют в python/Tkinter, а плагин станет доступен в графическом конструкторе Page для Python.

Но обо всем этом в следующих публикациях.

 Добавим, что svg-виджеты, также как и tcl/tk, доступны на платформах Linux, Windows и Android.

Часть I. SVG-виджеты для tcl/tk

Часть II. SVG-виджеты для tcl/tk. Градиентная заливка и прозрачность.

Комментарии (0)