Хочу представить свой пет-проект . Создан он в недрах tсl/tk, который, по моему мнению, многие недооценивают. В статье речь пойдет не столько о tcl (хотя все примеры и сам проект написаны именно на нем), а сколько о tk.
Удобство tk мало кто не признает. Но как только покажешь приложение, в котором gui разработано на tk, то тут же можешь услышать - опять этот убогий, примитивный, в лучшем случае устаревший интерфейс. И я здесь я соглашусь с этими критиками. Предпринималось немало попыток улучшение презентабельности tk-виджетов (помимо ttk-виджет). Но даже они на фоне пользовательского интерфейса на мобильниках, на qt или gtk смотрятся бледновато.
Мои ожидания, связанные с выходом tcl/tk-9.0, в плане внешнего вида виджетов не оправдались.
А поскольку я фанат tcl/tk, то мне очень хотелось бы поправить это положение. Понятно, что эту проблему можно решить путем привлечения SVG-графики. Поддержка SVG-графики в tcl/tk реализована через пакет tkpath. Сразу отмечу, что поддержка svg-графики сегодня есть и в пакете tko, которая в нем реализована по образу и подобию tkpath. Различия в интерфейсах для работы с svg-графикой в них минимальны.
Помимо пакета tkpath (tko) для реализации проекта понадобился еще и пакет treectrl, о его роли будет рассказано позже.
Так родился проект, в недрах которого были разработаны виджеты на базе векторной графики, а именно svg-виджеты. Эти svg-виджеты и представлены в скриншоте к статье.
Проект включает в себя три пакета, а именно svgwidgets, svg2can и tkfe_svg. Первый пакет предназначен для создания собственно svg-виджетов. Пакет svg2can предназначен для экспорта на холст изображений из svg-файлов, а пакет tkfe_svg обеспечивает приложения файловым проводником. Все эти пакеты добавлены в состав интерпретаторов tclexrcomp_svg для платформ Linux и Windows. Сам проект, который включает перечисленные выше пакеты, интерпретаторы и примеры можно найти на github-e. Здесь же в папке applications можно найти и приложение cryptoarmpkcs_svg_linux64 для работы с электронной подписью как образец использования svg-виджетов.
Поэтому можно скачать и запустить приложение cryptoarmpkcs_svg_linux64, чтобы посмотреть, как выглядит приложение на базе svg-виджетов.
Скачав проект, запустите интерпретатор tclexecomp_v200_svg_Lin64.
После запуска на экране появится графическая консоль интерпретатора tcl/tk.
Первое что можно сделать, это посмотреть с какой версией tcl/tk вы работаете:
% puts $tcl_patchLevel
8.6.14
%
А на втором шаге, следует посмотреть доступные пакеты:
% foreach {p1 p2 p3 } [glob -types {d} -directory /cvfs/modules *] {
puts "[file tail $p1]\t\t\t[file tail $p2]\t\t\t[file tail $p3]"
}
tdbcpostgres1.1.7 tksvg0.6 tkfe_svg1.0
tclRFB0.5 tktray1.3.9 vfs1.4.2
sqlite3.44.2 zstd1.0 scrollutil_utils
tbcload1.7.2 Tclxml3.2 Tktable2.10
itcl4.2.4 mentry4.2 extrafont1.3
udp1.0.11 tdbcmysql1.1.7 Img1.4.14
scrolledwidget0.2 tcltls1.7.22 pgintcl3.5.1
cloudtk thread2.8.9 scrollutil2.2
Trf2.1.4 tkdnd2.9.4 tksvg0.12
TclReadLine1.4 Imagescale0.1 treectrl2.4.3
tko wcb4.0 trofs0.4.9
tdbcodbc1.1.7 bwidget1.9.16 tcllib1.21
Tkhtml3.0 tclcompiler1.7.4 html3widget0.2.6.1
svgwidgets0.3.3 spritz1.0 tdom0.9.3
imgtools0.3 tdbc1.1.7 pdf4tcl0.9.4
tklib0.7 tablelist7.2 SVG2CAN
tclx8.4 tkpath0.3.3 expect5.45.4
bgexec3.0
%
И убедиться, что требуемые пакеты (tkpath, treectrl, svgwidgets, svg2can и tkfe_svg) в наличии. Если их не окажется, то надо будет ручками добавить путь к требуемым пакетам в переменную auto_path.
В репозитории TkSVGwidgets в папке examples лежат tcl-скрипты, демонстрирующие svg-виджеты. Все примеры готовились на платформе linux в кодировке utf-8.
Примеры можно запускать как из командной строки:
$tclexecomp_v200_svg_Lin64 ~/TkSVGwidgets/examples/скрипт_button_PACK.tcl
так и из меню интерпретатора tclexecomp_v200_svg_Lin64 (File->Интерпретировать файл -><выбранный файл>).
Результаты работы примеров демонстрирует скриншот в начале статьи.
А теперь собственно о виджетах. SVG-виджеты оформлены в виде пяти классов: cbutton, ibutton, mbutton, cmenu и cframe, которые объединены в пакет svgwidgets:
%#Загрузка пакета svgwidgetds
%package require svgwidgets
0.3.3
%
Убедиться в том, что svg-виджеты стали доступны (классы ::cbutton, ::ibutton, ::mbutton, ::cmenu, cframe), можно выполнив следующую команду:
% foreach class [info class instances oo::class] {puts $class}
::oo::object
::oo::class
::oo::Slot
::cbutton
::ibutton
::mbutton
::cmenu
::cframe
%
Создание svg-виджетов практически ничем не отличается от создания классических виджетов в tcl/tk. Если вспомнить как создаются объекты того или иного класса при объектно-ориентированном программировании в tcl/tk, то окажется, что есть два способа. Различие этих способов состоит в том, что в первом способе идентификатор создаваемого объекта назначает конструктор класса:
<имя класса> new <имя холста> [параметры объекта]
Во втором способе идентификатор объекта назначает программист:
<имя класса> create <идентификатор объекта> <имя холста> [параметры объекта]
В обоих случаях конструктор возвращает идентификатор созданного объекта.
Для уничтожения объекта используется метод destroy:
<идентификатор объекта> destroy
При уничтожении объекта удаляется и холст, на котором создавался виджет.
Виджеты могут создаваться как каждый на отдельном холсте, так и размещаться на одном холсте. В последнем случае должны дополнительно указываться координаты левого верхнего угла виджета (параметры -x и -y). В этой статье мы будем рассматривать случай, когда каждый виджет создается на отдельном холсте. Заливка холста, на котором будет создаваться виджет, задается параметром –background или -bg.
Начнем знакомство с svg-виджетами с базового класса cbutton. В этом классе можно создать виджеты следующих типов (параметр -type): rect, round. ellipse, square, circle, check, radio, frame. По умолчанию создается виджет типа rect:
%cbutton new .but1 –text {Прямоугольник}
::oo::Obj58
#Посмотреть тип созданного виджета
%::oo::Obj58 config –type
rect
#Удаляем созданный виджет
%::oo::Obj58 destroy
%
Ниже представлен скрипт, который демонстрирует создание виджетов класса cbutton, за исключением типов radio и check. В скрипте демонстрируется создание виджетов типа frame и размещение в нём виджетов типа rect, round. ellipse, square, circle:
#скрипт №1
#загрузка пакета svgwidgets
package require svgwidgets
#установка геометрии главного окна
wm geometry . 500x400+100+50
#создаем svg-виджет класс cbutton и типа frame
set wfr [cbutton new .fr -type frame -fillnormal snow -strokenormal red]
#размещаем фрейм на главном окне, используя метод pack в классе cbutton
$wfr pack -in . -fill both -expand 1 -padx 1c -pady 1c
#Создаем виджеты кнопок rect, round. ellipse, square, circle
set i 0
foreach tbut [list rect round ellipse square circle ] {
set but$i [ eval cbutton new .but$i -type $tbut -command \{puts [set tbut]\} -text $tbut]
#Метод canvas в проекте svg-виджетов возвращает идентификатор (имя) холста,
#на котором размещается виджет
[set but$i] pack -in [$wfr canvas] -pady {5m 0}
incr i
}
Для получения свойств (параметров) отдельного виджета служит метод config. Например, для получения всех свойств виджета типа round в рассматриваемом примере достаточно выполнить команду вида:
%$but1 config
-text round -strokepress #dadada -strokeenter cyan -command {puts round} -stroke #dadada press 0 -fillnormal gradient1 -strokewidth 1 -strokenormal #dadada -state normal -rx 13.000000000000002 -fontsize 11.338582677165354 -relcom 0 -ry 0 -displaymenu release -image {} -fillpress green -textfill black -fillenter skyblue -compound none -ipad {3.779527559055118 3.8004301075268843 3.8628571428571488 3.8628571428571488} -fontweight normal -rotate 0 -width 94.0 -fontfamily {DejaVu Sans} -isvg {} -height 26.000000000000004 -type round
%
Назначение параметров достаточно прозрачное. Отдельного пояснения требует работа с иконками (параметры -image, -isvg, -compound, -ipad), о них мы поговорим в следующей части.
Сразу отметим, что заливка виджетов (параметры -fillpress, -fillenter, -fillnormal) может быть как одноцветной, так и градиентной. О градиентной заливке расскажем в отдельной статье. Параметр -fillpress определяет заливку виджета при нажатой кнопки мыши, -fillenter – при наведении курсора мыши на виджет, -fillnormal – при обычном состоянии.
Оконтовка виджета (параметры -strokenormal, -strokepress, -strokeenter) может быть только одноцветной. При этом можно регулировать прозрачность как заливки (параметр -fillopacity), так и окантовки (параметр -strokeopacity). По умолчанию виджеты создаются непрозрачными. Уровень прозрачности задается от 0 до 1.
Метод config служит также для получения текущего значения того или иного атрибута или установления нового значения:
<экземпляр объекта> config <атрибут> [<новое значение атрибута>]
При создании виджетов класса cbutton с типом check и radio (аналоги классических виджетов checkbutton и radiobutton) дополнительно должен задаваться параметр -variable с указанием глобальной переменной, в которой будет сохраняться ее значение. Для виджета типа check значение 1 будет указывать на то, что кнопка была нажата, а 0 – кнопка отжата. Для виджета типа radio задается еще параметр –value со значением, которое будет принимать переменная при нажатии на эту кнопку.
Кстати, получить список всех доступных методов можно выполнив команду вида:
<экземпляр объекта> methods
Для получения списка экземпляров отдельного класса можно воспользоваться командой вида:
info class instances <имя класса >
В последующем мы рассмотрим использование иконок, в том числе и из svg-файлов, а так же покажем как работает масштабирование, создание выносок (callout-ов) и другое. А здесь можно попробовать получить текущий список иконок:
%image names
::tk::icons::information ::tk::icons::warning
%
и одну из этих иконок ::tk::icons::warning назначить виджету, который имеет тип rect (переменная but0):
%$but0 config -image ::tk::icons::warning
%
Иконки доступны для виджетов класса cbutton типа rect или square.