|
| ||||||||||||
| ||||||||||||
|
2009 г.
Создание кросс-платформенных графических интерфейсов на Perl/TkАлександр Симаков, alexander-simakov.blogspot.com ВведениеИстория графического тулкита Tk неразрывно связана с языком программирования Tcl и его создателем Джоном Остераутом (John Ousterhout). Первая версия Tcl вышла в свет в далёком 1987 году. Четыре года спустя Остераут представил и первый релиз графического тулкита Tk. Поддержка тулкита Tk в языке Perl, пусть и в виде альфа версии, появилась уже в 1994 году - гораздо раньше чем GTK+, Qt или WxWidgets. Автором этого проекта был Малкольм Бетти (Malcolm Beattie) из Оксфорда. Чуть позже к нему присоединился Ник Инг-Симмонс (Nick Ing-Simmons) из Texas Instruments, который в последствии и продолжил разработку Perl/Tk. На сегодняшний день существует несколько модулей для работы с Tk (да, TIMTOWTDI в Perl ещё никто не отменял). Основное отличие между ними заключается в способе взаимодействия с библиотекой Tk: или через XS-интерфейс, или через язык Tcl. Первый подход более трудоёмок для разработки и поддержки, но обладает большей производительностью, кроме того, он является стандартной идиомой для языка Perl. Второй подход представляет из себя тонкую прослойку, транслирующую Perl-код для работы с интерфейсом в команды Tcl/Tk, которые затем передаются на исполнение интерпретатору Tcl. Оба подхода имеют как плюсы так и минусы. Модуль, о котором говорилось в начале статьи относится к первой категории. Чуть позже мы также рассмотрим наиболее популярный модуль из второй категории. Установка в Linux/BSDВ UNIX-системах проблем с установкой Perl/Tk возникнуть не должно. К примеру, в Mandriva Linux соответствующий пакет называется perl -MTk -e "MainWindow->new(); MainLoop();" Если всё установлено правильно, то на экране должно появиться пустое окошко:
Установка в WindowsПод Windows Perl/Tk также устанавливается без проблем: ActiveState предоставляет PPM пакет
Более сложный пример на Perl/TkДля того чтобы продемонстрировать некоторые особенности Perl/Tk напишем чуть более сложное приложение с несколькими стандартными элементами пользовательского интерфейса: #!/usr/bin/perl # # Александр Симаков, <xdr (тчк) box на Google Mail> # http://alexander-simakov.blogspot.com/ # # Демонстрационная программа на Perl/Tk # use strict; use warnings; use Tk; sub main() { # Создаём главное окно my $mw = MainWindow->new(); # Фрейм для группировки Radiobutton-ов my $rb_frame = $mw->Frame()->pack( -side => "top" ); # В этой переменной будет сохраняться -value # выбранного Radiobutton-а. При изменении значения # $rb_variable извне, интерфейс будет обновлён # автоматически. my $rb_variable = "foo"; foreach my $name ( qw{ foo bar baz } ) { my $rb = $rb_frame->Radiobutton( -text => "Radiobutton $name", -value => $name, -variable => \$rb_variable, ); $rb->pack( -side => "left" ); } # Создаём Checkbutton. Его состояние сохраняется # в переменной $cb_variable: при её изменении # извне изменится и внешний вид Checkbutton-а. my $cb_variable = "on"; my $cb = $mw->Checkbutton( -text => "Checkbutton foobar", -onvalue => "on", -offvalue => "off", -variable => \$cb_variable, ); $cb->pack( -side => "top" ); # Создаём кнопку с обработчиком. При нажатии # будет выведен выбранный Radiobutton и текущее # состояние Checkbutton-а my $b = $mw->Button( -text => "Show status", -command => sub { print "Selected Radiobutton: '$rb_variable'\n"; print "Checkbutton state: '$cb_variable'\n"; } ); $b->pack( -side => "top" ); # Запускаем главный цикл обработки событий MainLoop(); } main();
Первое, что бросается в глаза - некоторая архаичность интерфейса, особенно в UNIX-окружении. Для одних задач это не имеет принципиального значения, а для других - наоборот. Также стоит отметить, что модуль Perl/Tk базируется на библиотеке Tk версии 8.4. Интерфейс, написанный на Tk 8.5, выглядит иначе: как именно - смотрите в следующем разделе. Модуль Tkx от ActiveStateМодуль Tkx, разрабатываемый при поддержке ActiveState, реализует своеобразный "мост" между Perl и Tcl. В результате, код для работы с интерфейсом транслируется в команды Tcl/Tk. Плюс такого подхода в том, что можно всегда использовать самую последнюю версию Tk без необходимости существенной переработки модуля. Минус - меньшая производительность по сравнению с XS-версией. Стоит отметить, что последние версии ActivePerl поставляются с предустановленным модулем Tkx. Это объясняется тем, что Tkx активно используется в программах, входящих в состав PDK (ActiveState Perl Dev Kit). В частности, Tkx используется графической версией менеджера пакетов PPM: для того чтобы посмотреть его в действии достаточно набрать команду perl -MTkx -e "Tkx::MainLoop();" Теперь перепишем предыдущий пример с использованием модуля Tkx и сравним результаты: #!/usr/bin/perl # # Александр Симаков, <xdr (тчк) box на Google Mail> # http://alexander-simakov.blogspot.com/ # # Демонстрационная программа на Perl/Tkx # use strict; use warnings; use Tkx; sub main() { # Создаём главное окно my $mw = Tkx::widget->new( "." ); # Фрейм для группировки Radiobutton-ов my $rb_frame = $mw->new_frame(); $rb_frame->g_pack( -side => "top" ); # В этой переменной будет сохраняться -value # выбранного Radiobutton-а. При изменении значения # $rb_variable извне, интерфейс будет обновлён # автоматически. my $rb_variable = "foo"; foreach my $name ( qw{ foo bar baz } ) { my $rb = $rb_frame->new_radiobutton( -text => "Radiobutton $name", -value => $name, -variable => \$rb_variable, ); $rb->g_pack( -side => "left" ); } # Создаём Checkbutton. Его состояние сохраняется # в переменной $cb_variable: при её изменении # извне изменится и внешний вид Checkbutton-а. my $cb_variable = "on"; my $cb = $mw->new_checkbutton( -text => "Checkbutton foobar", -onvalue => "on", -offvalue => "off", -variable => \$cb_variable, ); $cb->g_pack( -side => "top" ); # Создаём кнопку с обработчиком. При нажатии # будет выведен выбранный Radiobutton и текущее # состояние Checkbutton-а my $b = $mw->new_button( -text => "Show status", -command => sub { print "Selected Radiobutton: '$rb_variable'\n"; print "Checkbutton state: '$cb_variable'\n"; } ); $b->g_pack( -side => "top" ); # Запускаем главный цикл обработки событий Tkx::MainLoop(); } main(); Изменения в коде незначительные, чего не скажешь о внешнем виде:
Под Windows на таком простом примере различия не видны, но в более сложных приложениях они также будут заметны. Не смотря на то, что у Tkx открытая лицензиия, широкого распространения в UNIX-системах он пока не получил. Если в вашей UNIX-системе нет соответствующего пакета, потребуется установить по крайней мере два модуля из CPAN: Tkx и Tcl. В завершение стоит упомянуть про модуль Tcl::Tk, который также работает по принципу "моста". ВыводыИтак, мы рассмотрели два Perl-модуля для работы с тулкитом Tk: одноименный модуль Tk и Tkx. К плюсам модуля Tk можно отнести его распространенность и хорошую переносимость. К минусам - некоторую архаичность внешнего вида и привязку к устаревшей версии тулкита Tk. В актив Tkx можно записать современный внешний вид и значительно меньшую зависимость от версии тулкита Tk. С другой стороны, "из коробки" Tkx работает только в ActivePerl, хотя возможно в будущем ситуация и изменится. Также следует учитывать, что добавление ещё одного промежуточного слоя - Tcl - негативно сказывается скорости работы и усложняет и без того не тривиальный API. В целом, тулкит Tk обладает очень гибким API, но в силу своей оригинальности потребуется какое-то время чтобы к нему привыкнуть. В особенности это относится к фреймворку MegaWidgets для создания собственных виджетов на базе существующих. К странностям почти всех модулей для работы с Tk можно отнести невнятный и непоследовательный способ именования виджетов, методов и классов. Также стоит подчеркнуть обилие качественной документации как по Tcl/Tk так и по соответствующим Perl-модулям. К слову, Tk - единственный графический тулкит, чей Perl-интерфейс удостоился отдельной книги: Mastering Perl/Tk. Ссылки
|
|
CITForum © 1997–2025