Chapter 24. Виджеты накрутки

Иерархия наследования

Object
   +--- Widget
         +---  Editable
               +---  Entry
                     +--- SpinButton
         

Виджет накрутки используется для того, чтобы пользователь мог выбрать значение из какого-то определенного диапазона. Он состоит из тектового бокса со стрелочками, позволяющими при нажатии на них увеличивать или уменьшать значение числа в текстовом боксе. В текстовом боксе также можно вручную отредактировать числовое значение.

Виджет накрутки может иметь нулевое значение или дробные значения и в зависимости от времени удержания инкремента/декремента скорость прибавления увеличивается.

Виджет накрутки использует выравнивание чтобы сохранять информацию о диапазоне значений, в котором находится значение текстового поля.

Вспомните, что виджет диапазона объявляется следующей функцией:

$adj = new Gtk::Adjustment( $value,
                            $lower,
                            $upper,
                            $step_increment,
                            $page_increment,
                            $page_size );

Аттрибуты диапазона используются виджетом накрутки в таком виде:

$value

Начальное значение виджета накрутки.

$lower

Минимальное значение.

$upper

Максимальное значение.

$step_increment

Значение инкремента/декремента когда удерживается мышиная кнопка 1.

$page_increment

Значение инкремента/декремента в случае нажатия кнопки 2.

$page_size

Не используется.

Третья кнопка может использоваться дл того, чтобы увеличивать значения накрутчика в максимальное и минимальное значения, $upper или $lower соответственно. Накрутчик можно создать следующим образом:

$spin = new Gtk::SpinButton( $adjustment, $climb_rate, $digits );

Переменная $climb_rate принимает значения между 0.0 и 1.0 и показывает величину изменения скорости увеличения значения в текстовом боксе накрутчика. Переменная $digits определяет число десятичных долей, которые будут выведены в спине.

Накрутчик(Spin Button) может быть повторно создан при помощи следующей функции

$spin->configure( $adjustment, $climb_rate, $digits );

Сохранение пропорций может быть установлено или восстановлено при помощи независимого использования двух функций

$spin->set_adjustment( $adjustment );

$spin->get_adjustment();

Число десятичных позиций также может быть изменено при помощи функции

$spin->set_digits( $digits );

Значение переменной накрутчика может быть изменено при помощи функции

$spin->set_value( $value );

Текущее значение накрутчика может быть восстановлено в виде значения с плавающей запятой или целочисленно использя функцию

$spin->get_value_as_float();

$spin->get_value_as_int();

Если необходимо изменить значение накрутчика, то это возможно при помощи следующей функции:

$spin->spin( $direction, $increment );

Параметр $direction может принимать одно из приведенных значений

'forward'
'backward'
'page_forward'
'page_backward'
'home'
'end'
'user_defined'

Эта функция несет в себе мало функциональных возможностей, которые я(автор tutorial) попытаюсь наиболее хорошо объяснить. Многие из установок используют настройки выравнивания(Adjustment object), которые связаны с кнопкой накрутки.

'forward' и 'backward' изменяют величину накрутчика значением, указанным в $increment, если $increment не равен 0, когда значение изменено $step_increment в настройках выравнивания.

'page_forward' и 'page_backward' просто изменяют значение накрутчика при помощи $increment.

'home' Устанавливает значение накрутчика в положение, соответствующее значению выравнивания(Adjustments).

'end' Устанавливает значение накрутчика в положение, соответствующее максимальному значению выравнивания(Adjustments).

'user_defined' изменяет значение накрутчика на нужную величину.

Тепрерь перейдем от функций к установке и доставке признаков диапазона накрутчика и функциям, ответственным за отрисовку и поведение накрутчика непосредственно.

Первая из функций используется для того, чтобы задавать размеры текстового поля виджета вплоть до того, что текстовое поле виджета ограничится только цифрой, показывающей значение виджета. Это необходимо для того, чтобы пользователь не мог ввести ничего, кроме цифр:

$spin->set_numeric( $numeric );

Вы можете установить свойство накрутчика выравниваться в зависимости от положения виджета между верхним и нижним значениями диапазона при помощи следующей функции:

$spin->set_wrap( $wrap );

Также можно заставить накрутчика округлять значения к ближайшему step_increment , который устанавливается в соответствии с базовым выравниванием(Adjustment object) для накрутчика. Это можно сделать с помощью следующей функции:

