Logo Море(!) аналитической информации!
IT-консалтинг Software Engineering Программирование СУБД Безопасность Internet Сети Операционные системы Hardware
Обучение от Mail.Ru Group.
Онлайн-университет
для программистов с
гарантией трудоустройства.
Набор открыт!
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-Tk, а в OpenBSD - p5-Tk. Корректность установки можно проверить простым однострочником:

perl -MTk -e "MainWindow->new(); MainLoop();"

Если всё установлено правильно, то на экране должно появиться пустое окошко:

Установка в Windows

Под Windows Perl/Tk также устанавливается без проблем: ActiveState предоставляет PPM пакет Tk для своего дистрибутива ActivePerl. Проверить корректность установки можно тем же самым однострочником. Вот как выглядит результат его запуска под Windows:

Более сложный пример на 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();


Вид в Linux


Вид в Windows

Первое, что бросается в глаза - некоторая архаичность интерфейса, особенно в 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: для того чтобы посмотреть его в действии достаточно набрать команду ppm. Проверить работоспособность Tkx можно и следующим однострочником:

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();

Изменения в коде незначительные, чего не скажешь о внешнем виде:


Вид в Linux


Вид в Windows

Под 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.

Ссылки

Новости мира IT:

Архив новостей

Последние комментарии:

Loading

IT-консалтинг Software Engineering Программирование СУБД Безопасность Internet Сети Операционные системы Hardware

Информация для рекламодателей PR-акции, размещение рекламы — adv@citforum.ru,
тел. +7 985 1945361
Пресс-релизы — pr@citforum.ru
Обратная связь
Информация для авторов
Rambler's Top100 TopList liveinternet.ru: показано число просмотров за 24 часа, посетителей за 24 часа и за сегодня This Web server launched on February 24, 1997
Copyright © 1997-2000 CIT, © 2001-2015 CIT Forum
Внимание! Любой из материалов, опубликованных на этом сервере, не может быть воспроизведен в какой бы то ни было форме и какими бы то ни было средствами без письменного разрешения владельцев авторских прав. Подробнее...