Окна, которые создает Gtk-perl
Если необходимо поставить надпись в титле window вместо названия скритпа, то надо воспользоваться следующей функцией:
$window->set_title( $title );
где $title - строка, в которой содержится текст.
Установка фокуса в виджете и про свойства виджета по умолчанию.
Каждое окно имеет виджет с фокусом, для его установки необходимо написать
$window->set_focus( $widget );
фокус можно установить при помощи нажатия пробела на клавиатуре(? проверить)
Виджет по умолчанию может быть установлен при помощи функции
$window->set_default( $widget );
Отметим, что виджет в первую очередь должет быть определен функцией can_default(). Виджет по умолчанию активируется по нажатию кнопки Enter.
Поведение окон(window policy).
Поведение окон определяет, что происходит с изображением, когда окно изменяет сой размер. Можно установить window policy вызывая функцию
$window->set_policy( $allow_shrink, $allow_grow, $auto_shrink);
аргумент $allow_shrink может быть либо истинным либо ложным, определяет, может ли пользователь сделать окно меньшим его минимального размера.
аргумент $allow_grow (true или false) определяет может ли быть окно больше, чем его размер.
аргумент $auto_shrink(true или false) определяет, необходимо ли автоматически изменять размер окна в начальный, если он был изменен пользователем.
В большинстве случаев пользуются двумя путями:
# разрешить изменение размеров
$window->set_policy( $false, $true, $false );
# програмный контроль размеров
$window->set_policy( $false, $false, $true );
Приоритеты форм(Modal Windows)
Если необходимо, чтобы фокус всегда находился на одном и том-же окне(оно было всегда сверху всех остальных), то надо вызвать функцию
$window->set_modal( $modal );
агрументом которой может быть истина или ложь.
Размеры окна и начальное положение.
функция $window->set_default_size( $width, $height ); указывает размеры окна при его прорисовке по умолчанию. Установить позицию окна можно при помощи функции $window->set_position( $position ); где аргументами явяются 'none'(никакого влияния на размещение, оконный менеджер размещает форму там, где требуется), 'center'(отображаемое окно находится в центре экрана), 'mouse'(положение окна определяется текущим положением мыши).
Создание кнопок
Иерархия наследования
Inheritance Hierarchy
Object
+--- Widget
+--- Container
+--- Bin
+--- Button
Есть два пути создания кнопок, создать пустую кнопку и добавить потомка позднее или создать кнопку с лейблом как потомка:
$button = new Gtk::Button();
$button = new Gtk::Button( $label );
$button = new_with_label Gtk::Button( $label );
Первая функция создает пустую кнопку, две послдение создают её с лейблами. Средная просто сокращение последней.
Если создается кнопка с лейблом, то можно использовать button->child для доступа к виджету-потомку. Например, чтобы изменить текст в на лейбле, нужно сделать так:
$button->child->set( "new label" );
Если кнопка с лейблом не создается, то необходимо виджет добавить к кнопке. Например три следующих примера эквивалентны:
# создать кнопку с лейблом
$button = new Gtk::Button( "text" );
# тоже самое, но с другой функцией new()
$button = new_with_label Gtk::Button( "text" );
# создать лейбл, отделенный от кнопки и объединить их потом вручную.
$button = new Gtk::Button();
$label = new Gtk::Label( "text" );
$button->add( $label );
Сигналы, посылаемые кнопками.
Виждет кнопки посылает следующие сигналы:
'pressed' - посылается, когда кнопка нажата в пределах её размеров, или когда происходит вызов функции $button->pressed()
'released' - посылается, когда когда кнопка отжата в пределах её размеров, или когда происходит вызов функции $button->released()
'clicked' - когда кнопка нажата и отпущена в пределах размеров или когда вызывается функция $button->clicked()
'enter' - когда курсор мыши входит в пределы кнопки или когда вызывается функция $button->enter()
'leave' - когда курсор выходит из области, где нарисвана кнопка, соответственно эмитация выхода, как и выше, может быть вызвана програмно $button->leave()
Стили
Стили кнопок могут быть трех типов: 'normal', 'half' и 'none'. 'normal' - по умолчанию, для утсановки и апроса стиля, нужно писать следующее:
$button->set_relief( $relief_style );
$button->get_relief();
Ниже пример, в котором создается кнопка с лейблом, который в дальнейшем изменяется, далее удаляется и
переопределяется вручную и в конце по третьему клику происходит выход из формы с кнопкой.
#!/usr/bin/perl -w
use Gtk;
use strict;
set_locale Gtk;
init Gtk;
my $false = 0;
my $true = 1;
my $window = new Gtk::Window( "toplevel" );
my $button = new Gtk::Button( "Button created with label" );
my $label;
my $id;
my $numclicked = 0;
# обработка выхода
$window->signal_connect( "delete_event", \&CloseWindowEvent );
$button->signal_connect( "clicked", \&ClickedButtonEvent );
# атрибуты
$button->show();
# атрибуты окна
$window->border_width( 15 );
$window->add( $button );
$window->show();
# вызов Gtk
main Gtk;
exit( 0 );
### Подпрограммы
# вызов когда кнопка кликнется, при первом нажатии лейбл изменяется, при втором нажатии лейбл добавляется к кнопке, при
# третьем нажатии лейбл меняется и пи четвертом происходит выход из программы
sub ClickedButtonEvent{
if ( $numclicked == 0 ){
$button->child->set( "Changed Button Label" );
$numclicked++;
} elsif ( $numclicked == 1 ){
$window->remove( $button );
$button = new Gtk::Button();
$label = new Gtk::Label( "Label added to a button" );
$button->add( $label );
$label->show();
$button->show();
$window->add( $button );
$id = $button->signal_connect( "clicked", \&ClickedButtonEvent );
$numclicked++;
} elsif ( $numclicked == 2 ) {
$label->set( "Now Click to Close Window" );
$numclicked++;
} else {
Gtk->exit( 0 );
}
}
# Callback called when the window is asked to close. What really
# happens is that the window moves down and to the right. This is an
# excellent example of a program that doesn't act like the user
# expects.
sub CloseWindowEvent
{
# If you return a false value in the "delete_event" signal
# handler, GTK will emit the "delete_event" signal.
# Returning a true value means you don't want the window to
# be destroyed.
$window->window->move( 100, 100 );
return $true;
}
сделать скриншоты работы программы
Кнопки Toggle
Иерархия наследования
Object
+--- Widget
+--- Container
+--- Bin
+--- Button
+--- ToggleButton
Кнопки Toggle отличны от нормальных тем, что находятся в одном из состояний "нажато" или "не нажато".
Создание кнопок Toggle
new Gtk::ToggleButton();
new Gtk::ToggleButton( $label );
Реакция кнопки на запросы аналогична тому, что было описано выше про виджеты. Соответственно первая строчка создает просто кнопку, а вторая создает кнопку с лейблом.
Toggle сигналы.
Чтобы восстановить состояние toggle виджета, включая радиокнопки или
чекбоксы, используется приведенная ниже конструкция. Код проверяет состояние
кнопки, обращаясь к активной области виджета, содержащего toggle.
Интересующий сигнал, посылаемый кнопкой(радио или чекбоксом), зовется
'toggled'. Чтобы проверить состояние этих кнопок, необходимо выставить
обработчик сигнала чтобы поймать toggled сигнал:
sub toggle_button_callback
{
$togglebutton = $_[0];
if ( $togglebutton->active )
{
# Если тоггл нажат, то выполнится этот участок кода
}
else
{
# Если тоггл отжат, то выполнится этот участок кода
}
}
Состояние кнопки toggle
Чтобы сэмулировать нажатие тоггль-кнопки, её детей(все это относится к
чекбоксам и радиокнопкам), используется функция set_active():
$togglebutton->set_active( $state );
Когда срабатывает эта функция, то в системе проходит сигнал 'clicked' но не 'toggled'.
Чтобы узнать состояние кнопки, необходимо вызвать функцию get_active():
$togglebutton->get_active();
Строчка $togglebutton->toggled(); испускает 'toggled' сигнал;
Чекбоксы
Иерархия наследования
Object
+--- Widget
+--- Container
+--- Bin
+--- Button
+--- ToggleButton
+--- CheckButton
Чекбоксы наследуют свойства и функции тоггля, но с небольшим различием. В случае чекбокса название располагается рядом с полем для галочки(или круглой кнопки и т.д. - зависит от темы оконного менеджера). Создание чекбокса происходит как обычно:
new Gtk::CheckButton();
new Gtk::CheckButton( $label );
Соответственно первая строка - просто чекбокс, вторая - чекбокс с лейблом. Обработка евентов оналогичо тогглям.
Радиокнопки
Object
+--- Widget
+--- Container
+--- Bin
+--- Button
+--- ToggleButton
+--- CheckButton
+--- RadioButton
поведение радиокнопок аналогично их поведению при использовании html и удобно, когда необходимо выбрать что-то из очень короткого списка позиций.
Создать группу радиокнопок можно при помощи следующих строк:
new Gtk::RadioButton( $label );
new Gtk::RadioButton( $label, $button );
Видно, что второй способ создания радиокнопки имеет дополнительный параметр $button, который позволяет группировать кнопки относительно начальной кнопки. Следующий пример более четко поясняет эту концепцию группировки(связывания нескольких радиокнопок):
#создаем первую кнопку и добавляем её в бокс
$radio1 = new Gtk::RadioButton( "button 1" );
$box->add( $radio1 );
# создаем вторую кнопку и добавляем её в бокс(к первой )
$radio2 = new Gtk::RadioButton( "button 2", $radio1 );
$box->add( $radio2 );
# создаем третью кнопку и добавляем её в бокс
# и связываем её со второй кнопкой
$radio3 = new Gtk::RadioButton( "button 3", $radio1 );
$box->add( $radio3 );
# создаем 4-ю кнопку, и связываем её с третьей
$radio4 = new Gtk::RadioButton( "button 4", $radio3 );
$box->add( $radio4 );
Если необходимо выделять по дефолту какую-то из кнопок из группы, то это делается строчкой
$togglebutton-> set_active ($state);
Действие аналогично действию тогглов, В группе радиокнопок только одна может быть активной. Когда происходит смена выделения радиокнопки, то происходит испускание двух 'toggled' сигналов "снятие выделения" и "новое выделение".
Группы кнопок.
Если есть желание получить список радиокнопок, то необходимо использовать функцию:
@group = $radiobutton->button_group();
Если необходимо добавить радиокнопку к ранее созданной группе, то надо написать:
$radiobutton->button_set_group( @group );
Пример использования радиокнопок
#!/usr/bin/perl -w
use Gtk;
use strict;
set_locale Gtk;
init Gtk;
my $false = 0;
my $true = 1;
my $window;
my $box1;
my $box2;
my $button;
my $separator;
$window = new Gtk::Window( "toplevel" );
$window->signal_connect( "delete_event", sub { Gtk->exit( 0 ); } );
$window->set_title( "Radio Buttons" );
$window->border_width( 0 );
$box1 = new Gtk::VBox( $false, 0 );
$box1->show();
$box2 = new Gtk::VBox( $false, 10 );
$box2->border_width( 10 );
$box1->pack_start( $box2, $false, $false, 0 );
$box2->show();
$window->add( $box1 );
$button = new Gtk::RadioButton( "button 1" );
$box2->pack_start( $button, $false, $false, 0 );
$button->show();
$button = new Gtk::RadioButton( "button 2", $button );
$button->set_active( $true );
$box2->pack_start( $button, $true, $true, 0 );
$button->show();
$button = new Gtk::RadioButton( "button 3", $button );
$box2->pack_start( $button, $true, $true, 0 );
$button->show();
$button = new Gtk::RadioButton( "button 4", $button );
$box2->pack_start( $button, $true, $true, 0 );
$button->show();
$separator = new Gtk::HSeparator();
$box1->pack_start( $separator, $false, $false, 0 );
$separator->show();
$box2 = new Gtk::VBox( $false, 10 );
$box2->border_width( 10 );
$box1->pack_start( $box2, $false, $true, 0 );
$box2->show();
$button = new Gtk::Button( "Close" );
$button->signal_connect( "clicked", sub { Gtk->exit( 0 ); } );
$box2->pack_start( $button, $true, $true, 0 );
$button->can_default( $true );
$button->grab_default();
$button->show();
$window->show();
main Gtk;
exit( 0 );
когда пример будет запущен, что на экране покажется тчо-то подобное этому скриншоту(по дефолту выделена 4-я кнопка): (вставить скриншот)
Button box
Иерархия наследования
Object
+--- Widget
+--- Container
+--- Box
+--- ButtonBox
Бокс с кнопками предназначен для удобства расположения последних. Можно располагать серии кнопок как вертикально, так и горизонтально. Для создания необходимого button box нужно написать
$button_box = new Gtk::HButtonBox();
$button_box = new Gtk::VButtonBox();
Так-же этот метод расположения позволяет задавать и изменять величину пробела между кнопками:
$button_box-> set_spacing_default ($spacing);
$button_box-> get_spacing_default ();
И, помимо всего прочего, можно задавать тип расположения кнопок внутри бокса:
$button_box-> set_layout_default ($layout);
Переменная $layout может иметь несколько значений:
'default_style'
'spread'
'edge'
'start'
'end'
Текущее состояние лайота может быть восстановлено функцией
$button_box-> get_layout_default ();
Добавление кнопок в бокс можно реализовать, написав функцию
$button_box->add( $button );
И небольшой пример, иллюстрирующий все типы лайотов, определяющих поведение содержимого button box:
#!/usr/bin/perl -w
use Gtk;
use strict;
set_locale Gtk;
init Gtk;
my $false = 0;
my $true = 1;
my $window;
my $main_vbox;
my $vbox;
my $hbox;
my $frame_horizontal;
my $frame_vertical;
# создаем окно
$window = new Gtk::Window( "toplevel" );
$window->set_title( "Button Boxes" );
$window->signal_connect( "destroy", sub { Gtk->exit( 0 ); } );
$window->border_width( 10 );
# Создаем вертикальный бокс
$main_vbox = new Gtk::VBox( $false, 0 );
$window->add( $main_vbox );
# создаем горизонтальный фрейм
$frame_horizontal = new Gtk::Frame( "Horizontal Button Boxes" );
$main_vbox->pack_start( $frame_horizontal, $true, $true, 10 );
# Создаем вертикальный бокс, чтобы внутри поместить горизонтальный фрейм
$vbox = new Gtk::VBox( $false, 0 );
$vbox->border_width( 10 );
$frame_horizontal->add( $vbox );
$vbox->pack_start( create_bbox( $true, "Spread (spacing 30)",
30, 85, 20, 'spread' ),
$true, $true, 0 );
$vbox->pack_start( create_bbox( $true, "Spread (spacing 40)",
40, 85, 20, 'spread' ),
$true, $true, 0 );
$vbox->pack_start( create_bbox( $true, "Edge (spacing 30)",
30, 85, 20, 'edge' ),
$true, $true, 5 );
$vbox->pack_start( create_bbox( $true, "Start (spacing 20)",
20, 85, 20, 'start' ),
$true, $true, 5 );
$vbox->pack_start( create_bbox( $true, "End (spacing 10)",
10, 85, 20, 'end' ),
$true, $true, 5 );
# создаем вертикальный фрейм
$frame_vertical = new Gtk::Frame( "Vertical Button Boxes" );
$main_vbox->pack_start( $frame_vertical, $true, $true, 10 );
# создаем горизонтальный бокс, чтобы поставить туда вертикальный фрейм
$hbox = new Gtk::HBox( $false, 0 );
$hbox->border_width( 10 );
$frame_vertical->add( $hbox );
$hbox->pack_start( create_bbox( $false, "Spread (spacing 5)",
5, 85, 20, 'spread' ),
$true, $true, 0 );
$hbox->pack_start( create_bbox( $false, "Edge (spacing 30)",
30, 85, 20, 'edge' ),
$true, $true, 5 );
$hbox->pack_start( create_bbox( $false, "Start (spacing 20)",
20, 85, 20, 'start' ),
$true, $true, 5 );
$hbox->pack_start( create_bbox( $false, "End (spacing 20)",
20, 85, 20, 'end' ),
$true, $true, 5 );
$window->show_all();
main Gtk;
exit( 0 );
### подпрограммы
# Создаем бокс с параметрами. Первый параметр ложь или истина,
# отвечает за ориентацию бокса, второй - заголовок бокса.
# третий - величина отступа, четвертый и пятый - высота и ширина кнопок
# и шестой - параметр выравнивания внутри кнопок.
sub create_bbox{
my ( $horizontal, $title, $spacing, $child_w, $child_h, $layout ) = @_;
my $frame;
my $bbox;
my $button;
$frame = new Gtk::Frame( $title );
# создаем баттон бокс
if ( $horizontal )
{
$bbox = new Gtk::HButtonBox();
}
else
{
$bbox = new Gtk::VButtonBox();
}
$bbox->border_width( 5 );
$frame->add( $bbox );
# Устанавливаем набор параметров
$bbox->set_layout( $layout );
$bbox->set_spacing( $spacing );
$bbox->set_child_size( $child_w, $child_h );
# добавляем кнопки в бокс
$button = new Gtk::Button( "OK" );
$bbox->add( $button );
$button = new Gtk::Button( "Cancel" );
$bbox->add( $button );
$button = new Gtk::Button( "Help" );
$bbox->add( $button );
return ( $frame );
}
Виджеты-лейблы
Иерархия наследования
Object
+--- Widget
+--- Misc
+--- Label
Лейблы довольно часто используются в Gtk и относительно просты в применении. Лейблы не генерируют сигналов, так как они не имеют собственного окна XWindow. Если необходимо поймать сигнал, или зафиксировать его, поставьте его в EventBox или Button widget.
Для создания нового лейбла, нужно написать
$label = new Gtk::Label( $string );
Единственный аргумент, передаваемый функции - строчка, которую программист хочет видеть в заголовке лейбла. Для изменения этой строчки после создания лейбла, необходимо использовать функцию:
$label->set_text( $string );
Место, необходимое для новой строчки, будет выделено автоматически если это необходимо. Можно делать многострочные лейблы, выставляя переводы кареток в лейбл-стринге. Для восстановления текущего состояния стринга, используется функция get():
$sting = $label->get();
Лейбл-текст может быть выровнен при помощи функции set_justify():
$label->set_justify( $jtype );
Значения, которые может принимать переменная $jtype:
'left'
'right'
'center' (default)
'fill'
Лейбл-виджет так-же может автоматически выравнивать содержащийся в нем текст. Эта опция активируется функцией set_line_wrap():
$label->set_line_wrap( $wrap );
Переменная $wrap имеет значения истина или ложь. Если хочется текст в лейбле сделать подчеркнутым, то нужно выставить образец подчеркивания:
$label-> set_pattern ($pattern);
Аргемент показывает, как подчеркивать текст, допустим если подчеркивание определяется как "_ _ _ _ _" то подчеркнутыми будут певрая, третья, пятая, седьмая и девятая буквы. Ниже приведен пример, который иллюстрирует эти функции. Пример использует виджет-фрейм, чтобы показать лейбл-стили. Фрейм-виджет будет рассмотрен позднее.
#!/usr/bin/perl -w
use Gtk;
use strict;
set_locale Gtk;
init Gtk;
my $false = 0;
my $true = 1;
my $window;
my $hbox;
my $vbox;
my $frame;
my $label;
# Create the window
$window = new Gtk::Window( "toplevel" );
$window->signal_connect( "destroy", sub { Gtk->exit( 0 ); } );
$window->set_title( "Label" );
$vbox = new Gtk::VBox( $false, 5 );
$hbox = new Gtk::HBox( $false, 5 );
$window->add( $hbox );
$hbox->pack_start( $vbox, $false, $false, 0 );
$window->border_width( 5 );
# Create labels and add them
$label = new Gtk::Label( "This is a Normal Label" );
$frame = new Gtk::Frame( "Normal Label" );
$frame->add( $label );
$vbox->pack_start( $frame, $false, $false, 0 );
$label = new Gtk::Label( "This is a Multi-line label.\nSecond line\n"
. "Third Line" );
$frame = new Gtk::Frame( "Multi-line Label" );
$frame->add( $label );
$vbox->pack_start( $frame, $false, $false, 0 );
$label = new Gtk::Label( "This is a Left-Justified\n"
. "Multi-line label.\nThird line");
$label->set_justify( 'left' );
$frame = new Gtk::Frame( "Left Justified Label" );
$frame->add( $label );
$vbox->pack_start( $frame, $false, $false, 0 );
$label = new Gtk::Label( "This is a Right-Justified\nMulti-line label.\n"
. "Fourth line, (j/k)" );
$label->set_justify( 'right' );
$frame = new Gtk::Frame( "Right Justified Label" );
$frame->add( $label );
$vbox->pack_start( $frame, $false, $false, 0 );
$vbox = new Gtk::VBox( $false, 5 );
$hbox->pack_start( $vbox, $false, $false, 0 );
$frame = new Gtk::Frame( "Line wrapped label" );
$label = new Gtk::Label( "This is an example of a line-wrapped label. It "
. "should not be taking up the entire "
. "width allocated to it, but automatically "
. "wraps the words to fit. "
. "The time has come, for all good men, to come to "
. "the aid of their party. "
. "The sixth sheik's six sheep's sick.\n"
. " It supports multiple paragraphs correctly, "
. "and correctly adds "
. "many extra spaces. " );
$label->set_line_wrap( $true );
$frame->add( $label );
$vbox->pack_start( $frame, $false, $false, 0 );
$frame = new Gtk::Frame( "Filled, wrapped label" );
$label = new Gtk::Label( "This is an example of a line-wrapped, filled
label. "
. "It should be taking "
. "up the entire width allocated to it. "
. "Here is a sentence to prove "
. "my point. Here is another sentence. "
. "Here comes the sun, do de do de do.\n"
. " This is a new paragraph.\n"
. " This is another newer, longer, better "
. "paragraph. It is coming to an end, "
. "unfortunately." );
$label->set_justify( 'fill' );
$label->set_line_wrap( $true );
$frame->add( $label );
$vbox->pack_start( $frame, $false, $false, 0 );
$frame = new Gtk::Frame( "Underlined label" );
$label = new Gtk::Label( "This label is underlined!\n"
. "This one is underlined in quite a funky
fashion");
$label->set_justify( 'left' );
$label->set_pattern( "_________________________ _ _________ "
. "_ ______ __ _______ ___");
$frame->add( $label );
$vbox->pack_start( $frame, $false, $false, 0 );
$window->show_all();
main Gtk;
exit( 0 );
Вставить скриншот
Сепараторы
Иерархия наследования
Object
+--- Widget
+--- Separators
Сепараторы являются самыми простоыми виджетами. Это всего-лишь линии с тенью на воне общего виджета. Существуют два типа вертикальные и горизонтальные:
$hseparator = new Gtk::HSeparator();
$vseparator = new Gtk::VSeparator();
Единственное только то, что сепараторы не используются как разделители меню. В качестве разделителя тут используется пустое MenuItem.
Выравнивание
Иерархия наследования
Object
+--- Data
+--- Adjustment
Gtk имеют несколько типов виджетов, которые могут быть визуально расставлены пользователем при помощи клавиатуры и мыши, подобно range widgets, описанных в соответствующей главе. Есть так-же несколько виджетов, которые показывают показ текста или иного вида данных в соответствии с размером облисти их отображения. Например text widget или viewport widget.
Очевидно, что приложение должно уметь реагировать на изменения, которые пользователь вносит в отображение виджета. Один путь для реализации этой концепции состоит в том, чтобы каждый виджет испускал собственный сигнал при изменении его размеров и любое изменение этого размера будет сопровождаться сопоставлением с данными внутри виждета и соответственно как-то это изменение отрабатывать для каждого виджета. Другойпуть заключается в том, чтобы изменение одного виджета провоцировало изменение других виджетов, то есть связанное изменение. Наиболее очевидным примером для этого может являться связка scrollbar-panning viewport или scrollbar-text area. В случае, когда каждый виджет отдельно обрабабатывает изменение своих размеров, разработчику необходимо связывать воедино изменения различных элементов так, чтобы они вели себя как единое целое.
Gtk решает эту проблему при помощи Adjustment object, который не является виджетом, но заставляет виджет хранить и передавать информацию в абстрактрой и гибкой форме. Примером такого реглирования является хранение конфигурационных параметров и их изменение в соответствии с виджетными размерами, например scrollbars и scale controls. Однако, так как регулирование наследуется из объекта, видоизменяемые виджеты имеют некоторые специфические возможности в отличие от нормальных структур данных. Наиболее важным в регулировании отображения виджетов является то, что такие свойства виджетов мугут выдавать сигналы, подобные выдаваемым виджетами при совершении над последними каких-то действий, и эти сигналы могут давать соответствующую регулировку для остальных виджетов(например в пропорциях между ними). К сожалению, выравнивание может быть довольно трудной концепцией в тех случаях, когда нет визуальных примеров, показывающих её дейтсвие например при работе виджетов, подобных progress bars, viewports, scrolled windows и им подобных.
Определение объекта, отвечающего за выравнивание
Некоторые виджеты в случае пользоватльского вмешательства видоизменяются пропорциональным образом автоматически, но в некоторых случаях(которые будутпоказаны позднее в примерах) операцию изменения приходится проделывать автоматически. Создать объект, отвечающий за такой тип взаимодействия между виджетами, можно при помощи функции Gtk::Adjustment():
new Gtk::Adjustment( $value,
$lower,
$upper,
$step_increment,
$page_increment,
$page_size );
Перемення $valie - начальное значение, которое необходимо сохранить при изменении элементов окна, оно обычно соответствует левому верхнему положению элементов. Переменная $lower является минимальным значением, которе будет изменятся в соответствии с парвилами всего Adjustment. Переменная $step_increment определяет минимальное значение, из двух приращений, которое может инициировать пользователь, соответственно переменная $page_increment является максимальным допустимым изменяемым значением. Переменная $page_size соответствует видимой части виджета. Переменная $upper используется для выбора, что изменять в первую очередь, нижнюю или правую часть дочернего отображаемого виджета. Поэтому она не обладает наибольшим значением которое моежт иметь $value.
Использование авторегуляции виджетов.
Виджеты описываемой группы могут быть грубо разделены на те, которые настраиваются разработчиками, и те, которые все "делают" автомтически. К автоподстраиваемым виджетам относятся скроллбары, скейлы, прогрессбары и кнопки прокрутки. Эти виджеты являются виджетами, которые автоматически подстраивают свои размеры в соответствии с действиями пользователя.
Другая группа виджетов включает в себя text widget, viewport, CList и scrolles window. Все они используют попиксельное позиционирование. Также эти виджеты ковенно используют позиционирование при помощи скроллбаров.
Нижеследующий английский текст переводчик до конца не понял и будет благодарен за правильный его перевод
While all widgets which use adjustments can either create their own adjustments or use ones you supply, you'll generally want to let this particular category of widgets create its own adjustments. Usually, they will eventually override all the values except the value itself in whatever adjustments you give them, but the results are, in general, undefined (meaning, you'll have to read the source code to find out, and it may be different from widget to widget).
Now, you might be thinking, since text widgets and viewports insist on setting everything except the value of their adjustments, while scrollbars will only touch the adjustment's value, if you share an adjustment object between a scrollbar and a text widget, will manipulating the scrollbar automagically adjust the text widget? Of course it will! Just like this:
# creates its own adjustments
$text = new Gtk::Text( "", "" );
# uses the newly-created adjustment for the scrollbar as well
$vscrollbar = new Gtk::VScrollbar( $text->vadj );
Внутреннее регулирование
Если необходимо создать собственный механизм регулирования взаимного (пере- ?)расположения виджетов, то в Gtk-Perl возможно было бы использовать
get_adjustment->adjustment_name
где adjustment_name любая величина из перечисленных value, lower, upper, step_increment, page_increment, или page_size. Если необходимо переопределить значение какого-либо вида выравнивания для всех виджетов одним махом, то пишется строчка:
$adjustment->set_value( $value );
Как было упомянуто ранее, регулирование может инициировать сигналы в случае, когда, например, изменяется значение для сроллбара и вместе с ним текст внутри окна, где действует скроллбар.
Различные виджеты, которые используют объект выравнивания, испускают сигнал при изменении значения переменных, ответственных за виджеты(возможно, неправилен смысл перевода). Например, если имеется скейл-виджет и необходимо повращать картинку всякий раз, когда изменяются значения, влияющие на выравнивание, то используется следующий код:
sub cb_rotate_picture
{
( $adjustment, $picture ) = @_;
$picture->rotation( $adjustment->get_adjustment->value );
...
}
и далее соединяемся со скейл-виджетом, ответственным за выравнивание примерно так:
$adjustment->signal_connect( "value_changed",
\&cb_rotate_picture,
$picture );
В слече, если пользователь добавляет текст к текстовому виджету, то меняются значения переменной upper или lower и испускается сигнал 'changed'.
Range widgets typically connect a handler to this signal, which changes their appearance to reflect the change - for example, the size of the slider in a scrollbar will grow or shrink in inverse proportion to the difference between the lower and upper values of its adjustment.
You probably won't ever need to attach a handler to this signal, unless you're writing a new type of range widget. However, if you change any of the values in a Adjustment directly, you should emit this signal on it to reconfigure whatever widgets are using it, like this:
$adjustment->emit_by_name( "changed" );
Виджеты диапазона
Иерархия наследования
Object
+--- Widget
+--- Range
Категория диапазона включает в себя наиболее часто встречающийся скроллбар-виджет и почти идентичный по своим действиям скейл-виджет. Весь спектр виджетов имеет общие графические элементы, в каждом из которых есть свое окно X-сисетмы, которое обменивается событиями о своем изменении. Все они содержат окно прокрутки и ползунок(иногда называемый thumbwheel в других GUI - графический пользовательский интерфейс). Соответственно положение ползунка можно изменять, либо кликать на полоске прокрутки(подобно тому, как это сделано при проигрывании mp3 в xmms или winamp). Согласно вышеописанному выравниванию, величина области, где бегает ползунок, пропорционально постраивается под значения переменных, свойственных для этого виджета.
Основные функции виджетов диапазона.
Класс виджетов диапазона довольно сложен внутренне, но, подобно всем базовым классам виджетов, большинство его особенностей представляют интерес для того, кто хочет сам программировать свойства классов. Почти все функции и исгналы являются специфическими для данного класса, но, тем не менее, имеется несколько широкоиспользуемых функций, которые работают для всх виджетов диапазона.
"update policy" определяет когда во время работы пользователя происходит изменение переменных, влияющих на выравнивание(относительное построение? - перевести кусок текста заново). Правила изменения
'continuous' - по умолчанию, сигнал 'value_changed' испускается непрерывно, даже при малейших изменениях ползунка.
'discontinuous' - 'value_changed' испускается, когда ползунок перемещен и кнопка манипулятора "МЫШЬ" отпущена.
'delayed' - 'value_changed' появляется, когда юзер отпускает кнопку мыши или когда ползунок неподвижен в течении какого-то короткого времени. Функция, с помощью которой можно переопределять эти свойства, выглядить так:
$range->set_update_policy( $policy );
Получение и установка диапазона на лету выполняется примерно так:
$range->get_adjustment();
$range->set_adjustment( $adjustment );
get_adjustment() возвращает выравнивание, с которым связана переменная $range and set_adjustment() does absolutely nothing if you pass it the adjustment that the Range is already using, regardless of whether you changed any of its fields or not. If you pass it a new Adjustment, it will unreference the old one if it exists (possibly destroying it), connect the appropriate signals to the new one, and call the private function adjustment_changed(), which will (or at least, is supposed to...) recalculate the size and/or position of the slider and redraw if necessary. As mentioned in the section on adjustments, if you wish to reuse the same Adjustment, when you modify its values directly, you should emit the "changed" signal on it, like this:
$adjustment->signal_emit( "changed" );
Все виджеты диапазона GTK реагируют на нажатие мышиной клавиши более или менее одинаково. Нажатие в области прокрутки соответственно изменяет значение page_increment вичитая или добавляя его к текущей величине. В соответствии с этими действиями так-же перемещается и бегунок(slider). Щелчок любой кнопкой мыши на стрелках полосы прокрутки(скроллбара) заставляет изменяться step_increment.
Скроллбары и скейл-виджеты в GTK могут менять фокус в соответствии с нажатием клавиш на клавиатуре. Если необходимо отключить фокусировку на виджете, то это можно сделать при помощи функции
$scrollbar->unset_flags( 'focus' );
(пропущено о том, что есть невеликие различия между горизонтальными и вертикальными виджетами)
Пример кода, который показывает действия описанных свойств виджетов
диапазона.
#!/usr/bin/perl -w
use Gtk;
use strict;
set_locale Gtk;
init Gtk;
my $false = 0;
my $true = 1;
my $hscale;
my $vscale;
my $window;
my $box1;
my $box2;
my $box3;
my $button;
my $scrollbar;
my $separator;
my $opt;
my $menu;
my $item;
my $label;
my $scale;
my $adj1;
my $adj2;
# Стандартное создание виджета X-window
$window = new Gtk::Window( "toplevel" );
$window->set_title( "range controls" );
$window->signal_connect( "destroy", sub { Gtk->exit( 0 ); } );
$box1 = new Gtk::VBox( $false, 0 );
$window->add( $box1 );
$box1->show();
$box2 = new Gtk::HBox( $true, 10 );
$box2->border_width( 10 );
$box1->pack_start( $box2, $true, $true, 0 );
$box2->show();
# value, lower, upper, step_increment, page_increment, page_size
#обратим внимание, что переменная page_size показывает разницу
#между скроллбар-виджетом и максимальным значением,
#которое получается после взаимодействия(еще раз перевести)
# Note that the page_size value only makes a difference for
# scrollbar widgets, and the highest value you'll get is actually
# (upper - page_size).
$adj1 = new Gtk::Adjustment( 0.0, 0.0, 101.0, 0.1, 1.0, 1.0 );
$vscale = new Gtk::VScale( $adj1 );
scale_set_default_values( $vscale );
$box2->pack_start( $vscale, $true, $true, 0 );
$vscale->show();
$box3 = new Gtk::VBox( $false, 10 );
$box2->pack_start( $box3, $true, $true, 0 );
$box3->show();
# Reuse the same adjustment
# повторное использование того-же самого выравнивания
$hscale = new Gtk::HScale( $adj1 );
$hscale->set_usize( 200, 30 );
scale_set_default_values( $hscale );
$box3->pack_start( $hscale, $true, $true, 0 );
$hscale->show();
# Reuse the same adjustment again
# еще одно повторное использование
$scrollbar = new Gtk::HScrollbar( $adj1 );
# сделать обновление мгновенным в соответствии с положением скроллбара
$scrollbar->set_update_policy( 'continuous' );
$box3->pack_start( $scrollbar, $true, $true, 0 );
$scrollbar->show();
$box2 = new Gtk::HBox( $false, 10 );
$box2->border_width( 10 );
$box1->pack_start( $box2, $true, $true, 0 );
$box2->show();
# A checkbutton to control whether the value is displayed or not
# Чекбокс, указывающий, показывать или нет значение переменной
$button = new Gtk::CheckButton( "Display value on scale widgets" );
$button->set_active( $true );
$button->signal_connect( "toggled", \&cb_draw_value );
$box2->pack_start( $button, $true, $true, 0 );
$button->show();
$box2 = new Gtk::HBox( $false, 10 );
$box2->border_width( 10 );
# An option menu to change the position of the value
# меню для выбора положения переменной
$label = new Gtk::Label( "Scale Value Position:" );
$box2->pack_start( $label, $false, $false, 0 );
$label->show();
$opt = new Gtk::OptionMenu();
$menu = new Gtk::Menu();
$item = make_menu_item( "Top", \&cb_pos_menu_select, 'top' );
$menu->append( $item );
$item = make_menu_item( "Bottom", \&cb_pos_menu_select, 'bottom' );
$menu->append( $item );
$item = make_menu_item( "Left", \&cb_pos_menu_select, 'left' );
$menu->append( $item );
$item = make_menu_item( "Right", \&cb_pos_menu_select, 'right' );
$menu->append( $item );
$opt->set_menu( $menu );
$box2->pack_start( $opt, $true, $true, 0 );
$opt->show();
$box1->pack_start( $box2, $true, $true, 0 );
$box2->show();
$box2 = new Gtk::HBox( $false, 10 );
$box2->border_width( 10 );
# Yet another option menu, this time for the update policy of the
# scale widgets
$label = new Gtk::Label( "Scale Update Policy:" );
$box2->pack_start( $label, $false, $false, 0 );
$label->show();
$opt = new Gtk::OptionMenu();
$menu = new Gtk::Menu();
$item = make_menu_item ("Continuous", \&cb_update_menu_select, 'continuous' );
$menu->append( $item );
$item = make_menu_item ("Discontinuous", \&cb_update_menu_select, 'discontinuous' );
$menu->append( $item );
$item = make_menu_item ("Delayed", \&cb_update_menu_select, 'delayed' );
$menu->append( $item );
$opt->set_menu( $menu );
$box2->pack_start( $opt, $true, $true, 0 );
$opt->show();
$box1->pack_start( $box2, $true, $true, 0 );
$box2->show();
$box2 = new Gtk::HBox( $false, 10 );
$box2->border_width( 10 );
# An HScale widget for adjusting the number of digits on the
# sample scales.
$label = new Gtk::Label( "Scale Digits:" );
$box2->pack_start( $label, $false, $false, 0 );
$label->show();
$adj2 = new Gtk::Adjustment( 1.0, 0.0, 5.0, 1.0, 1.0, 0.0 );
$adj2->signal_connect( "value_changed", \&cb_digits_scale );
$scale = new Gtk::HScale( $adj2 );
$scale->set_digits( 0 );
$box2->pack_start( $scale, $true, $true, 0 );
$scale->show();
$box1->pack_start( $box2, $true, $true, 0 );
$box2->show();
$box2 = new Gtk::HBox( $false, 10 );
$box2->border_width( 10 );
# And, one last HScale widget for adjusting the page size of the scrollbar
$label = new Gtk::Label( "Scrollbar Page Size:" );
$box2->pack_start( $label, $false, $false, 0 );
$label->show();
$adj2 = new Gtk::Adjustment( 1.0, 1.0, 101.0, 1.0, 1.0, 0.0 );
$adj2->signal_connect( "value_changed", \&cb_page_size, $adj1 );
$scale = new Gtk::HScale( $adj2 );
$scale->set_digits( 0 );
$box2->pack_start( $scale, $true, $true, 0 );
$scale->show();
$box1->pack_start( $box2, $true, $true, 0 );
$box2->show();
$separator = new Gtk::HSeparator();
$box1->pack_start( $separator, $false, $true, 0 );
$separator->show();
$box2 = new Gtk::VBox( $false, 10 );
$box2->border_width( 10 );
$box1->pack_start( $box2, $false, $true, 0 );
$box2->show();
$button = new Gtk::Button( "Quit" );
$button->signal_connect( "clicked", sub { Gtk->exit( 0 ); } );
$box2->pack_start( $button, $true, $true, 0 );
$button->can_default( $true );
$button->grab_default();
$button->show();
$window->show();
main Gtk;
exit( 0 );
### Subroutines
sub cb_pos_menu_select
{
my ( $item, $pos ) = @_;
# Set the value position on both scale widgets
$hscale->set_value_pos( $pos );
$vscale->set_value_pos( $pos );
}
sub cb_update_menu_select
{
my ( $item, $policy ) = @_;
# Set the update policy for both scale widgets
$hscale->set_update_policy( $policy );
$vscale->set_update_policy( $policy );
}
sub cb_digits_scale
{
my ( $adj ) = @_;
# Set the number of decimal places to which adj->value is rounded
$hscale->set_digits( $adj->value );
$vscale->set_digits( $adj->value );
}
sub cb_page_size
{
my ( $get, $set ) = @_;
# Set the page size and page increment size of the sample
# adjustment to the value specified by the "Page Size" scale
$set->page_size( $get->value );
$set->page_increment( $get->value );
# Now emit the "changed" signal to reconfigure all the widgets
# that are attached to this adjustment
$set->signal_emit_by_name( "changed" );
}
sub cb_draw_value
{
my ( $button ) = @_;
# Turn the value display on the scale widgets off or on depending
# on the state of the checkbutton
$hscale->set_draw_value( $button->active );
$vscale->set_draw_value( $button->active );
}
# Convenience functions
sub make_menu_item
{
my ( $name, $callback, $data ) = @_;
my $item;
$item = new Gtk::MenuItem( $name );
$item->signal_connect( "activate", $callback, $data );
$item->show();
return $item;
}
sub scale_set_default_values
{
my ( $scale ) = @_;
$scale->set_update_policy( 'continuous' );
$scale->set_digits( 1 );
$scale->set_value_pos( 'top' );
$scale->set_draw_value( $true );
}
# END EXAMPLE PROGRAM
(поместить скриншот)
Можно заметить, что программа не вызывает функцию signal_connect() для 'delete_event', но вызывает для сигнала 'destroy', так как необработанный сигнал 'Delete_event' будет завершен сигналом 'destroy', закрывающим окно.
Скроллбар-виджеты
Иерархия наследования
Object
+--- Widget
+--- Range
+--- Scrollbar
Этот наиболее часто используемый виджет может быть использован только для
прокрутки некоторых других виджетов, таких как список, лист или viewport.
В других случаях вы должны использовать скейл-виджеты в силу того, что они наиболее дружественные
и более характерные. Есть два различных вида скроллбаров, вертикальный и
горизонтальный, создаются такими функциями:
new Gtk::HScrollbar( $adjustment );
new Gtk::VScrollbar( $adjustment );
$adjustment может быть уже определен. Вравнивание может быть нулевым в
том случае, если вы хотите передать значение этой переменной из другого
виджета, тоесть наследовать.
Скейл-виджеты
Иерархия наследования
Object
+--- Widget
+--- Range
+--- Scale
Скейл-виджеты используются для того, чтобы позволить пользователю выбирать или управлять
значением переменной в пределах определенного диапазона. Вы можете
регулировать масштаб виджета, например для определения значения увеличения картинки
или для контроля яркости цвета или для определения времени задержки
до включения скринсервера. Как и в случае скроллбаров, существуют отдельные типы
вертикальных и горизонтальных виджетов. Нижеследующие функции определяют
вертикальные и горизонтальные виджеты:
new Gtk::VScale( $adjustment );
new Gtk::HScale( $adjustment );
Аргумент $adjustment может являться уже ранее созданным, или пустым, когда регулирование
было создано со значением 0. Скейл-виджеты диапазона могут показывать текущее значение
как число при помощи функции. По умлочанию это число показывается, и его можно
изменить при помощи функции
$scale->set_draw_value( $draw_value );
$draw_value может быть либо истиной либо ложью.
Значение показываемой переменной округляется до одного десятичного пункта, это значение
можно изменить следующим образом:
$scale->set_digits( $digits );
где $digits - число десятичных знаков, которое Вам необходимо. Можно устанавливать значение
$digits как угодно, но если оно больше 13, то будет происходить перерисовка экрана.
И, в конце значение может быть установлено в разные относительноые положения при
помощи функции
$scale->set_value_pos( $pos );
где аргумент $pos может принимать значения 'left', 'right', 'top', или 'bottom'. Если Вы помещаете
значение переменной на вершине или внизу скейл-виджета, то тогда виджет будет следовать
вверх или вниз при изменении размеро парента.
Часть 20. Виджеты состояния процесса
Содержание
Пример
Диалог подгружения
Иерархия наследования
Object
+--- Widget
+--- Progress
+--- ProgressBar
Виджеты состояния процесса используются для контроля протекания процесса. Они
довольно удобны, как и будет показано кодом ниже. Но сначала создадим
прогрессбар. Есть два пути создания диалога состояния, один без агрументов,
другой с аргументром выравнивания в соовтетствии с поведением окружения. Еси
используется прежний прогрессбар, то выравнивание будет выстроено в
соответствии с указанным ранее:
$progress = new Gtk::ProgressBar();
$progress = new Gtk::ProgressBar( $adjustment );
Второй метод имеет большие преимущества, так как в нем можно переопределить
или определить заново динамические размеры самого линейки состояния и другие
его параметры:
$progress-> set_adjustment ($adjustment);
Теперь, после создания полосы прокрутки, прогрессбар можно использовать:
$progress->update( $percentage );
Аргумент функции показывает предел заполнения полосы состояния от 0 до 100%
Соответственно функция должна принимать значения от 0.0 до 1.0. Полоса
состояния может быть ориентирована при помощи функции
$progress->set_orientation( $orientation );
где аргумент $orientation, принимает следующие значения:
'left_to_right'
'right_to_left'
'bottom_to_top'
'top_to_bottom'
Вид увеличения полоски состояния может быть определен функцией
$progress->set_bar_style( $style );
в которой аргумент $style может приниметь два значения 'continuous' или
'discrete'. 'continuous' подразумевает непрерывное изменение полоски
состояния, 'discrete' - дискретное. Функцией
$progress->set_discrete_blocks( $blocks );
можно задать число дискрентых блоков виджета состояния. Функция
$progress->set_activity_mode( $activity_mode );
позволяет изменять поведение прогрессбара в том случае, когда идет
уменьшение результата какого-либо процесса. Размер шага актовного индикатора
и число блоков в случае дискретного увеличения может быть установлено при
помощи следующих функций:
$progress->set_activity_step( $step );
$progress->set_activity_blocks( $blocks );
Иногда бывает необходимо показать значения, определяющие продвижение
процесса к конечной цели. Полоса состояния позволяет это сделать в пределах
прогрессбара при помощи функции:
$progress->set_format_string( $format );
где аргумент $format подобен printf и может быть представлен как:
$progress->set_show_text( $show_text );Положение текста на прогрессбаре может быть фиксировано при помощи функции:
$progress->set_text_alignment( $x_align, $y_align );в которой аргументы $x_align и $y_align принимают значения между 0.0 и 1.0 Состояние прогрессбара может быть определено при помощи текущего или вновь определяемого выравнивания при помощи двух нижепреведенных функций, возвращающих форматированную строку, которая может быть показана на прогрессбаре:
$progress-> get_current_text (); $progress-> get_text_from_value ($value);тоже самое можно сделать при помощи другой функции:
$progress->configure( $value, $min, $max );Эта функция обеспечивает довольно простой интерфейс для установления значений диапазона и значения прогрессбара. Оставшиеся функции используются для установления значения переменной, отвечающей за уровень прогрессбара в различных типах и форматах:
$progress->set_percentage( $percentage ); $progress->set_value( $value ); $progress->get_value(); $progress->get_current_percentage(); $progress->get_percentage_from_value( $adjustment );Здесь проследняя функция использует текущее выравнивание для запроса текущего значения переменной, отвечающей за состояние выполнения какого-либо процесса.
Индикаторы состояния процесса используются с таймаутами или другими подобными функциями с тем, чтобы создать иллюзию мультзадачности(??). Все они используют функцию update();
Пример индикатора состояния
Нижеследующий пример показывает прогрессбар, изменяющийся при помощи
таймаутов, так же пример показывает, как можно переустановить прогрессбар:
#!/usr/bin/perl -w
use Gtk;
use strict;
set_locale Gtk;
init Gtk;
my $false = 0;
my $true = 1;
my ($window, $pbar, $timer, $align, $separator, $table, $adj, $button, $check1, $check2, $vbox);
# Создаем окно
$window = new Gtk::Window( "toplevel" );
$window->set_policy( $false, $false, $true );
$window->signal_connect( "destroy", sub { Gtk->exit( 0 ); } );
$window->set_title( "Progress Bar" );
$window->border_width( 0 );
$vbox = new Gtk::VBox( $false, 5 );
$vbox->border_width( 10 );
$window->add( $vbox );
$vbox->show();
# Создаем центрированый объект
$align = new Gtk::Alignment( 0.5, 0.5, 0, 0 );
$vbox->pack_start( $align, $false, $false, 5 );
$align->show();
# Создаем выровненный объект, содержащий уровень прогрессбара(???)
$adj = new Gtk::Adjustment( 0, 1, 150, 0, 0, 0 );
# создаем GtkProgressBar, использующий выравнивание
$pbar = new_with_adjustment Gtk::ProgressBar( $adj );
# Устанавливаем формат строки, который может быть показан на индикаторе состояния
# %p - проценты
# %v - значение
# %l - нижний предел
# %u - верхний предел
$pbar->set_format_string( "%v from [%l-%u] (=%p%%)" );
$align->add( $pbar );
$pbar->show();
# Добавляем таймер, который будет запрашивать значение переменной прогрессбара
$timer = Gtk->timeout_add( 100, \&progress_timeout );
$separator = new Gtk::HSeparator();
$vbox->pack_start( $separator, $false, $false, 0 );
$separator->show();
# ряды и колонки, похожести(homogeneous)
$table = new Gtk::Table( 2, 3, $false );
$vbox->pack_start( $table, $false, $true, 0 );
$table->show();
# Add a check button to select displaying of the trough text
# Добавляем кнопку типа select для выбора моды показа или скрытия текста на
# индикаторе состояния процесса
$check1 = new Gtk::CheckButton( "Show text" );
$table->attach( $check1, 0, 1, 0, 1, [ 'expand', 'fill' ],
['expand', 'fill' ], 5, 5 );
$check1->signal_connect( "clicked", sub {
$pbar->set_show_text( $check1->active ); } );
$check1->show();
# Add a check button to toggle activity mode
# Добавляем чекбокс, ответственный за активирование моды
$check2 = new Gtk::CheckButton( "Activity mode" );
$table->attach( $check2, 0, 1, 1, 2, [ 'expand', 'fill' ],
[ 'expand', 'fill' ], 5, 5 );
$check2->signal_connect( "clicked", sub {
$pbar->set_activity_mode( $check2->active ); }
);
$check2->show();
$separator = new Gtk::VSeparator();
$table->attach( $separator, 1, 2, 0, 2, [ 'expand', 'fill' ],
[ 'expand', 'fill' ], 5, 5 );
$separator->show();
# Добавляем радиокнопку, ответственную за непрерывное изменение индикатора
$button = new Gtk::RadioButton( "Continuous" );
$table->attach( $button, 2, 3, 0, 1, [ 'expand', 'fill' ],
[ 'expand', 'fill' ], 5, 5 );
$button->signal_connect( "clicked", sub {
$pbar->set_bar_style( 'continuous' ); } );
$button->show();
# Добавляем радиокнопку, ответственную за дискретное изменение индикатора
$button = new Gtk::RadioButton( "Discrete", $button );
$table->attach( $button, 2, 3, 1, 2, [ 'expand', 'fill' ],
[ 'expand', 'fill' ], 5, 5 );
$button->signal_connect( "clicked", sub {
$pbar->set_bar_style( 'discrete' ); } );
$button->show();
$separator = new Gtk::HSeparator();
$vbox->pack_start( $separator, $false, $false, 0 );
$separator->show();
# Кнопка выхода из программы
$button = new Gtk::Button( "Close" );
$button->signal_connect( "clicked", sub { Gtk->exit( 0 ); } );
$vbox->pack_start( $button, $false, $false, 0 );
# Устанавливаем кнопку выхода по дефолту
$button->can_default( $true );
# захват события и постановка ему в соответствие по дефолту,
# например нажатие кнопки "Enter" завершит программу.
$button->grab_default();
$button->show();
$window->show();
main Gtk;
exit( 0 );
### подпрограммы
# таймер, запрашивающий изменение прогрессбара.
sub progress_timeout
{
my ( $widget ) = @_;
my $new_val;
my $adj;
# Вычисление значения индикатора используюя значение переменной
# диапазона, определенной как выравненный объект(adjustment object)
$new_val = $pbar->get_value() + 1;
$adj = $pbar->adjustment;
$new_val = $adj->lower if ( $new_val > $adj->upper );
# Установка нового значения
$pbar->set_value( $new_val );
return ( $true );
}
Пример диалога подгружения html-страницы
#!/usr/bin/perl -w
use Gtk;
use strict;
set_locale Gtk;
init Gtk;
my $true = 1;
my $false = 0;
my ($command, $site, $dir, $file, $value, $signal, $window, $button, $vbox, $label, $adj, $pbar);
die "Этой программе необходим wget\n" if ( `which wget` =~ /^\s*$/ );
# Создаем окно
$window = new Gtk::Window( 'toplevel' );
$signal = $window->signal_connect( 'delete_event', sub { Gtk->exit( 0 ); });
$window->border_width( 15 );
$vbox = new Gtk::VBox( $false, 0 );
$window->add( $vbox );
# Ярлык, информирующий пользователя о том, на что он идет
$label = new Gtk::Label( "Downloading Gtk-Perl Tutorial" );
$vbox->pack_start( $label, $false, $false, 10 );
$label->show();
# Определение прогрессбара
$adj = new Gtk::Adjustment( 0, 1, 100, 0, 0, 0 );
$pbar = new_with_adjustment Gtk::ProgressBar( $adj );
$vbox->pack_start( $pbar, $false, $false, 10 );
$pbar->set_format_string( "%p%%" );
$pbar->set_show_text( 1 );
$pbar->set_value( 0 );
$pbar->show();
$vbox->show();
# Runs the main loop as long as events are pending
# Запуск основной части программы(???)
Gtk->main_iteration while ( Gtk->events_pending );
$window->show();
# Установки wget
$command = "wget --dot-style=micro";
$site = "http://personal.riverusers.com";
$dir = "/~swilhelm/download/";
$file = "gtkperl-tutorial.tar.gz";
# Открытие временного сокета для перехвата STDOUT wget
open TMP, "$command $site$dir$file 2>&1 |";
while ( $value =
Виджеты для редакции
Иерархия наследования
Object
+--- Widget
+--- Editable
Виджеты редактирования - базовый класс всех виджетов этого типа. Этот класс
не нуждается в применении функции new() и только обеспечивает обычные
функциональные возможности к тексту widgets. Все виджеты, в которых можно
редактировать текст, позволяют выделять область текста при помощи функции:
$editable->select_region( $start, $end );
где выделенный текст содержит те символы, которые отмечены с $start и до(не
включая) $end. Если $end отрицательно, то происходит обратный отсчет с конца
текста.
Текст может быть вставлен на определенную позицию при помощи функции
$editable->insert_text( $new_text, $position );
$new_text - текст, который вставляется, $position - позиция, начиная от
которой происходит вставление текста.
Символы могут быть удалены при помощи функции
$editable->delete_text( $start, $pos );
где $start - начальная позиция удаляемого текста и $pos - конечная позиция
удаляемого текста. Если $pos < 0, тогда отсчет удаляемых символов ведется от
конца текста.
Вытащить текст из положения "от" и "до" можно при помощи функции
$editable->get_chars( $start, $end );
Чтобы взять весь текст, находящийся в виджете нужно использовать
$editable->get_chars( 0, -1 );
Если текст выделен, то его можно скопировать в клипбоард при помощи функции
$editable->cut_clipboard();
При копировании текста в клипбоард берутся выделенные символы, помещаются в
клипбоарде и только после этого удаляются из виджета.
Текст в клипбоарде модет быть вставлен в виджет при помощи
$editable->paste_clipboard();
текст будет вставлен в месте, где находится курсор.
Для удаления текста используется функция
$editable->delete_selection();
Положение курсора может быть установлено или изменено при помощи функций
$editable->get_position();
$editable->set_position( $position );
Текстовый виджет может находится в двух состояниях "для чтения" и "для
редакции", эти состояния определяются функцией
$editable-> set_editable ($is_editable);
где $is_editable принимает значения "истина" или "ложь".
Текстовые редактируемые виджеты имеют множество сигналов:
'changed'
'insert-text'
'delete-text'
'activate'
'set-editable'
'move-cursor'
'move-word'
'move-page'
'move-to-row'
'move-to-column'
'kill-char'
'kill-word'
'kill-line'
'cut-clipboard'
'copy-clipboard'
'paste-clipboard'
Как работают эти сигналы - очевидно из их названия, если у Вас возникнут
вопросы относительно их применения - читайте описание Gtk. Например чтобы
посать сигнал 'changed' необходимо вызвать функцию $editable->changed().
Виджеты ввода
Иерархия наследования
Object
+--- Widget
+--- Editable
+--- Entry
Виджеты ввода позволяют напечатать и показать текст в одну строку. The text
may be set with function calls that allow new text to replace, prepend or
append the current contents of the Entry widget.
Две функции для создания текствых полей ввода:
$entry = new Gtk::Entry();
$entry = new Gtk::Entry( $max_length );
Первая функция создает новый виджет ввода, вторая функция делает то-же
самое, за исключением того, что ограничивает число символов, вводиммых
пользователем до значения, передаваемого аргуметом $max_length.
Несколько функций для манипуляций над текстом, находящимся в виджете:
$entry-> set_text ($text);
$entry-> append_text ($text);
$entry-> prepend_text ($text);
Функция set_text() устанавливает содержимое виджета, меняя его на текущее
содержимое. append_text() и prepend_text() добавляют текст к содержимому
виджета.
Для скрытия вводимого текста(в случае ввода пароля) можно использовать
функцию
$entry-> set_visibility ($visible);
Для контроля того, что делте с виджетом пользователь, нужно отлавливать
соответствующие сигналы(см. документацию).
Пример использования виджета. позволяющего вводить текст:
#!/usr/bin/perl -w
use Gtk;
use strict;
set_locale Gtk;
init Gtk;
my $false = 0;
my $true = 1;
my $window;
my $vbox;
my $hbox;
my $entry;
my $button;
my $check;
# Создаем окно
$window = new Gtk::Window( "toplevel" );
$window->set_usize( 200, 100 );
$window->set_title( "GTK Entry" );
$window->signal_connect( "delete_event", sub { Gtk->exit( 0 ); } );
$vbox = new Gtk::VBox( $false, 0 );
$window->add( $vbox );
$vbox->show();
# создаем поле ввода
$entry = new Gtk::Entry( 50 );
$entry->signal_connect( "activate", \&enter_callback, $entry );
$entry->set_text( "Hello" );
$entry->append_text( "World" );
$entry->select_region( 0, length( $entry->get_text() ) );
$vbox->pack_start( $entry, $true, $true, 0 );
$entry->show();
$hbox = new Gtk::HBox( $false, 0 );
$vbox->add( $hbox );
$hbox->show();
# создаем чекбокс, который определяет, будет ли поле ввод редактируемым
$check = new Gtk::CheckButton( "Editable" );
$hbox->pack_start( $check, $true, $true, 0 );
$check->signal_connect( "toggled", \&entry_toggle_editable, $entry );
$check->set_active( $true );
$check->show();
# создаем чекбокс, который определяет, будет ли введенный текст видимым
$check = new Gtk::CheckButton( "Visible" );
$hbox->pack_start( $check, $true, $true, 0 );
$check->signal_connect( "toggled", \&entry_toggle_visibility, $entry );
$check->set_active( $true );
$check->show();
# создаем кнопку выхода
$button = new Gtk::Button( "Close" );
$button->signal_connect( "clicked", sub { Gtk->exit( 0 ); } );
$vbox->pack_start( $button, $true, $true, 0 );
$button->can_default( $true );
$button->grab_default();
$button->show();
$window->show();
main Gtk;
exit( 0 );
### подпрограммы
# Callback that is called when the enter key is pressed and the Entry
# widget has the focus. It prints out the text in the entry widget.
sub enter_callback
{
my ( $widget, $entry ) = @_;
my $entry_text = $entry->get_text();
print( "Entry contents: $entry_text\n" );
}
# Callback to toggle the editable property of the entry widget.
sub entry_toggle_editable
{
my ( $checkbutton, $entry ) = @_;
$entry->set_editable( $checkbutton->active );
}
# Callback to toggle the visible property of the entry widget.
sub entry_toggle_visibility
{
my ( $checkbutton, $entry ) = @_;
$entry->set_visibility( $checkbutton->active );
}
Текстовый виджет
Содержание
Создание и конфигурация текстового бокса
Манипуляции с текстом
Клавиатурное шаманство
Пример текстового виджета
Текстовый виджет поволяет показывать и редактировать многострочный текст. Он также поддерживает цветной текст и различные фонты и может смешивать эти фонты в различных комбинациях. Также этот виджет имеет много команд, совместимых с редактором Emacs.
Создание и конфигурирование текстового бокса.
Есть только одна функция для создания текстового виджета:
$text = new Gtk::Text( $hadj, $vadj );
The arguments allow us to give the Text widget adjustments that can be used
to track the viewing position of the widget. Passing undefined values to
either or both of these arguments will cause the new() function to create
its own.
$text->set_adjustments( $hadj, $vadj );
The above function allows the horizontal and vertical adjustments of a text
widget to be changed at any time. Текстовый виджет не будет автоматически
создавать линейки прокрутки в случае, когда текст выходит за границы
виджета. Вобщем эти линейки надо создавать самостоятельно:
$vscrollbar = new Gtk::VScrollbar( $text->vadj );
$hbox->pack_start( $vscrollbar, $false, $false, 0 );
$vscrollbar->show();