http://www.nadomnik.by.ru/


Hello, Perl! Perl FAQ по-русски. Часть 5

Дмитрий Репин aka cmapuk[0nline]

Сегодня мы рассмотрим способы взаимодействия программы с пользователем, а именно - различные интерфейсы.

Интерлица

"Интерфейсы бывают разные: черные, белые, красные..."

"Птица-говорун отличается умом и сообразительностью...". Консольный интерфейс отличается простотой и производительностью.

Консольный интерфейс - это основа любой программы. Будь то чисто консольное приложение или "окошечная" программа. Многие не знают, что ассоциация расширений файлов с программой в системах Windows была бы невозможной, если бы разработчики софта забыли про консоль. При двойном клике на файле hello.txt в вашем файл-менеджере происходит следующее:

cmd>C:/WINDOWS/NOTEPAD.EXE hello.txt (можно набрать руками в консоли). Если бы программа NotePad не обрабатывала параметры, с которыми она вызывается, то она запустилась бы без открытия файла.

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

# Практический пример
# Аргументы командной строки aka параметры находятся в @ARGV
# разделителем команд является пробел.
# Для начала определим текст справки в переменную $HELP
$HELP=< Usage: myprogram.pl

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

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

Getopt::Std помогает собирать односимвольные параметры, а Getopt::Long - словесные.

# Простые
use Getopt::Std;
getopt('dphDAX', \%options);
# Так мы получим опции -d -p -h -D -A -X в хэш
# Сложные
use Getopt::Long;
my $save="";
my $action=""
my @files = ();
my %settings=();
GetOptions ("save" => \$save);
# Так мы получим параметр: myprogram.pl --save
# Если он существует, то в переменную $save запишется "1".
GetOptions ("action=s" => \$action);
# Так мы получим параметр: myprogram.pl --action=text
# Если он существует, то в переменную $action запишется текст "text".
GetOptions ("file=s" => \@files);
# Так мы получим список параметров: myprogram.pl --file=file1 --file=file2 --file=file3
# Если он существует, то в массиве @files мы найдем "file1","file2" и "file3"
GetOptions ("set=s" => \%settings);
# Так мы получим сложный параметр: myprogram.pl --set os=Linux --set cc=gcc
# Если параметры указаны, мы получим хэш с ключами os и cc, со значениями Linux и gcc соответственно.


Подробнее узнать об этих модулях и их возможностях можно по адресу perldoc Getopt::Std и perldoc Getopt::Long.

Если ваша программа не завершается после запуска и выполнения задачи, а требует дальнейшего ввода команд (как, например, ppm), чтение данных будет производиться из STDIN оператором <>.

...
while(!$exit){ # Цикл чтения команд. Работает до тех пор, пока не появится $exit=true
         print "\nmyprog>"; # приглашение для ввода myprog>
         $com=<>; # чтение строки. <> то же, что и
         last if $com =~/^exit/; # Выйдем из цикла, если введена команда "exit"
         ...
}
...

Совет: делайте распечатку хелпа, если пользователь запустил программу без аргументов. Если хелп большой, то можно просто написать 'Type myprogram.pl -h' или т.п.

Псевдографика. Все знают такие программы, как Norton-, Far- или Midnight-коммандеры. Они выполнены в текстовом интерфейсе (псевдографическом). Эх... было времечко ;-). Когда не было на свете Мелкомягких окон, Красных шапок с KDE и подобных GUI'евых примочек ($GUI="Graphic User Interface";), текстовые интерфейсы были самыми юзерскими. Они представляют собой набор простейших символов, расположенных на экране в определенных позициях, составляя таким образом некоторое изображение. Во, завернул! ;-) Анекдот по теме. Прапорщик: "Телевизор - это набор радиодеталей, соединенных специальным образом, чтобы на экране возникало изображение". Вернемся все же к Perl.

Для создания программы с текстовым интерфейсом вам потребуется библиотека Curses с CPAN. Альтернативный вариант - модули Term::***. В отличие от Term, варианты Curses имеются и для Win32 (под другие системы тоже). Работу с этим модулем я рассматривать не буду по причине того, что я уже с этим модулем работал мало, к тому же это было не вчера. Поэтому я не могу рассказать о тонкостях работы с ним, недостатках и преимуществах. Кроме того, я не слишком инетересуюсь псевдографическими интерфейсами, считая, что в наше время это смесь недостатков консольного и графического интерфейсного исполнения. Если вас сильно заинтересовал этот модуль, - установите его, загрузив с сайта CPAN, и на этом же сайте вы найдете необходимую документацию.

Совсем не псевдографика