$spin->set_snap_to_ticks( $snap_to_ticks );

Изменить правила поведения накрутчика можно при помощи нижеприведенной функции

$spin->set_update_policy( $policy );

Возможные значения $policy принимают одно из двух вариантов: 'always' или 'if_valid'.

Эти политики определяют поведение накрутчика, разбирая вставленный текст и сопоставляя необходимым образом его со значениями базовой политики выравнивания.

В случае 'if_valid' накрутчик только оценивает текст, если введенный текст является числовым и лежит в пределах определенных общей для всех виджетов приложения политикой выравнивания. В противном случае текст переустанавливается в текущее значение.

В случае 'update_always' мы игнорируем ошибки в процессе конверации текста в числовое значение.

Появление кнопок, необходимых для изменения значения накрутчика возможно при помощи сприведенной функции:

$spin->set_shadow_type( $shadow_type );

Как обычно $shadow_type может быть одной из

'in'
'out'
'etched_in'
'etched_out'

В заключении можно заставить обновляться накрутчик непосредственно при изменении:

$spin->update();

24.1. Пример работы накрутчика

Исходник

#!/usr/bin/perl -w use Gtk ; use strict ; set_locale Gtk; init Gtk; my $false = 0; my $true = 1; my $spinner1; my $window; my $frame; my $hbox; my $main_vbox; my $vbox; my $vbox2; my $spinner2; my $spinner; my $button; my $label; my $val_label; my $adj; # Создаем панель $window = new Gtk::Window( "toplevel" ); $window->signal_connect( "destroy", sub { Gtk-> exit ( 0 ); } ); $window->set_title( "Spin Button" ); $main_vbox = new Gtk::VBox( $false, 5 ); $main_vbox->border_width( 10 ); $window->add( $main_vbox ); # Создаем фрейм для неускоренного прокрутчика $frame = new Gtk::Frame( "Not accelerated" ); $main_vbox->pack_start( $frame, $true, $true, 0 ); $vbox = new Gtk::VBox( $false, 0 ); $vbox->border_width( 5 ); $frame->add( $vbox ); # День, месяц и год $hbox = new Gtk::HBox( $false, 0 ); $vbox->pack_start( $hbox, $true, $true, 5 ); $vbox2 = new Gtk::VBox( $false, 0 ); $hbox->pack_start( $vbox2, $true, $true, 5 ); $label = new Gtk::Label( "Day :" ); $label->set_alignment( 0, 0.5 ); $vbox2->pack_start( $label, $false, $true, 0 ); $adj = new Gtk::Adjustment( 1.0, 1.0, 31.0, 1.0, 5.0, 0.0 ); $spinner = new Gtk::SpinButton( $adj, 0, 0 ); $spinner->set_wrap( $true ); $spinner->set_shadow_type( 'out' ); $vbox2->pack_start( $spinner, $false, $true, 0 ); $vbox2 = new Gtk::VBox( $false, 0 ); $hbox->pack_start( $vbox2, $true, $true, 5 ); $label = new Gtk::Label( "Month :" ); $label->set_alignment( 0, 0.5 ); $vbox2->pack_start( $label, $false, $true, 0 ); $adj = new Gtk::Adjustment( 1.0, 1.0, 12.0, 1.0, 5.0, 0.0 ); $spinner = new Gtk::SpinButton( $adj, 0, 0 ); $spinner->set_wrap( $true ); $spinner->set_shadow_type( 'etched_in' ); $vbox2->pack_start( $spinner, $false, $true, 0 ); $vbox2 = new Gtk::VBox( $false, 0 ); $hbox->pack_start( $vbox2, $true, $true, 5 ); $label = new Gtk::Label( "Year :" ); $label->set_alignment( 0, 0.5 ); $vbox2->pack_start( $label, $false, $true, 0 ); $adj = new Gtk::Adjustment( 1998.0, 0.0, 2100.0, 1.0, 100.0, 0.0 ); $spinner = new Gtk::SpinButton( $adj, 0, 0 ); $spinner->set_wrap( $false ); $spinner->set_shadow_type( 'in' ); $spinner->set_usize( 55, 0 ); $vbox2->pack_start( $spinner, $false, $true, 0 ); # создаем фрейм для обновляющихся накрутчиков $frame = new Gtk::Frame( "Accelerated" ); $main_vbox->pack_start( $frame, $true, $true, 0 ); $vbox = new Gtk::VBox( $false, 0 ); $vbox->border_width( 5 ); $frame->add( $vbox ); $hbox = new Gtk::HBox( $false, 0 ); $vbox->pack_start( $hbox, $false, $true, 5 ); $vbox2 = new Gtk::VBox( $false, 0 ); $hbox->pack_start( $vbox2, $true, $true, 5 ); # Создаем ускоренные накрутчики $label = new Gtk::Label( "Value :" ); $label->set_alignment( 0, 0.5 ); $vbox2->pack_start( $label, $false, $true, 0 ); $adj = new Gtk::Adjustment( 0.0, -10000.0, 10000.0, 0.5, 100.0, 0.0 ); $spinner1 = new Gtk::SpinButton( $adj, 1.0, 2 ); $spinner1->set_wrap( $true ); $spinner1->set_usize( 100, 0 ); $vbox2->pack_start( $spinner1, $false, $true, 0 ); $vbox2 = new Gtk::VBox( $false, 0 ); $hbox->pack_start( $vbox2, $true, $true, 5 ); $label = new Gtk::Label( "Digits :" ); $label->set_alignment( 0, 0.5 ); $vbox2->pack_start( $label, $false, $true, 0 ); $adj = new Gtk::Adjustment( 2, 1, 5, 1, 1, 0 ); $spinner2 = new Gtk::SpinButton( $adj, 0.0, 0 ); $spinner2->set_wrap( $true ); $adj->signal_connect( "value_changed", \&change_digits, $spinner2 ); $vbox2->pack_start( $spinner2, $false, $true, 0 ); $hbox = new Gtk::HBox( $false, 0 ); $vbox->pack_start( $hbox, $false, $true, 5 ); $button = new Gtk::CheckButton( "Snap to 0.5-ticks" ); $button->signal_connect( "clicked", \&toggle_snap, $spinner1 ); $vbox->pack_start( $button, $true, $true, 0 ); $button->set_active( $true ); $button = new Gtk::CheckButton( "Numeric only input mode" ); $button->signal_connect( "clicked", \&toggle_numeric, $spinner1 ); $vbox->pack_start( $button, $true, $true, 0 ); $button->set_active( $true ); $val_label = new Gtk::Label( " " ); $hbox = new Gtk::HBox( $false, 0 ); $vbox->pack_start( $hbox, $false, $true, 5 ); $button = new Gtk::Button( "Value as Int" ); $button->set_user_data( $val_label ); $button->signal_connect( "clicked", \&get_value, $spinner1, 1 ); $hbox->pack_start( $button, $true, $true, 5 ); $button = new Gtk::Button( "Value as Font" ); $button->set_user_data( $val_label ); $button->signal_connect( "clicked", \&get_value, $spinner1, 2 ); $hbox->pack_start( $button, $true, $true, 5 ); $vbox->pack_start( $val_label, $true, $true, 0 ); $val_label->set_text( "0" ); $hbox = new Gtk::HBox( $false, 0 ); $main_vbox->pack_start( $hbox, $false, $true, 0 ); $button = new Gtk::Button( "Close" ); $button->signal_connect( "clicked", sub { Gtk-> exit ( 0 ); } ); $hbox->pack_start( $button, $true, $true, 5 ); $window->show_all(); main Gtk; exit ( 0 ); ### Subroutines # Toggle whether text entry should snap to the tick values sub toggle_snap { my ( $widget, $spin ) = @_; $spin->set_snap_to_ticks( $widget->active ); } # Toggle whether only numeric input is allowed sub toggle_numeric { my ( $widget, $spin ) = @_; $spin->set_numeric( $widget->active ); } # Set the number of digits displayed after the decimal point sub change_digits { my ( $widget, $spin ) = @_; $spinner1->set_digits( $spin->get_value_as_int() ); } # Get the value of the spinner and put in in a label sub get_value { my ( $widget, $spin, $num ) = @_; my $buf = " "; my $label; $label = new Gtk::Label( $widget->get_user_data() ); if ( $num == 1 ) { $buf = $spin->get_value_as_int(); } else { $buf = $spin->get_value_as_float(); } $val_label->set_text( $buf ); } # END EXAMPLE PROGRAM

Скриншот с накрутчиками