LINUX.ORG.RU

Tcl/tk. GUI на SVG-виджетах. Поддержка SVG-файлов. Часть II

 , , , ,


0

1

Прежде чем перейти к рассмотрению svg-файлов, хотелось бы остановиться на самом интерпретаторе tcl/tk. Отвечая на один из вопросов, заданных после публикации первой части, я написал, что рассматриваемый проект успешно работает и на tcl/tk версии 9.0.1.

Мне захотелось, чтобы вместе с публикацией второй части статьи был выложен и дистрибутив графического интерпретатора tclexecomp на базе девятой версии tcl/tk. Однако выпуск версии tclexecomp для tcl/tk-9 задерживается и было решено собрать дистрибутив самостоятельно. Уже имея опыт сборки проекта Bawt для tcl/tk-9.0.1, удалось после нескольких дней работы собрать и дистрибутив tclexecomp с tcl/tk-9.0.1, с включёнными в него пакетами проекта svgwidgets. И всё было замечательно, все тестовые примеры работали. Но тут случайно мною была на клавиатуре нажата клавиша Backspace и произошел крах интерпретатора. После проверки остальных клавиш выяснилось, что аналогичный эффект происходит при нажатии клавиш Left и Right. Сначала я подумал, что это мои косяки, но решил проверить работу этих клавиш на виджетах text, entry и ttk::entry, в которых для редактирования текста используются эти клавиши. И тут выяснялось, что нажатие на эти клавиши приводит к краху интерпретатора wish9.0, т. е. собранная версия графического интерпретатора tclexecomp здесь ни при чём.

Честно говоря, я не стал проверять работу этих клавиш на первой версии tcl/tk-9.0.0. Первым порывом было написать письмо разработчикам tcl/tk, но прежде я решил посмотреть, как идут дела у разработчиков с подготовкой очередного релиза. И здесь меня ждал приятный сюрприз. В файле изменений для tk-9.0.2 присутствует такая запись: Backspace crashes 9.0 interpreter on FreeBSD.

Это было то, с чем столкнулся я. Правда здесь речь идёт о FreeBSD, а у меня Linux, но я решил проверить. Проверка дала положительный результат и больше проблем с клавиатурой я не наблюдал. Собранный интерпретатор со всеми пакетами svgwidgets под именем tclexecomp64_902_Lin64 добавлен в проект TkSVGWidgets на GitHub-е в папку tclexecomp902. Всем, кто будет тестировать проект, необходимо его скачать заново с GitHub. А теперь возвращаемся к основному материалу.

SVG-файлы представляют собой текстовые файлы с расширением .svg, содержащие xml-код, описывающий изображения в виде геометрических примитивов: линий, кривых, фигур, текста и т.д.

В tk-9.0 добавлена частичная поддержка svg-графики, которая позволяет использовать svg-иконки в GUI. Для этого сначала создается изображение:

image create photo [<идентификатор изображения>] [-format {svg [-scale <масштабирование> | -scaletowidth <ширина> | -scaletoheight <высота>]} 

Данный оператор всегда возвращает идентификатор изображения. Параметр scale задает масштаб изображения относительно исходного. Параметр scaletowidth указывает требуемую ширину изображения. Пропорционально изменению ширины будет установлена и высота изображения. Аналогично работает и параметр scaletoheight. Менять размер изображения можно и командой configure:

<идентификатор изображения> configure -format {svg [-scale <масштабирование> | -scaletowidth <ширина> | -scaletoheight <высота>] 

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

Это классика, а мы говорим об svg-виджетах и здесь этих проблем нет.

Для демонстрации запустим интерпретатор tclexecomp64_902_Lin64.

После запуска интерпретатора и загрузки пакета svg2can достаточно выполнить несколько команд, чтобы на холсте появилось изображение из файла svgimages/Action_launch.svg:

#Загружвем пакет svg2can
package require svg2can
#Создаем окно проекта
toplevel .t -background cyan
#Геометрия окна
wm geometry .t  380x640
#Создаем холст tkp::canvas
tkp::canvas .t.c -bg yellow -width 500 -height 450
#Размещаем холст в окне
pack .t.c -fill both -expand 1
#Размещаем на холсте картинку из svg-файла
set idsvg [svg2can::SVGFileToCanvas .t.c svgimages/Action_launch.svg]
winfo class .win.c
#Координаты картинки на холсте
set coordsid [.t.c bbox $idsvg]

В данном примере для отображения на холсте картинки используется команда svg2can::SVGFileToCanvas из пакета svg2can, которая имеет следующий формат:

svg2can::SVGFileToCanvas <tkp-холст> <путь к svg-файлу>

Xml-код картинки необязательно должен храниться в файле, его можно задавать явно в виде константы или как значение tcl-переменной. В этом случае используется команда следующего вида:

svg2can::SVGXmlToCanvas <path-холст> <xml-код>

Команды svg2can::SVGFileToCanvas и svg2can::SVGXmlToCanvas при успешном выполнении возвращают идентификатор группы (далее просто группа), в которой сгруппированы все элементы картинки. Чтобы получить все идентификаторы элементов картинки, достаточно выполнить команду:

<холст с картинкой> children <идентификатор группы>

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

svg2can::copy <холст с картинкой> <холст назначения> <группа> [<параметры>]

Эта команда копирует заданную картинку (<холст с картинкой> и <группа>) на указанный <холст назначения> и возвращает идентификатор группы на холсте назначения. Естественно, копирование может производиться и в рамках одного холста. После копирования оригинал может быть (если он больше не потребуется) уничтожен:

<холст с картинкой> delete <идентификатор группы>

Координаты клона на заданном холсте задаются списком параметров:

-x <координата по оси X>
-y <координата по оси Y>
-width <ширина картинки>
-height <высота картинки>

Для примера клонируем нашу картинку, при этом ширину картинки увеличим в полтора раза, а высоту увеличим в три раза и расположим справа от эталона. Размеры оригинала определим, выполнив команду bbox:

#Вычисляем координаты орининала
lassign [.t.c bbox $idsvg] x0 y0 x1 y1
#Создаем клон ракеты
::svg2can::copy .t.c .t.c $idsvg -x $x1 -y $y1 -width  [expr {($x1 - $x0) * 1.5}] -height [expr {($y1 - $y0) * 3}]

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

Итак, svg-изображение характеризуется двумя параметрами: именем холста, на котором оно размещено, и номером группы на этом холсте. SVG-изображения, так же как и классические изображения (image) могут использоваться как иконки в виджетах классов ibutton и cbutton. В классе cbutton иконки применимы к типам rect и square. Классические иконки задаются их идентификаторами, а svg-изображения задаются парой (списком)

-image | -isvg [list <svg-холст> <идентификатор группы>] 

или

-image | -isvg "<svg-холст> <идентификатор группы>"

Ниже представлен код, который добавляет кнопку «Старт» с иконкой в виде ракеты:

#Загружаем пакет svgwidgets
package require svgwidgets
#Устанавливаем высоту холста
.t.c configure -height 520
#Создаём кнопку «Старт» 
set idlauch [cbutton new .t.b2 -text Старт -image ".t.c $idsvg" -rx 10 -strokewidth 3]
#Устанавливает характеристика шрифта
$idlauch config -fontsize 29 -textfill red -textstroke yellow -fontweight bold
#Размещаем иконку в окне
pack  [$idlauch canvas] -fill both -expand 1 -padx 2c -pady 5m

Можно «поиграться» геометрией главного окна (например, перемещая правый нижний угол окна) и посмотреть как будет видоизменяться иконка с ракетой.

На Linux в каталоге /usr/share/icons можно найти много svg-файлов. Для их просмотра были написаны тестовые утилиты svgTestOrigToSVGWIDGET_Pack.tcl и svgtesttocan.tcl, которые находятся в каталоге examples.

К svg-изображениям можно применять различные трансформации (перемещение, масштабирование, поворот, смещение по осям X и Y). Увидеть, как это работает, можно, запустив утилиту examples/svgFileToCan.tcl. Результат работы этого скрипта можно видеть в правой нижней четверти скриншота в начале статьи.

Для комплексной демонстрации возможностей проекта svgwidgets в хранилище проекта на GitHub-е добавлен каталог examples/CryptoArmPKCS_Test, в котором лежит демонстрационный код криптографической утилиты cryptoatmpkcs_svg для работы с электронной подписью. Для ее запуска следует воспользоваться интерпретатором tclexecomp64_902_Lin64:

$tclexecomp64_902_Lin64 examples/CryptoArmPKCS_Test/mainguipkcs_svg.tcl

Стартовую страницу этой утилиты можно видеть в правой верхней четверти скриншота в начале статьи.



Проверено: CrX ()
Последнее исправление: TclTk (всего исправлений: 5)

Насколько я помню, в SVG, как и в EPS, нет возможности задать, скажем, толщину линии в 2pt конкретно на конечном устройстве, чтобы оно и на принтере было 2pt, и на мобиле 2pt, и на 4k - тоже 2pt.

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

Также в интерфейсах часто необходимы «резиновые» картинки, делящиеся на квадраты 3х3, в которых середина произвольно вытягивается, а края сохраняются. Теоретически такую можно собрать из 9 отдельных svg, но на стыках, скорее всего, будет грязь.

Adamos ★★
()
Ответ на: комментарий от Adamos

А что качество ракеты изменилось после «издевательств» над ней? Мне кажется нет. Насчет масштабирования вы ответили сами. Если картинка растровая, то при масштабировании её качество будет меняться. Если картинка состоит из фигур векторной графики, то качество сохраняется. Насчёт стыков - надо просто поэксперементировать.

TclTk
() автор топика
Для того чтобы оставить комментарий войдите или зарегистрируйтесь.