Наконец мы подошли к теме графических интерфейсов. Самым популярным способом создания графических программ является модуль Tk и его подмодули. Для пользователей Win32 имеется также модуль Win32::GUI (docs - http://dada.perl.it). Всех этих примочек в стандартной поставке Перла нет, поэтому их нужно взять с сайта CPAN или ActiveState. Можно еще использовать модуль Win32::API, чтобы рисовать окошки напрямую через WinAPI, но тогда уж лучше вообще на Assembler переходить.

Рассмотрим способы "рисования окошек" с помощью модуля Tk. Этот модуль имеет объектно-ориентированный интерфейс (опять это импортное слово!).

use Tk;
$window = MainWindow->new();
MainLoop;
# Это минимальный код для создания окна

Теперь попробуем заполнить окно элементами (widgets).
use Tk;
$window = MainWindow->new();
# Рамка для группировки верхних кнопок.
$top=$window->Frame()->pack('-side' => 'top', '-fill' => 'x');
# Метод pack предназначен для задания свойств расположения элемента на форме.
# -side=>top означает, что рамка будет "прилипать" к верху формы.
# -fill=>x означает, что надо заполнять все пространство рамкой
# иначе при увеличении размера окна элементы будут сдвигаться к центру
$menu1=$top->Menubutton('-text' => 'File')->pack('-side' => 'left');
# Меню "File". Кнопка упакована в левой части рамки $top
# Команды меню "File". Параметр -command - обработчик выбора меню
# функция mbox ниже
         $menu1_1=$menu1->command('-label' => 'New',
                         '-command' => sub{mbox("New!\n");});
         $menu1_2=$menu1->command('-label' => 'Open',
                         '-command' => sub{mbox("Opened!\n");});
         $menu1_3=$menu1->command('-label' => 'Save',
                         '-command' => sub{mbox("Saved!\n");});
# Меню Help
$menu2=$top->Menubutton('-text' => 'Help')->pack('-side' => 'left');
         $menu2_1=$menu2->command('-label' => 'Help',
                         '-command' => sub{mbox("What\'s difficult?");});
# Теперь создадим вторую рамку
# Для других элементов.
$mainframe=$window->Frame()->pack('-side' => 'top', '-fill' => 'x');
         $text=$mainframe->Scrolled('Text', '-width' => 50, '-height' => 20, -font => 'Tahoma 8', -wrap => 'word',-scrollbars => 'se')->pack('-side' => 'left');
# Это текстовое поле с полосами прокрутки (параметры говорят сами за себя =) )
# Просто поле выглядело бы так:
# $text=$mainframe->Text('-width' => 100, '-height' => 30, -font => 'Tahoma 8', -wrap => 'word')->pack('-side' => 'left');
         $text->insert('1.0', "Hello, Perl!\n");
         # Вставляем текст. '1.0' - это курсор, указывающий начало текста
         # если надо дописать текст, то следует указать курсор 'end'
         $text->update();
# Обновить изменения в текстовом поле
# Получить текст можно методом get()
$mywords=$text->get('1.0','end');
# Т.е. прочитать от начала до конца
# Добавим элемент OptionMenu
@opt=("Beer", "Wine", "Gin", "Whiskey" , "White Spirit");
# В качестве вариантов выбора этот элемент берет ссылку на
# массив. В результате выбора значение оказывается в переменной,
# на которую ссылается параметр -variable
# Обработчик пишется в параметр -command, как у кнопок
$mainframe->Optionmenu(
  -options => \@opt,
  -variable => \$var,
  -command => sub{$text->insert('end',"$var\n");
                 $text->update();
                 }
  )->pack('-side' => 'top', '-fill' => 'x');
# Ну и самый главный элемент любой формы - кнопка! ;-))
$button=$mainframe->Button(-text => 'Exit', -width => 6, -height => 2,
                         -command => sub{$window->exit();})->
                         pack('-side' => 'top', '-fill' => 'x');
sub mbox{
         my $str=shift;
         # Этот метод вызывает окна сообщения
         # В данном случае это окно с одной кнопкой OK
         $window->messageBox( '-title' => 'Message Box',
                         '-message' => $str,
                         '-type' => "OK" );
}
# Все элементы формы должны быть описаны до MainLoop;
MainLoop; # Это, собственно, запуск интерфейса.
Все элементы остальных форм выстраиваются так же, как вышеописанные. Полный перечень с описанием свойств имеется в perldoc TK, perldoc Tk::Подраздел. Стоит отметить некоторые подразделы модуля Tk.
Tk::Animation - Отображение анимированных GIF'ов
Tk::Balloon - Круглые всплывающие подсказки
Tk::Canvas - Канвы (рисованные линии, круги, etc)
Tk::chooseColor - Диалог выбора цвета
Tk::clipboard - Работа с буфером обмена (Copy/Paste)
Tk::Clock - Элемент-часы
Tk::Dialog, Tk::DialogBox - Диалоги
Tk::DirTree - дерево каталогов

И еще много-много других подмодулей, позволяющих создавать полноценные GUI-программы, работать с файловой системой, графикой, различными *ML-форматами, базами данных, другими приложениями, и т.п. На этом я закончу рассказ о модуле Tk.

Источник: "Компьютер Price", http://www.comprice.ru

 


Copyright © "Internet Zone", http://www.izcity.com/, info@izcity.com