July 05, 2001
Этот документ описывает Gtk-Perl-интерфейс для Gimp Toolkit (Gtk). Английская версия GTK+ Tutorial написана Tony Gale и Ian Main. Если Вы обнаружили какие-либо ошибки, имеете какие-либо вопросы или слова благодраности - пишите мне по адресу <swilhelm@computer.org>.
Если Вы хотите загрузить документ для чтения в оффлайне - то вам сюда.
Перевод Дмитрий Кувшинов aka Vilfred и Вадим Суханов aka Light Elf
Дальше | ||
Введение |
The GTK (GIMP Toolkit) is a library for creating graphical user interfaces. It is licensed using the LGPL license, so you can develop open software, free software, or even commercial non-free software using GTK without having to spend anything for licenses or royalties.
It's called the GIMP Toolkit because it was originally written for the GNU Image Manipulation Program (GIMP), but GTK has been used in a large number of software projects, including the GNU Network Object Model Environment (GNOME) project. GTK is built on top of the GDK (GIMP Drawing Kit) which is basically a wrapper around the low-level functions for accessing the underlying windowing functions (Xlib in the case of the X windows system).
Despite being written completely in C, GTK is essentially an object oriented API. GTK is implemented using the idea of classes and callbacks (pointers to functions). One advantage to having the library written in C is that most languages are able to interface with C libraries, making GTK available to several languages, including C++, Perl, Python, Eiffel, and many more (see the GTK Home Page for a more complete list).
Perl is a scripting language designed to make the simple things easy, and the hard things possible. If you are new to Perl, I highly recommend both Learning Perl and Programming Perl by O'reilly and Associates.
Иерархия наследования
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" );
The chapters are there to provide administrative information such as information about how to contribute to this tutorial and what you need to know if you want to copy, modify, or translate the tutorial.
Описание Gtk-Perl | ||
---|---|---|
Предыдущая | Следующая |
Виджет позиционирования позволяет вам устанавливать необходимый вижет в пределах панели, на которой он отображается, относительно непосредственного размера окна. Например очень часто бывает необходимо поставить виджет в пределах панели, на которой он отображается.
Есть только две функции, связанные с рассматриваемым виджетом:
$alignment = new Gtk::Alignment( $xalign, $yalign, $xscale, $yscale
);
$alignment->set( $xalign, $yalign, $xscale, $yscale );
Первая функция создает новый виждет выравнивания с задаваемыми параметрами. Вторая функция позволяет переопределять атрибуты ранее заданного виджета.
Все четыре параметра - числа с плавающей запятой, которые изменяются от 0.0 до 1.0. Параметры $xalign и $yalign касаются виджета, помещенного в пределах виджета выравнивания. Параметры $xscale и $yscale касаются воздействия и количествоа области, отдаваемой виджету.
Дочерний виджет может быть добавлен на виджет выравнивания при помощи
функции:
$alignment->add( $child_widget );
Пример работы виджета выравнивания, смотрите на виджете, контролирующем состояние протекания какого либо процесса.
Предыдущий | На главную | Следующий |
Область событий | Up | Уровень прокрутки |
Описание Gtk-Perl | ||
---|---|---|
Предыдущая | Следующая |
Object
+--- Widget
+--- Misc
+--- Arrow
Внешне виджет стрелок представляет собой указатель. Ему можно задать направление и стиль стрелок. На практике очень удобно использовать эти виджеты на кнопках. Как и Label, виджет стрелок не отправляет сигналов.
Существует только две функции для управления виджетом стрелок.
$arrow = new Gtk::Arrow( $arrow_type, $shadow_type );
$arrow->set( $arrow_type, $shadow_type );
'up' 'in'
Первая создает новый виджет заданого направления и вида.
Второй позволяет менять эти значения.
$arrow_type
может принимать одно из следующих значений:
Эти значения однозначно определеяют направление указателя стрелки.
В свою очередь
$shadow_type
может принимать следующие значения:
'down'
'left'
'right'
'out' (the default)
'etched_in'
'etched_out'
Приведем краткий пример для илюстрации использования стрелок.
#!/usr/bin/perl -w use Gtk ; use strict ; set_locale Gtk; init Gtk; my $false = 0; my $true = 1; my $window; my $button; my $box; # Создаем окно приложения $window = new Gtk::Window( "toplevel" ); $window->set_title( "Arrow Buttons" ); $window->signal_connect( "destroy", sub { Gtk-> exit ( 0 ); } ); $window->border_width( 10 ); # Создаем контейнер для стрелок-кнопок $box = new Gtk::HBox( $false, 0 ); $box->border_width( 2 ); $window->add( $box ); # упаковываем и показываем наши виджеты $box->show(); $button = create_arrow_button( 'up', 'in' ); $box->pack_start( $button, $false, $false, 3 ); $button = create_arrow_button( 'down', 'out' ); $box->pack_start( $button, $false, $false, 3 ); $button = create_arrow_button( 'left', 'in' ); $box->pack_start( $button, $false, $false, 3 ); $button = create_arrow_button( 'right', 'out' ); $box->pack_start( $button, $false, $false, 3 ); $window->show(); main Gtk; exit ( 0 ); ### Функции # Создаем виджет стрелок с указанными параметрами и упаковываем # его в кнопку. Первый параметр - направление стрелки, второй - # тип тени. sub create_arrow_button { my ( $arrow_type, $shadow_type ) = @_; my $button; my $arrow; $button = new Gtk::Button(); $arrow = new Gtk::Arrow( $arrow_type, $shadow_type ); $button->add( $arrow ); $button->show(); $arrow->show(); return ( $button ); } # Конец примера
Скриншот
Предыдущая | На главную | Следующая |
Календарь | Up | Списки и деревья |
Object
+--- Widget
+--- Container
+--- Bin
+--- Frame
+--- AspectFrame
The aspect frame widget is like a frame widget, except that it also enforces the aspect ratio (that is, the ratio of the width to the height) of the child widget to have a certain value, adding extra space if necessary. This is useful, for instance, if you want to preview a larger image. The size of the preview should vary when the user resizes the window, but the aspect ratio needs to always match the original image.
To create a new aspect frame use:
$aspect = new Gtk::AspectFrame( $label,
The
$xalign
and
$yalign
arguments specify the horizontal and vertical alignment, and
varies from
0.0
(left or top aligned) to
1.0
(right or bottom aligned).
If
$obey_child
is true, the aspect ratio of a child widget will match the
aspect ratio of the ideal size it requests. Otherwise, it is
given by
$ratio.
$xalign,
$yalign,
$ratio,
$obey_child );
To change the options of an existing aspect frame, you can use:
$aspect->frame_set( $xalign, $yalign, $ratio, $obey_child );
As an example, the following program uses an AspectFrame to present a drawing area whose aspect ratio will always be 2:1, no matter how the user resizes the top-level window.
#!/usr/bin/perl -w use Gtk ; use strict ; set_locale Gtk; init Gtk; my $false = 0; my $true = 1; my $window; my $aspect; my $drawing_area; # Create the window $window = new Gtk::Window( "toplevel" ); $window->set_title( "Aspect Frame" ); $window->signal_connect( "destroy", sub { Gtk-> exit ( 0 ); } ); $window->border_width( 10 ); # Create an aspect_frame and add it to our toplevel window $aspect = new Gtk::AspectFrame( "2x1", 0.5, 0.5, 2, $false ); $window->add( $aspect ); $aspect->show(); # Now add a child widget to the aspect frame $drawing_area = new Gtk::DrawingArea(); # Ask for a 200x200 window, but the AspectFrame will give us a 200x100 # window since we are forcing a 2x1 aspect ratio $drawing_area->set_usize( 200, 200 ); $aspect->add( $drawing_area ); $drawing_area->show(); $window->show(); main Gtk; exit ( 0 ); # END EXAMPLE PROGRAM
AspectFrame Example Screenshot
Обзор Gtk-Perl | ||
---|---|---|
Предыдущая | Следующая |
Эта глава написана для того, чтобы показать общий смысл контейнергог построения виджетов Gtk. После окончания прочтения этой части вы поймете как строить программы со сложным набором виджетов и использовать кнопки в программе.
Предыдущая | Наверх | Следующая |
Сигналы и события | Блоки кнопок |
These chapters document the most common Gtk widgets that are not containers. These widgets range from the very simple (like Labels and Arrows) to the more sophisticated widgets (like ProgressBars). After finishing these chapters you should know how to program most Graphical User Interfaces that a user will expect.
Обзор Gtk-Perl | ||
---|---|---|
Предыдущая | Следующая |
Object
+--- Widget
+--- Container
+--- Box
При создании приложения, вам будет необходимо расположить более одного виджета на формочке, ооветственной за все приложение. В первом примере была всего одна кнопка, и поэтому можно было использовать простую конструкцию $window->add() чтобы поместить виджет в окно. Но когда нужно поместить более одного виджета, необходимо их позиционировать относительно друг друга, с тем чтобы создать некий интерфейс к создаваемому Вами приложению.
Packing boxes - невидимые widget контейнеры, в которых располагаются вджеты. Packing boxes имееют две формы: горизонтальную и вертикальную. При помещении widgets в горизонтальный бокс, объекты вставлены горизонтально слева направо или наоборот в зависимости от используемого запроса. В вертикальном боксе, widgets упакованы сверху донизу или наоборот. Вы можете использовать любую комбинацию боксов для расположения виджетов внутри или рядом с двругими Packing boxes, чтобы придать желательные эффект и дизайн вашему приложению.
Для создания нового горизонтального или вертикального бокса, нужно написать
следующие строчки:
$hbox = new Gtk::HBox( $homogeneous, $spacing );
$vbox = new Gtk::VBox( $homogeneous, $spacing );
$box->pack_start( $child, $expand, $fill, $padding );
$box->pack_end( $child, $expand, $fill, $padding );
Если переменная $homogeneous
, то виждет можно располагать в пределах, определяемых HBox и Vbox.
Переменная $spacing
определяет границу в пикселах, на которую отстоят виджеты друг от друга.
Следующие функции используются для расположения объектов внутри бокса:
Функция
pack_start()
располагает элементы списка сверху в VBox и соответственно в слева направо в
HBox. Действие функции
pack_end() противоположно действию pack_start().
Добавленный объект может быть другим контейнером, например много виджетов -
те-же самые контейнеры, за исключением что в таких случаях как правло
используются либо pixmaps либо кнопки. Расположенный виджет в боксе является
дочерним к этому боксу.
Если аргумент $expand истеннен, то виджеты расположены в боксе так, что заполняют все место, если аргумент ложен, то бокс сокращается до размера виджета. Присваивая параметру расширения ложное значение виждет будет выравниваться по левому или правому краю в зависимости от желания. Следует отметить, что присваивание переменной $homogeneous значения true аналогично присваиванию значения ture переменной $expand
Если аргумент $fill истеннен, тогда дополнительное место распределено между объектами. В другом случае дополнительное свободное место распределяется между виджетами. Такое распределение возможно когда $expand выставлен в положение true.
Используя данные вариации, Gtk знает, где Вы хотите разместить ваш widgets, и автоматически может изменять размер виджета и другие изящные вещи. Вобщем использование данного метода дает немного гибкости при размещении и создании widgets.
Из-за этой гибкости боксы в GTK могут быть немного запутанны. Есть много различных способов расположения виджетов и не сразу очевидно, как они взаимодействуют между собой. В основном есть 5 различных стилей размещения, примеры которых приведены ниже:
Packing Box Styles Screenshot
Каждая линия примера содержит один горизонтальный бокс с несколькими кнопками. Запрос pack записывается для каждого pack отвечающего за кнопку внутри hbox. Каждая из кнопок помещается в hbox различными способами(то есть, те же самые аргументы подходят для функции pack_start()).
Метод является быстрым вызовом из
pack_start()
и
pack_end(),
которые устанавливают растягивающую виджет переменную в true, заполняют её и
устанавливают переменную в 0:
$box->pack_start_defaults( $widget );
$box->pack_end_defaults( $widget );
Однотипная(homogeneous) переменная бокса, в котором располагаются виджеты, может быть
установлена в on или off при помощи следующей функции:
$box->set_homogeneous( $homogeneous );
Переменная устанваливающая отступы вокруг виджета, может быть установлена
при помощи функции
$box->set_spacing( $spacing );
Если Вы хотите перестить потомка на новое место, то нужно использовать
функцию
$box->reorder_child( $child, $position );
где
$child
- перемещаемый виджет и
$position
- позиция для перемещения, начиная с 0. Если Вы хотите рассмотреть текущий
порядок, то нежно смотреть на список, возвращаемый функцией
children()
(унаследованной от Container).
Если необходимо изменить установку потомка, то используется следующая
функция:
$box->set_child_packing( $widget, $expand, $fill, $padding, $pack_type );
Аргументы этой функции похожи на аргументы
pack_start()
и
pack_end(),
за исключением
$pack_type,
которая может принимать значения либо 'start' либо 'end'. Каково различие
между интервалом и дополнением? Интервал добавлен между объектами, а
дополнение добавлено с обоих сторон объекта. Приведенная картинка поясняет
сказанное более ясно:
Packing Box Spacing Screenshot
Приведенная ниже программа показывает, как реализовать некоторые из типов расположения структур в приложении:
#!/usr/bin/perl -w use Gtk; use strict; set_locale Gtk; init Gtk; unless ($ARGV[0]){ print( "Использование: выберите тип расположения 1, 2, или 3.\n" ); Gtk->exit( 1 ); exit( 1 ); } my $false = 0; my $true = 1; my $which = $ARGV[0]; my ($window,$box1,$box2,$label,$separator,$quitbox,$button); # Вы должны всегда определять обработчик сигнала # delete_event для основного окна # Это очень важно для верного поведения програмы в случае сбоев $window = new Gtk::Window( "toplevel" ); $window->signal_connect( "delete_event", sub { Gtk->exit( 0 ); } ); $window->border_width( 10 ); # Мы создаем вертикальный бокс(vbox), и затем в него # ставим горизонтальные боксы. Такое расположение позволяет # расставлять горизонтальные боксы, заполненные кнопками, один над другим $box1 = new Gtk::VBox( $false, 0 ); # какой пример, соответствующий изображениям выше, показывать if ( $which == 1 ) { # создаем новый лейбл. $label = new Gtk::Label( 'new Gtk::HBox( $false, 0 );' ); # Выравниваем его по левой стороне. Описание этой функции ниже. $label->set_alignment( 0, 0 ); # Поместить лейбл в вертикальный бокс(vbox box1). Запомните, что # эти виджеты добавляются в vbox, который будет расположен свеху # остальных $box1->pack_start( $label, $false, $false, 0 ); # показываем лейбл $label->show(); # запрашиваем нашу создаваемую box функцию # homogeneous = FALSE, spacing = 0, # expand = FALSE, fill = FALSE, padding = 0 $box2 = make_box( $false, 0, $false, $false, 0 ); $box1->pack_start( $box2, $false, $false, 0 ); $box2->show(); # запрашиваем создающую бокс функцию # homogeneous = FALSE, spacing = 0, # expand = TRUE, fill = FALSE, padding = 0 $box2 = make_box( $false, 0, $true, $false, 0 ); $box1->pack_start( $box2, $false, $false, 0 ); $box2->show(); # Аргументы следующие: homogeneous, spacing, expand, fill, padding $box2 = make_box( $false, 0, $true, $true, 0 ); $box1->pack_start( $box2, $false, $false, 0 ); $box2->show(); # Создаем разделитель, описание позднее. $separator = new Gtk::HSeparator(); # Устанавливаем сепаратор в vbox, помните, # что каждый из этих widgets упаковывается в vbox, # так что они будут сложены вертикально $box1->pack_start( $separator, $false, $true, 5 ); $separator->show(); # Создаем другой лейбл и показываем $label = new Gtk::Label( 'new Gtk::HBox( $true, 0 );' ); $label->set_alignment( 0, 0 ); $box1->pack_start( $label, $false, $false, 0 ); $label->show(); # Аргументы: homogeneous, spacing, expand, fill, padding $box2 = make_box( $true, 0, $true, $false, 0 ); $box1->pack_start( $box2, $false, $false, 0 ); $box2->show(); # Аргументы: homogeneous, spacing, expand, fill, padding $box2 = make_box( $true, 0, $true, $true, 0 ); $box1->pack_start( $box2, $false, $false, 0 ); $box2->show(); # Другой новый сепаратор. $separator = new Gtk::HSeparator(); # Последние три аргумента gtk_box_pack_start: $separator = new Gtk::HSeparator(); # Последние три аргумента gtk_box_pack_start: # expand, fill, padding. $box1->pack_start( $separator, $false, $true, 5 ); $separator->show(); } elsif ( $which == 2 ) { # Создаем новый лейбл, запомните, что box1 это vbox $label = new Gtk::Label( 'new Gtk::HBox( $false, 10 );' ); $label->set_alignment( 0, 0 ); $box1->pack_start( $label, $false, $false, 0 ); $label->show(); # Аргументы: homogeneous, spacing, expand, fill, padding $box2 = make_box( $false, 10, $true, $false, 0 ); $box1->pack_start( $box2, $false, $false, 0 ); $box2->show(); # Аргументы: homogeneous, spacing, expand, fill, padding $box2 = make_box( $false, 10, $true, $true, 0 ); $box1->pack_start( $box2, $false, $false, 0 ); $box2->show(); $separator = new Gtk::HSeparator(); # Последние три аргумента gtk_box_pack_start: expand, fill, # и padding. $box1->pack_start( $separator, $false, $true, 5 ); $separator->show(); $label = new Gtk::Label( 'new Gtk::HBox( $false, 0 );' ); $label->set_alignment( 0, 0 ); $box1->pack_start( $label, $false, $false, 0 ); $label->show(); # Аргументы: homogeneous, spacing, expand, fill, padding $box2 = make_box( $false, 0, $true, $false, 10 ); $box1->pack_start( $box2, $false, $false, 0 ); $box2->show(); # Аргументы: homogeneous, spacing, expand, fill, padding $box2 = make_box( $false, 0, $true, $true, 10 ); $box1->pack_start( $box2, $false, $false, 0 ); $box2->show(); $separator = new Gtk::HSeparator(); # Последние три аргумента: expand, fill, # и padding. $box1->pack_start( $separator, $false, $true, 5); $separator->show(); } elsif ( $which == 3 ) { # этот пример показывает, как pack_end() выравнивает # widgets по правому краю. Создаем новый box. $box2 = make_box( $false, 0, $false, $false, 0); # Создаем новый лейбл, который будет установлен в конец. $label = new Gtk::Label( "end" ); # Установка с применением gtk_box_pack_end(), $box2->pack_end( $label, $false, $false, 0 ); # показываем лейбл. $label->show(); # Помещаем box2 в box1 $box1->pack_start( $box2, $false, $false, 0 ); $box2->show(); # Сепаратор снизу $separator = new Gtk::HSeparator(); # далее подробно устанавливаем параметры разделителя # в 400 пикселов и ширинойц и 5 пикселов высотой # так-же это значит, что hbox быдет создан шириной в 400 пикселов # и ярлык "end" будет отделен от других лейблов в hbox. # В противном случае все лейблы будут прилегать друг к другу вплотную $separator->set_usize( 400, 5 ); # добавить сепаратор в vbox(box1), созданный вначале программы $box1->pack_start( $separator, $false, $true, 5 ); $separator->show(); } # создать другой бокс, $quitbox = new Gtk::HBox( $false, 0 ); # создаем кнопку выход. $button = new Gtk::Button( "Quit" ); # Послать сигнал для завершения программы, когда кнопка будет нажата $button->signal_connect( "clicked", sub { Gtk->exit( 0 ); } ); # Добавить кнопку в quitbox # последние три аргумента gtk_box_pack_start: # expand, fill, padding. $quitbox->pack_start( $button, $true, $false, 0 ); # добавить quitbox в vbox (box1) $box1->pack_start( $quitbox, $false, $false, 0 ); # Добавить vbox(box1) который теперь содержит все наши виджеты в основное окно $window->add( $box1 ); # и показать все слева $button->show(); $quitbox->show(); $box1->show(); # Показ всего окна со всеми лейблами и кнопками. $window->show(); # вызов основной функции. main Gtk; exit(0); # создаем новый hbox, заполненный кнопками и лейбралми. # Мы не показываем сам бокс, но показываем его содержимое sub make_box{ my ($homogeneous,$spacing,$expand,$fill,$padding) = @_; # создаем новый hbox с соответствующими установками типов и отступов my $box = new Gtk::HBox( $homogeneous, $spacing ); $button = new Gtk::Button( '$box->' ); $box->pack_start( $button, $expand, $fill, $padding ); $button->show(); # Create a series of buttons with the appropriate settings # Создаем серию кнопок с соответствующими настройками $button = new Gtk::Button( "pack" ); $box->pack_start( $button, $expand, $fill, $padding ); $button->show(); $button = new Gtk::Button( '( $button,' ); $box->pack_start( $button, $expand, $fill, $padding ); $button->show(); # создаем кнопку с лейблом, зависящим от переменной, отвечающей за растягивание if ($expand){ $button = new Gtk::Button('$true,'); } else { $button = new Gtk::Button('$false,'); } $box->pack_start( $button, $expand, $fill, $padding ); $button->show(); if ( $fill ) { $button = new Gtk::Button( '$true,' ); } else { $button = new Gtk::Button( '$false,' ); } $box->pack_start( $button, $expand, $fill, $padding ); $button->show(); $button = new Gtk::Button( "$padding );" ); $box->pack_start( $button, $expand, $fill, $padding ); $button->show(); return ( $box ); }
Предыдущая | Начало | Следующая |
Основные контейнеры | Вверх | Таблицы |
Иерархия наследования
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;
}
сделать скриншоты работы программы
Иерархия наследования
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
+--- Calendar
The Calendar widget is an effective way to display and retrieve date related information. It is a very simple widget to create and work with.
Creating a Calendar widget is a simple as:
$calendar = new Gtk::Calendar();
There might be times where you need to change a lot of
information within this widget and the following functions allow
you to make multiple change to a Calendar widget without the
user seeing multiple on-screen updates.
$calendar->freeze();
$calendar->thaw();
They work just like the freeze/thaw functions of other widgets.
The Calendar widget has a few options that allow you to change
the way the widget both looks and operates by using the
following function:
$calendar->display_options( $flags );
The
$flags
argument can be formed by combining any of the following five
options:
'heading' - this option specifies that the month and year should be shown when drawing the calendar.
'show_day_names' - this option specifies that the three letter descriptions should be displayed for each day (eg MON,TUE...).
'no_month_change' - this option states that the user should not and can not change the currently displayed month. This can be good if you only need to display a particular month such as if you are displaying 12 calendar widgets for every month in a particular year.
'show_week_numbers' - this option specifies that the number for each week should be displayed down the left side of the calendar. (eg. Jan 1 = Week 1,Dec 31 = Week 52).
'week_start_monday' - this option states that the calander week will start on Monday instead of Sunday which is the default. This only affects the order in which days are displayed from left to right.
The following functions are used to set the the currently
displayed date:
$calendar->select_month( $month, $year );
$calendar->select_day( $day );
The return value from
select_month()
is a true or false value indicating whether the selection was
successful.
With select_day() the specified day number is selected within the current month, if that is possible. A $day value of 0 will deselect any current selection.
In addition to having a day selected, any number of days in the
month may be "marked". A marked day is highlighted within the
calendar display. The following functions are provided to
manipulate marked days:
$calendar->mark_day( $day );
$calendar->unmark_day( $day );
$calendar->clear_marks();
The currently marked days are stored within an array. This array
is 31 elements long so to test whether a particular day is
currently marked, you need to access the corresponding element
of the array (don't forget that the array elements are numbered
0 to 30). For example:
if ( $calendar->marked_date[ $day - 1 ] )
{
print( "Day $day is marked\n" );
}
Note that marks are persistent across month and year changes.
The final Calendar widget function is used to retrieve the
currently selected date, month and/or year.
( $year, $month, $day ) = $calendar->get_date();
The Calendar widget can generate a number of signals indicating date selection and change. The names of these signals are self explanatory, and are:
'month_changed'
'day_selected'
'day_selected_double_click'
'prev_month'
'next_month'
'prev_year'
'next_year'
That just leaves us with the need to put all of this together into example code.
Calendar Widget Example Source
#!/usr/bin/perl -w # Be advised, this program is more complicated than the others in the # tutorial. However, I wanted to document as many features as # possible. I am also taking advantage of Perl data structures more # heavily than normal. use Gtk ; use strict ; set_locale Gtk; init Gtk; my $false = 0; my $true = 1; my $year_base = 1900; my $i; my @flags = ( "Show Heading", "Show Day Names", "No Month Change", "Show Week Numbers", "Week Start Monday" ); my %calendar_data = ( " ", " " ); my $window; my $vbox; my $vbox2; my $vbox3; my $hbox; my $hbbox; my $calendar; my $toggle; my $button; my $frame; my $separator; my $label; my $bbox; # Set up calendar data $calendar_data{ "window" } = undef; $calendar_data{ "font" } = undef; $calendar_data{ "font_dialog" } = undef; $calendar_data{ "settings" } = [ 0, 0, 0, 0, 0 ]; # Create the window $window = new Gtk::Window( 'toplevel' ); $window->set_title( "Calendar Example" ); $window->border_width( 5 ); $window->signal_connect( 'destroy', sub { Gtk-> exit ( 0 ); } ); $window->signal_connect( 'delete-event', \>k_false ); $window->set_policy( $false, $false, $true ); $vbox = new Gtk::VBox( $false, 10 ); $window->add( $vbox ); # The top part of the window, Calendar, flags and fontsel. $hbox = new Gtk::HBox( $false, 10 ); $vbox->pack_start( $hbox, $true, $true, 10 ); $hbbox = new Gtk::HButtonBox(); $hbox->pack_start( $hbbox, $false, $false, 10 ); $hbbox->set_layout( 'spread' ); $hbbox->set_spacing( 5 ); # Create the Calendar widget $frame = new Gtk::Frame( "Calendar" ); $hbbox->pack_start( $frame, $false, $true, 10 ); $calendar = new Gtk::Calendar(); $calendar_data{ "window" } = $calendar; calendar_set_flags(); $calendar->mark_day( 19 ); $frame->add( $calendar ); # Set up calendar callbacks $calendar->signal_connect( 'month_changed', \&calendar_month_changed ); $calendar->signal_connect( 'day_selected', \&calendar_day_selected ); $calendar->signal_connect( 'day_selected_double_click', \&calendar_day_selected_double_click ); $calendar->signal_connect( 'prev_month', \&calendar_prev_month ); $calendar->signal_connect( 'next_month', \&calendar_next_month ); $calendar->signal_connect( 'prev_year', \&calendar_prev_year ); $calendar->signal_connect( 'next_year', \&calendar_next_year ); $separator = new Gtk::VSeparator(); $hbox->pack_start( $separator, $false, $true, 0 ); $vbox2 = new Gtk::VBox( $false, 10 ); $hbox->pack_start( $vbox2, $false, $false, 10 ); # Build the Right frame with the flags in $frame = new Gtk::Frame( "Flags" ); $vbox2->pack_start( $frame, $true, $true, 10 ); $vbox3 = new Gtk::VBox( $true, 5 ); $frame->add( $vbox3 ); for $i ( 0..4 ) { $toggle = new Gtk::CheckButton( $flags[ $i ] ); $toggle->signal_connect( 'toggled', \&calendar_toggle_flag ); $vbox3->pack_start( $toggle, $true, $true, 0 ); $calendar_data{ 'flag_checkboxes' }[ $i ] = $toggle; } # Build the right font-button $button = new Gtk::Button( "Font..." ); $button->signal_connect( 'clicked', \&calendar_select_font ); $vbox2->pack_start( $button, $false, $false, 0 ); # Build the Signal-event part. $frame = new Gtk::Frame( "Signal Events" ); $vbox->pack_start( $frame, $true, $true, 10 ); $vbox2 = new Gtk::VBox( $true, 5 ); $frame->add( $vbox2 ); # Frame to report signals $hbox = new Gtk::HBox( $false, 3 ); $vbox2->pack_start( $hbox, $false, $true, 0 ); $label = new Gtk::Label( "Signal:" ); $hbox->pack_start( $label, $false, $true, 0 ); $calendar_data{ "last_sig" } = new Gtk::Label( " " ); $hbox->pack_start( $calendar_data{ "last_sig" }, $false, $true, 0 ); $hbox = new Gtk::HBox( $false, 3 ); $vbox2->pack_start( $hbox, $false, $true, 0 ); $label = new Gtk::Label( "Previous Signal:" ); $hbox->pack_start( $label, $false, $true, 0 ); $calendar_data{ "prev_sig" } = new Gtk::Label( " " ); $hbox->pack_start( $calendar_data{ "prev_sig" }, $false, $true, 0 ); $hbox = new Gtk::HBox( $false, 3 ); $vbox2->pack_start( $hbox, $false, $true, 0 ); $label = new Gtk::Label( "Second Previous Signal:" ); $hbox->pack_start( $label, $false, $true, 0 ); $calendar_data{ "prev2_sig" } = new Gtk::Label( " " ); $hbox->pack_start( $calendar_data{ "prev2_sig" }, $false, $true, 0 ); $bbox = new Gtk::HButtonBox(); $vbox->pack_start( $bbox, $false, $false, 0 ); $bbox->set_layout( 'end' ); # Close button $button = new Gtk::Button( "Close" ); $button->signal_connect( 'clicked', sub { Gtk-> exit ( 0 ); } ); $bbox->add( $button ); $button->can_default( $true ); $button->grab_default(); $window->show_all(); main Gtk; exit ( 0 ); ### Subroutines # Function that takes the selected calendar date and converts it to a # American style string. sub calendar_date_to_string { my $string; my $year; my $month; my $day; my @months = qw( January February March April May June July August September October November December ); ( $year, $month, $day ) = $calendar_data{ 'window' }->get_date(); $string = $months[ $month ] . " " . $day . ", " . $year; return ( $string ); } # Add a new string to the signal strings, moving previous strings to # their appropriate place. sub calendar_set_signal_strings { my ( $sig_str ) = @_; my $prev_sig; $prev_sig = $calendar_data{ 'prev_sig' }->get(); $calendar_data{ 'prev2_sig' }->set( $prev_sig ); $prev_sig = $calendar_data{ 'last_sig' }->get(); $calendar_data{ 'prev_sig' }->set( $prev_sig ); $calendar_data{ 'last_sig' }->set( $sig_str ); } # Callback to report that the month has been changed. sub calendar_month_changed { my $buffer = "month_changed: " . calendar_date_to_string(); calendar_set_signal_strings( $buffer ); } # Callback to report that the day has been changed. sub calendar_day_selected { my $buffer = "day_selected: " . calendar_date_to_string(); calendar_set_signal_strings( $buffer ); } # Callback to report that the previous month button has been pressed. sub calendar_prev_month { my $buffer = "prev_month: " . calendar_date_to_string(); calendar_set_signal_strings( $buffer ); } # Callback to report that the next month button has been pressed. sub calendar_next_month { my $buffer = "next_month: " . calendar_date_to_string(); calendar_set_signal_strings( $buffer ); } # Callback to report that the previous year button has been pressed. sub calendar_prev_year { my $buffer = "prev_year: " . calendar_date_to_string(); calendar_set_signal_strings( $buffer ); } # Callback to report that the next year button has been pressed. sub calendar_next_year { my $buffer = "next_year: " . calendar_date_to_string(); calendar_set_signal_strings( $buffer ); } # A function that set the calendar settings based on the toggle # buttons. sub calendar_set_flags { my $i; my $options = 0; for ( $i = 0; $i < 5; $i++ ) { if ( $calendar_data{ 'settings' }[ $i ] ) { $options = $options + ( 1 << $i ); } } if ( $calendar_data{ 'window' } ) { $calendar_data{ 'window' }->display_options( $options ); } } # Callback for radio buttons. When toggled, they change the # appropriate calendar setting. sub calendar_toggle_flag { my ( $toggle ) = @_; my $j = 0; for my $i ( 0..4 ) { if ( $calendar_data{ 'flag_checkboxes' }[ $i ] == $toggle ) { $j = $i; } } $calendar_data{ 'settings' }[$j] = not $calendar_data{ 'settings' }[$j]; calendar_set_flags(); } # Callback called when the OK button of the font dialog is clicked on. sub calendar_font_selection_ok { my ( $button ) = @_; my $style; my $font; $calendar_data{'font'} = $calendar_data{ 'font_dialog' }->get_font_name(); if ( $calendar_data{ 'window' } ) { $font = $calendar_data{ 'font_dialog' }->get_font(); if ( $font ) { $style=new Gtk::Style(); $style->font($font); $calendar_data{ 'window' }->set_style( $style ); } } } # Callback attached to the "Change Font" button. It starts up a font # dialog, allowing you to set a new font. sub calendar_select_font { my ( $button ) = @_; my $window; if ( $calendar_data{ 'font_dialog' } ) { $window = $calendar_data{ 'font_dialog' }; } else { $window = new Gtk::FontSelectionDialog( "Font Selection Dialog" ); $window->position( 'mouse' ); $window->signal_connect( 'destroy', sub { $window->destroyed(); } ); $window->ok_button->signal_connect( 'clicked', \&calendar_font_selection_ok ); $window->cancel_button->signal_connect( 'clicked', sub { $window->hide(); } ); $calendar_data{ 'font_dialog' } = $window; } if ( $window->visible ) { $window->destroy(); } else { $window->show(); } } # END EXAMPLE PROGRAM
Calendar Example Screenshot
Иерархия наследования
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' сигналов "снятие выделения" и "новое выделение".
The CList widget has replaced the List widget (which is still available).
The CList widget is a multi-column list widget that is capable of handling literally thousands of rows of information. Each column can optionally have a title, which itself is optionally active, allowing us to bind a function to its selection.
Creating a CList is quite straightforward, once you have learned about widgets in general. It provides the almost standard two ways: the hard way, and the easy way. But before we create it, there is one thing we should figure out beforehand: how many columns should it have?
Not all columns have to be visible and can be used to store data
that is related to a certain cell in the list.
$clist = new Gtk::CList( $columns );
$clist = new_with_titles Gtk::CList( @titles );
The first form is very straightforward, the second might require
some explanation. Each column can have a title associated with
it, and this title can be a label or a button that reacts when
we click on it. If we use the second form, we provide a list of
title texts, and the number of elements in the list becomes the
number of columns in the CList. Of course we can always use the
first form, and manually add titles later.
Note: The CList widget does not have its own scrollbars and should be placed within a ScrolledWindow widget if your require this functionality. This is a change from the GTK 1.0 implementation.
There are several attributes that can be used to alter the
behaviour of a CList. First there is:
$clist->set_selection_mode( $mode );
which, as the name implies, sets the selection mode of the
CList. The argument specifies the cell selection mode (they are
defined in Gtk's C header fill gtkenums.h). At the time of this
writing, the following modes are available to us:
'single' - The selection is either empty or contains a single selected item.
'browse' - The selection is empty if the list contains no widgets or insensitive ones only, otherwise it contains one list item.
'multiple' - The selection is empty if no list items are selected or a list of selected items. This is currently the default for the CList widget.
'extended' - Any number of elements may be selected. Click-drag selects a range of elements. The Ctrl key may be used to enlarge the selection, and Shift key to select between the focus and the child pointed to.
We can also define what the border of the CList widget should
look like. It is done through:
$clist->set_shadow_type( $border );
'none'
The possible values for
$border are:
'in'
'out'
'etched_in'
'etched_out'
When you create a CList widget, you will also get a set of title
buttons automatically. They live in the top of the CList window,
and can act either as normal buttons that respond to being
pressed, or they can be passive, in which case they are nothing
more than a title. There are four different calls that aid us in
setting the status of the title buttons.
$clist->column_title_active( $column );
$clist->column_title_passive( $column );
$clist->column_titles_active();
$clist->column_titles_passive();
An active title is one which acts as a normal button, a passive
one is just a label. The first two calls above will
activate/deactivate the title button above the specific column,
while the last two calls activate/deactivate all title buttons in
the supplied clist widget.
But of course there are those cases when we don't want them at
all, and so they can be hidden and shown at will using the
following two calls.
$clist->column_titles_show();
$clist->column_titles_hide();
For titles to be really useful we need a mechanism to set and
change them, and this is done using
$clist->set_column_title( $column, $title );
$clist->set_column_widget( $column, $widget );
Note that only the title of one column can be set at a time, so
if all the titles are known from the beginning, then I really
suggest using
new_with_titles Gtk::CList()
(as described above) to set them. It saves you coding time, and
makes your program smaller. There are some cases where getting
the job done the manual way is better, and that's when not all
titles will be text. CList provides us with title buttons that
can in fact incorporate whole widgets, for example a
pixmap
.
It's all done through
which should require no special explanation.
It is possible to change the justification for a column, and it is
done through
$clist->set_column_justification( $column, $justification );
where the
$justification
can take the following values:
'left' - The text in the column will begin from the left edge.
'right' - The text in the column will begin from the right edge.
'center' - The text is placed in the center of the column.
'fill' - The text will use up all available space in the column. It is normally done by inserting extra blank spaces between words (or between individual letters if it's a single word). Much in the same way as any ordinary WYSIWYG text editor.
The next function is a very important one, and should be
standard in the setup of all CList widgets. When the list is
created, the width of the various columns are chosen to match
their titles, and since this is seldom the right width we have
to set it using:
$clist->set_column_width( $column, $width );
$clist->set_row_height( $height );
Note that the width is given in pixels and not letters. The same
goes for the height of the cells in the columns, but as the
default value is the height of the current font this isn't as
critical to the application. Still, it is done through:
Again, note that the height is given in pixels.
We can also move the list around without user interaction,
however, it does require that we know what we are looking
for. Or in other words, we need the row and column of the item
we want to scroll to.
$clist->moveto( $row, $column, $row_align, $col_align );
$row_align
is pretty important to understand. It's a value between 0.0 and
1.0, where 0.0 means that we should scroll the list so the row
appears at the top, while if the value of row_align is 1.0, the
row will appear at the bottom instead. All other values between
0.0 and 1.0 are also valid and will place the row between the
top and the bottom. The last argument,
$col_align
works in the same way, though 0.0 marks left and 1.0 marks right
instead.
Depending on the application's needs, we don't have to scroll to
an item that is already visible to us. So how do we know if it is
visible? As usual, there is a function to find that out as well.
$clist->row_is_visible( $row );
'none'
The return value is is one of the following:
Note that it will only tell us if a row is visible. Currently
there is no way to determine this for a column. We can get
partial information though, because if the return is
'partial',
then some of it is hidden, but we don't know if it is the row
that is being cut by the lower edge of the listbox, or if the
row has columns that are outside.
'partial'
'full'
We can also change both the foreground and background colors of
a particular row. This is useful for marking the row selected by
the user, and the two functions that is used to do it are
$clist->set_foreground( $row, $color );
$clist->set_background( $row, $color );
The colors must have been previously allocated.
We can add rows in three ways. They can be prepended or appended
to the list using:
$clist->prepend( @text );
$clist->append( @text );
$clist->insert( $row, @text );
The return value of these two functions indicate the index of
the row that was just added. We can insert a row at a given
place using:
In these calls we have to provide a list of the texts we want to put in the columns. The number of texts should equal the number of columns in the list. If the list of text argument is empty, then there will be no text in the columns of the row. This is useful, for example, if we want to add pixmaps instead (something that has to be done manually).
Also remember that the numbering of both rows and columns start at 0.
To remove an individual row we use:
$clist->remove( $row );
There is also a call that removes all rows in the list. This is
a lot faster than calling gtk_clist_remove once for each row,
which is the only alternative. To do this we use:
$clist->clear();
There are also two convenience functions that should be used
when a lot of changes have to be made to the list. This is to
prevent the list flickering while being repeatedly updated,
which may be highly annoying to the user. So instead it is a
good idea to freeze the list, do the updates to it, and finally
thaw it which causes the list to be updated on the screen.
$clist->freeze();
$clist->thaw();
A cell can contain a
pixmap
,
text or both. To set them the following functions are used.
$clist->set_text( $row, $column, $text );
$clist->set_pixmap( $row, $column, $pixmap, $mask );
$clist->set_pixtext( $row, $column, $text, $spacing, $pixmap, $mask );
It's quite straightforward. All the calls have the row and
column of the cell, followed by the data to be set. The
$spacing
argument in
set_pixtext()
is the number of pixels between the pixmap and the beginning of
the text. In all cases the data is copied into the widget.
To read back the data, we instead use:
$text = $clist->get_text( $row, $column );
( $pixmap, $mask ) = $clist->get_pixmap( $row, $column );
( $text, $spacing, $pixmap, $mask ) = $clist->get_pixtext( $row, $column );
The returned values are all references to the data stored within
the widget, so the referenced data should not be modified.
There is one more call that is related to what's inside a cell in
the clist, and that's:
$clist->get_cell_type( $row, $column );
'empty'
which returns the type of data in a cell. The return value is one
of:
'text'
'pixmap'
'pixtext'
'widget'
There is also a function that will let us set the indentation,
both vertical and horizontal, of a cell. The indentation value
is given in pixels, and can be both positive and negative.
$clist->set_shift( $row, $column, $vertical, $horizontal );
There are also functions available that let us force the selection
or unselection of a row. These are
$clist->select_row( $row, $column );
$clist->unselect_row( $row, $column );
And also a function that will take x and y coordinates (for
example, from the mousepointer), and map that onto the list,
returning the corresponding row and column.
( $row, $column ) = $clist->get_selection_info( $x, $y );
When we detect something of interest (it might be movement of
the pointer, or a click somewhere in the list) we can read the
pointer coordinates and find out where in the list the pointer
is. Cumbersome? Luckily, there is a simpler way...
As with all other widgets, there are a few signals that can be used. The CList widget is derived from the Container widget, and so has all the same signals, but also adds the following:
'select_row' - This signal will send the following information, in order: the CList, the row, the column, and the event.
'unselect_row' - When the user unselects a row, this signal is activated. It sends the same information as the 'select_row' signal.
'click_column' - Sends a CList and a column.
So if we want to connect a callback to
'select_row',
the callback function would be declared like this:
sub select_row_callback
{
my ( $widget, $row, $column, $event, @data ) = @_;
}
The callback is connected as usual with:
$clist->signal_connect( "select_row", \&select_row_callback, @data );
#!/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 $scrolled_window; my $clist; my $button_add; my $button_clear; my $button_hide_show; my $titles_visible = $true; my @titles = ( "Ingredients", "Amount" ); # Create the window $window = new Gtk::Window( "toplevel" ); $window->set_usize( 300, 150 ); $window->set_title( "CList Example" ); $window->signal_connect( "destroy", sub { Gtk-> exit ( 0 ); } ); $vbox = new Gtk::VBox( $false, 5 ); $window->add( $vbox ); $vbox->border_width( 5 ); $vbox->show(); # Create a scrolled window to pack the CList widget into $scrolled_window = new Gtk::ScrolledWindow( undef, undef ); $vbox->pack_start( $scrolled_window, $true, $true, 0 ); $scrolled_window->set_policy( 'automatic', 'always' ); $scrolled_window->show(); # Create the CList. For this example we use 2 columns $clist = new_with_titles Gtk::CList( @titles ); # When a selection is made, we want to know about it. The callback # used is selection_made, and its code can be found further down $clist->signal_connect( "select_row", \&selection_made ); # It isn't necessary to shadow the border, but it looks nice :) $clist->set_shadow_type( 'out' ); # What however is important, is that we set the column widths as # they will never be right otherwise. Note that the columns are # numbered from 0 and up (to 1 in this case). $clist->set_column_width( 0, 150 ); # Add the CList widget to the vertical box and show it. $scrolled_window->add( $clist ); $clist->show(); # Create the buttons and add them to the window. $hbox = new Gtk::HBox( $false, 0 ); $vbox->pack_start( $hbox, $false, $true, 0 ); $hbox->show(); $button_add = new Gtk::Button( "Add List" ); $button_clear = new Gtk::Button( "Clear List" ); $button_hide_show = new Gtk::Button( "Hide/Show Titles" ); $hbox->pack_start( $button_add, $true, $true, 0 ); $hbox->pack_start( $button_clear, $true, $true, 0 ); $hbox->pack_start( $button_hide_show, $true, $true, 0 ); # Connect our callbacks to the three buttons $button_add->signal_connect( "clicked", \&button_add_clicked, $clist ); $button_clear->signal_connect( "clicked", sub { $clist->clear(); } ); $button_hide_show->signal_connect( "clicked", \&button_hide_show_clicked, $clist ); $button_add->show(); $button_clear->show(); $button_hide_show->show(); $window->show(); main Gtk; exit ( 0 ); ### Subroutines # User clicked the "Add List" button. sub button_add_clicked { my ( $widget, $clist ) = @_; # Something silly to add to the list. 4 rows of 2 columns each. my @drink = ( [ Milk => "3 Oz" ], [ Water => "6 l" ], [ Carrots => "2" ], [ Snakes => "55" ] ); # Here we do the actual adding of the text. It's done once for each row. for my $i ( 0..3 ) { $clist->append( @{$drink[ $i ]} ); } # For those who may not have understood the above, here is a brief # explanation. @drink is a list of references to anonymouse lists # (references are scalars holding a memory address, similar to # pointers). This is used because Perl doesn't directly support # two-dimensional arrays. Because of this, $drink[$i] is not a # list, but a reference to one, so we must dereference it by # enclosing it like this: @{ reference } ( we use @ because it is a # reference to a list. For further information on references, see # the perlref(1) man page, or chapter 4 of _Programming Perl_. return ; } # The user clicked the "Hide/Show titles" button. sub button_hide_show_clicked { my ( $widget, $clist ) = @_; if ( $titles_visible ) { # Hide the titles and set the flag to 1 $clist->column_titles_hide(); $titles_visible++; } else { # Show the titles and reset flag to 0 $clist->column_titles_show(); $titles_visible--; } } # If we come here, then the user has selected a row in the list. sub selection_made { my ( $clist, $row, $column, $event, @data ) = @_; my $text; # Get the text that is stored in the selected row and column # which was clicked in. We will receive it as a pointer in the # argument text. $text = $clist->get_text( $row, $column ); # Just prints some information about the selected row print ( "You selected row $row. More specifically, you clicked in\n" ); print ( "column $column, and the text in this cell is:\n" ); print ( " $text\n\n" ); return ; } # END EXAMPLE PROGRAM
CList Example Screenshot
Object
+--- Widget
+--- Container
+--- Box
+--- VBox
+--- ColorSelection
The color selection widget is, not surprisingly, a widget for interactive selection of colors. This composite widget lets the user select a color by manipulating RGB (Red, Green, Blue) and HSV (Hue, Saturation, Value) triples. This is done either by adjusting single values with sliders or entries, or by picking the desired color from a hue-saturation wheel/value bar. Optionally, the opacity of the color can also be set.
The color selection widget currently emits only one signal, 'color_changed' which is emitted whenever the current color in the widget changes, either when the user changes it or if it's set explicitly through selection_set_color().
Lets have a look at what the color selection widget has to offer us. The widget comes in two flavours: Gtk::ColorSelection (described here) and Gtk::ColorSelectionDialog (described later .)
To create a ColorSelection widget, use:
$color = new Gtk::ColorSelection();
The update policy can be set using:
$color->set_update_policy( $policy );
$color->set_opacity( $use_opacity );
The default policy is
'continuous'
which means that the current color is updated continuously when
the user drags the sliders or presses the mouse and drags in the
hue-saturation wheel or value bar. If you experience performance
problems, you may want to set the policy to
'discontinuous' or
'delayed'.
The color selection widget supports adjusting the opacity of a
color (also known as translucency or the alpha channel). This is
disabled by default. Calling this function with
$use_opacity
set to a true value enables opacity. Likewise, if
$use_opacity
is set to a false value it will disable opacity.
$color->set_color( @colors );
You can set the current color explicitly by calling this
function with a list of colors. The length of the array depends
on whether opacity is enabled or not. Position 0 contains the
red component, 1 is green, 2 is blue and opacity is at position
3 (only if opacity is enabled, see
set_opacity()).
All values are between 0.0 and 1.0.
@color = $color->get_color();
When you need to query the current color, typically when you've received a 'color_changed' signal, you use this function. Returned is a list of colors to fill in. See the set_color() function for the description of this list.
Object
+--- Widget
+--- Container
+--- Bin
+--- Window
+--- ColorSelectionDialog
The ColorSelectionDialog widget is a dialog box consisting of a ColorSelection widget. See the chapter on the ColorSelection widget for more information.
To create a color selection dialog, use:
$colordialog = new Gtk::ColorSelectionDialog( $window_title );
The new ColorSelectionDialog consists of a Frame containing a ColorSelection widget, an HSeparator and an HBox with three buttons, "Ok", "Cancel" and "Help". You can reach these buttons by accessing the ok_button , cancel_button and help_button widgets in the ColorSelectionDialog structure, (i.e., $colordialog->ok_button ).
Here's a simple example demonstrating the use of the ColorSelectionDialog. The program displays a window containing a drawing area. Clicking on it opens a color selection dialog, and changing the color in the color selection dialog changes the background color. As an extra bonus, it prints out the color in the hexidecimal format used by HTML. With this format, the first two characters are the red value, the next two are green, and the last two are blue.
A good exercise would be to turn the label into a Text Entry and allow you to enter an HTML color and change the color of the drawing area accordingly. You could also try verifying that the inputted HTML color is valid.
#!/usr/bin/perl -w use Gtk ; use strict ; set_locale Gtk; init Gtk; my $false = 0; my $true = 1; my $dialog_shown = $false; my $window; my $mainbox; my $drawingarea; my $buttonbox; my $button; my $label; my $colorsel; my $colormap; my $gdk_color; # Create the window $window = new Gtk::Window( "toplevel" ); $window->set_title( "Color Selection Test" ); $window->border_width( 10 ); $window->realize(); $window->signal_connect( "delete_event", sub { Gtk-> exit ( 0 ); } ); $mainbox = new Gtk::VBox( $false, 10 ); $window->add( $mainbox ); $mainbox->show(); # Create a button with a drawingarea inside it $button = new Gtk::Button(); $button->signal_connect( "clicked", \&select_color ); $button->show(); $mainbox->pack_start( $button, $false, $false, 0 ); # Create a button box $buttonbox = new Gtk::VBox( $false, 0 ); $buttonbox->show(); $button->add( $buttonbox ); # Create the drawing area used to display the color $drawingarea = new Gtk::DrawingArea(); $drawingarea->size( 32, 32 ); $drawingarea->show(); $buttonbox->pack_start( $drawingarea, $false, $false, 0 ); $colormap = $drawingarea->window->get_colormap(); $gdk_color = Gtk::Gdk::Color->parse_color( "black" ); $gdk_color = $colormap->color_alloc( $gdk_color ); $drawingarea->window->set_background( $gdk_color ); # Create the label used to display the HTML hexidecimal color $label = new Gtk::Label( "HTML color: #FFFFFF" ); $label->show(); $mainbox->pack_start( $label, $false, $false, 0 ); $window->show(); main Gtk; exit ( 0 ); ### Subroutines # Drawingarea event handler called when the button is clicked. sub select_color { my ( $drawingarea ) = @_; my $colordialog = " "; # Make sure the dialog isn't already shown unless ( $dialog_shown ) { # Create color selection dialog $colordialog = new Gtk::ColorSelectionDialog( "Select Color"); $dialog_shown = $true; # Get the ColorSelection widget $colorsel = $colordialog->colorsel; $colordialog->ok_button->signal_connect( "clicked", \&close_dialog, $colordialog ); $colordialog->cancel_button->signal_connect( "clicked", \&close_dialog, $colordialog ); # Connect to the "color_changed" signal, set the client-data # to the colorsel widget $colorsel->signal_connect( "color_changed", \&color_changed_cb ); # Show the dialog $colordialog->show(); } } # Callback that is called when the color in the color dialog is changed. It updates the color shown in the drawing area. sub color_changed_cb { my ( $colorsel ) = @_; my @color; my $red; my $green; my $blue; @color = $colorsel->get_color(); $gdk_color->{ 'red' } = $color[0] * 65535.0; $gdk_color->{ 'green' } = $color[1] * 65535.0; $gdk_color->{ 'blue' } = $color[2] * 65535.0; # Convert to HTML format. There are better ways to do this. $red = $gdk_color->{ 'red' } / 256; $green = $gdk_color->{ 'green' } / 256; $blue = $gdk_color->{ 'blue' } / 256; $red = uc( sprintf( "%lx", $red ) ); $green = uc( sprintf( "%lx", $green ) ); $blue = uc( sprintf( "%lx", $blue ) ); $red = "0" . $red if ( $red =~ /^\d$/ ); $green = "0" . $green if ( $green =~ /^\d$/ ); $blue = "0" . $blue if ( $blue =~ /^\d$/ ); $label->set_text( "HTML color: #" . $red . $green . $blue . "\n" ); $gdk_color = $colormap->color_alloc( $gdk_color ); $drawingarea->window->set_background( $gdk_color ); $drawingarea->window->clear(); } # Close the color dialog. sub close_dialog { my ( $button, $colordialog ) = @_; $colordialog->hide(); $dialog_shown = $false; } # END EXAMPLE PROGRAM
Color Selection Dialog Main Window Screenshot
Color Selection Dialog Example Screenshot
Object
+--- Widget
+--- Container
+--- Box
+--- HBox
+--- Combo
The combo box is fairly simple widget that is really just a collection of other widgets. From the user's point of view, the widget consists of a text entry box and a pulldown menu from which the user can select one of a set of predefined entries. Alternatively, the user can type a different option directly into the text box.
The following extracts from the structure that defines a Combo
Box identifies several of the components:
Gtk::Combo
-> hbox
-> entry
-> button
-> popup
-> popwin
-> list
As you can see, the Combo Box has two principal parts that you really care about: an entry and a list.
First off, to create a combo box, use:
$combo = new Gtk::Combo();
Now, if you want to set the string in the entry section of the
combo box, this is done by manipulating the
entry
widget directly:
$combo->entry->set_text( "My String." );
To set the values in the popdown list, use the function:
$combo->set_popdown_strings( @strings );
Before you can do this, you have to assemble a list of the
strings that you want. Any Perl expression that can be
evaluated as a list can be use as an argument. A comma
seperated, double-quoted list of strings is most common. To
append to this list, use:
$combo->list = ( $combo->list, "append1", "append2", ... );
As suggested above, anything that you can do to a Perl list (which is a lot), you can also do to the Combo List.
Here's a typical code segment for creating a set of options:
@list = ( "String1", "String2", "String3" ); $combo->set_popdown_strings( "String1", "String2", "String3" );
Or, if you prefer terse code:
$combo->set_popdown_strings( @list );
If you want to let the user change the value in the entry using
the up/down arrow keys, use:
$combo->set_use_arrows( $use_arrows );
where
$use_arrows
is a true or false value. This doesn't bring up the list, but
rather replaces the current text in the entry with the next list
entry (up or down, as your key choice indicates). It does this
by searching in the list for the item corresponding to the
current value in the entry and selecting the previous/next item
accordingly. Usually in an entry the arrow keys are used to
change focus (you can do that anyway using TAB). Note that when
the current item is the last of the list and you press
arrow-down it changes the focus (the same applies with the first
item and arrow-up).
If the current value in the entry is not in the list, then the function of set_use_arrows() is disabled.
If you want the up/down arrow keys to cycle through the choices
in the dropdown list, except that it wraps around the values in
the list, use:
$combo->set_use_arrows_always( $use_arrows );
This will completely disable the use of the up and down arrow
keys for changing focus.
To determine whether GTK searches for entries in a case
sensitive manner or not, use:
$combo->set_case_sensitive( $case );
This is used when the Combo widget is asked to find a value from
the list using the current entry in the text box. This
completion can be performed in either a case sensitive or
insensitive manner, depending upon the use of this function. The
Combo widget can also simply complete the current entry if the
user presses the key combination MOD-1 and "Tab". MOD-1 is often
mapped to the "Alt" key, by the
xmodmap
utility. Note, however that some window managers also use this
key combination, which will override its use within GTK.
If you wish to specify whether the value entered into the entry
must be one of the items in the list, you can do so with:
$combo->set_value_in_list( $must_match, $ok_if_empty );
Where if
$must_match
is a true value, the value entered must be one of the values in
the list, and
$ok_if_empty
is a true or false value that determines if an empty field is
acceptable.
If an item in the list isn't a simple label, you might have to
tell GTK what that label is. You would do so with:
$combo->set_item_string( $item, $string );
where
$item
is the item in the list you wish to set, and
$string
is the label. Without this, GTK might not know what to put the
the entry field.
You can stop the Combo widget from showing the popup list when
the entry emits an
'activate' signal using:
$combo->disable_activate();
This could be useful if you want the Return key to close a
dialog instead. In most cases, though, you should leave it
alone.
Now that we have a combo box, tailored to look and act how we
want it, all that remains is being able to get data from the
combo box. This is relatively straightforward. Most of the
time, all you are going to care about getting data from is the
entry. The entry is accessed simply by
combo->entry
.
The two principal things that you are going to want to do with
it are attach to the activate signal, which indicates that the
user has pressed the Return or Enter key, and read the text. The
first is accomplished using something like:
$combo->entry->signal_connect( "activate", \&callback );
Getting the text at any arbitrary time is accomplished by simply
using the entry function:
$combo->entry->get_text();
Обзор Gtk-Perl | ||
---|---|---|
Предыдущий | Следующий |
Объект
+--- Widget
+--- Container
+--- Box
Контейнеры - это виджеты, которые содержат другие виджеты
Первый тип контейнера является подклассом Bin, который является потомком класса(?) Container. Эти контейнеры могут иметь только одного потомка и наследовать его возможности. Кнопки и Фреймы являются хорошим примером этог7о типа контейнеров.
Второй тип контейнеров может содержать много виджетов и используется для контроля их лайотов. Примеры такого типа приведены на страничке, описывающей поведение Box и Tables
Виджеты могут быть добавлены или удалены при помощи следующих функций
$container->add( $widget );
$container->remove( $widget );
После того, как виджеты будут добавлены к контейнеру, они не будут видимыми до тех пор, пока их не показать функцией show() или до того, как контейнер не обратится к функции show_all()
Нижеследующие функции возвращают список виджетов, находящихся в контейнере
@children = $container->children();
В данном случае граница контейнера является значением отступа в пикселах до
виджета(-ов), находящегося(-ихся) в контейнере и она(они) может(-ут) быть установлена(-ы) при
помощи следующих двух функций:
$container->border_width();
$container->set_border_width();
Первая функция определена в Gtk как макрос для второй, хотя между обоими в принципе
нет никакой разницы, однако, лучше использовать вторую функцию. Относительно get_border_width
ничего не известно.
Предыдущая | Домой | Следующая |
Обзор виджетов | Вверх | Сигналы и события |
This document, like so much of the great software out there, was created for free by volunteers. If you are at all knowledgeable about any aspect of Gtk-Perl that does not already have documentation, please consider contributing to this document.
If you do decide to contribute, please mail your text to Stephen Wilhelm, <swilhelm@computer.org>. Be aware that the entirety of this document is free (see the copyright notice ), and any addition that you provide must also be free. That is, people may use any portion of your examples in their programs, and copies of this document may be distributed at will, etc.
The only other thing I require of contributed work, is that the Gtk-Perl style of examples matche the style I use in this Tutorial. Its not that I think I have the One True Style, but because I feel consistency is important for beginners.
This document is written using DocBook so if you wish to contribute something large (like a chapter), it would be helpful if the contribution was made in DocBook SGML or XML.
Gtk-Perl Tutorial | ||
---|---|---|
Prev |
The Gtk-Perl Tutorial is Copyright (C) 2000 Stephen Wilhelm
The Gtk-Perl Tutorial is derived from the GTK Tutorial, which is Copyright (C) 1997 Ian Main, and Copyright (C) 1998-1999 Tony Gale.
The Gtk-Perl Tutorial is covered under the same terms as the GTK Tutorial, which is as follows:
Permission is granted to make and distribute verbatim copies of this manual provided the copyright notice and this permission notice are preserved on all copies.
Permission is granted to copy and distribute modified versions of this document under the conditions for verbatim copying, provided that this copyright notice is included exactly as in the original, and that the entire resulting derived work is distributed under the terms of a permission notice identical to this one.
Permission is granted to copy and distribute translations of this document into another language, under the above conditions for modified versions.
If you are intending to incorporate this document into a published work, please contact the maintainer, and we will make an effort to ensure that you have the most up to date information available.
There is no guarantee that this document lives up to its intended purpose. This is simply provided as a free resource. As such, the authors and maintainers of the information provided within can not make any guarantee that the information is even accurate.
One clarification that I would like to make on the original copyright notice, is that translations to another language include both natural and computer languages.
The CTree widget is derived from the CList widget. It is designed to display hierarchically-organised data. The tree is displayed vertically, and branches of the tree can be clapsed and expanded as required by the user.
A CTree, being derived from CList, can have multiple
columns. These columns optionally have titles that are displayed
along the top of the CTree widget. Hence there are two functions
for creating a new CTree widget:
$ctree = new Gtk::CTree( $columns, $tree_column );
$ctree = new_with_titles Gtk::CTree( $tree_column, @titles );
The $columns argument specifies the number of columns that the CTree will contain. The $tree_column argumnet specifies which of those columns is to contain the tree. Columns are numbered starting from 0.
With the second funtion above, the
@titles
argument contains a list of strings that contain the captions
for the column headings. The number of columns is determined
from the number of strings in the list. A typical code fragment
using the
new_with_titles()
function would be:
$ctree = new_with_titles Gtk::CTree( 0, "Location", "Description" );
This would create a new CTree with two columns entitled "Location" and "Description", with the first column containing the tree.
The items in a CTree are termed nodes. Nodes are inserted into a
CTree in such a way as to create a hierarchy (although the order
of insertion is not critical). The following function is used to
insert a node:
$ctree->insert_node( $parent,
$sibling,
$text,
$spacing,
$pixmap_closed,
$mask_closed,
$pixmap_opened,
$mask_opened,
$is_leaf,
$expanded );
This function looks a little daunting, but that is merely due to the power of the CTreee widget. Not all of the parameters above are required.
The CTree widget allows you to specify pixmaps to display in each node. For branch nodes, you can specify different pixmaps for when the branch is collapsed or expanded. This gives a nice visual feedback to the user, but it is optional so you don't have to specify pixmaps.
Lets have a quick look at all of the parameters:
- $parent
The parent node of the one we are inserting. May be undef for a root-level (i.e. initial) node
- $sibling
A sibling of the node we are inserting. May be undef if there are no siblings.
- $text
The textual contents of each column in the tree for this node. This must have an entry for each column, even if it is an empty string. You may be wondering how a scalar holds the text for each column. The answer is pretty simple. The scalar actually holds an anonymouse list containing each of the text labels. For example, if you have a two column tree, you should use something like this:
$text = [ "column 1", "column 2" ];
- $spacing
Specifies the padding between the nodes pixmap and text elements, if a pixmap is provided.
- $pixmap_closed
A pixmap to display for a collapsed branch node and for a leaf node.
- $mask_closed
A bitmap mask for the above pixmap.
- $pixmap_opened
A pixmap to display for an expanded branch node.
- $mask_opened
A bitmap mask for the above pixmap.
- $is_leaf
Indicates whether this is a leaf or branch node.
- $expanded
Indicates whether a branch node is initially expanded or collapsed.
An object of type GtkCTreeNode is returned by the insert_node() function. This object is used to reference the node when manipulating it. The node is also supplied by many of the CTree signals to identify which node the signal pertains to.
To remove a node for a CTree, the following function is
provided:
$ctree->remove_node( $node );
There are a number of functions that set options that pertain to
a CTree instance as a whole (rather than to a particular
node). The first group set padding attributes that effect how
the widget is drawn:
$ctree->set_indent( $indent );
$ctree->set_spacing( $spacing );
The function set_indent() sets how far a new branch is indented in relation to it's parent. The default is 20.
The function set_spacing() sets how far a node is horizontally padded from the vertical line that is drawn linking the nodes of each branch. The default is 5.
The next two functions affect the style of the lines and
expander that are drawn to represent the tree structure. An
expander is a graphical component that the user can select to
expand and collapse a branch of the tree.
$ctree->set_line_style( $line_style );
$ctree->set_expander_style( $expander_style );
The function
set_line_style()
is used to select the style of line that is drawn between nodes
of the tree. The parameter line_style can be one of:
'none'
'solid'
'dotted'
'tabbed'
The function
set_expander_style()
is used to select the style of branch expander, and the
parameter expander_style can be one of:
'none'
'square'
'triangle'
'circular'
#!/usr/bin/perl -w use Gtk ; use strict ; set_locale Gtk; init Gtk; my $false = 0; my $true = 1; my $window; my $scrolled_window; my $ctree; my $closed; my $closed_mask; my $opened; my $opened_mask; my $leaf; my $leaf_mask; my @closed_xpm = ( "16 16 6 1", " c None s None", ". c black", "X c red", "o c yellow", "O c #808080", "# c white", " ", " .. ", " ..XX. ", " ..XXXXX. ", " ..XXXXXXXX. ", ".ooXXXXXXXXX. ", "..ooXXXXXXXXX. ", ".X.ooXXXXXXXXX. ", ".XX.ooXXXXXX.. ", " .XX.ooXXX..#O ", " .XX.oo..##OO. ", " .XX..##OO.. ", " .X.#OO.. ", " ..O.. ", " .. ", " "); my @open_xpm = ( "16 16 4 1", " c None s None", ". c black", "X c #808080", "o c white", " ", " .. ", " .Xo. ... ", " .Xoo. ..oo. ", " .Xooo.Xooo... ", " .Xooo.oooo.X. ", " .Xooo.Xooo.X. ", " .Xooo.oooo.X. ", " .Xooo.Xooo.X. ", " .Xooo.oooo.X. ", " .Xoo.Xoo..X. ", " .Xo.o..ooX. ", " .X..XXXXX. ", " ..X....... ", " .. ", " "); my @leaf_xpm = ( "16 16 4 1", " c None s None", ". c black", "X c white", "o c #808080", " ", " ....... ", " .XXXXX.. ", " .XoooX.X. ", " .XXXXX.... ", " .XooooXoo.o ", " .XXXXXXXX.o ", " .XooooooX.o ", " .XXXXXXXX.o ", " .XooooooX.o ", " .XXXXXXXX.o ", " .XooooooX.o ", " .XXXXXXXX.o ", " ..........o ", " oooooooooo ", " "); # Create Window $window = new Gtk::Window( "toplevel" ); $window->set_usize( 300, 200 ); $window->set_title( "CTree Example" ); $window->signal_connect( "destroy", sub { Gtk-> exit ( 0 ); } ); $window->border_width( 5 ); $window->realize(); # Create Scrolled Window $scrolled_window = new Gtk::ScrolledWindow( undef, undef ); $window->add( $scrolled_window ); $scrolled_window->set_policy( 'automatic', 'always' ); $scrolled_window->show(); # Set up Pixmaps ($closed, $closed_mask) = initialize_pixmap( @closed_xpm ); ($opened, $opened_mask) = initialize_pixmap( @open_xpm ); ($leaf, $leaf_mask) = initialize_pixmap( @leaf_xpm ); # Create CTree $ctree = create_tree(); $ctree->signal_connect( 'select_row', \&selection_made ); $scrolled_window->add( $ctree ); $ctree->show(); $window->show(); main Gtk; exit 0; ### Subroutines # Since I am hard-coding the values of the tree, I've decided to # include all that code inside this function. Once the tree is built, # it is returned. sub create_tree { my $tree = new_with_titles Gtk::CTree( 0, "Column 1", "Column 2" ); $tree->set_column_width( 0, 150 ); my $root = insert_node( $tree, undef, ["root", "a"], $false ); my $node = insert_node( $tree, $root, ["branch", "b1"], $false ); insert_node( $tree, $node, ["leaf", "c11"], $true ); insert_node( $tree, $node, ["leaf", "c12"], $true ); insert_node( $tree, $node, ["leaf", "c13"], $true ); insert_node( $tree, $root, ["leaf", "b2"], $true ); $node = insert_node( $tree, $root, ["branch", "b3"], $false ); $node = insert_node( $tree, $node, ["branch", "c31"], $false ); insert_node( $tree, $node, ["leaf", "d311"], $true ); insert_node( $tree, $node, ["leaf", "d312"], $true ); insert_node( $tree, $node, ["leaf", "d313"], $true ); insert_node( $tree, $node, ["leaf", "d314"], $true ); return $tree; } # Given the tree, parent node (undef for root node), text, and whether # the node is to be a leaf node, add the node to the tree. sub insert_node { my ( $tree, $parent, $text, $is_leaf ) = @_; my @args; if ( $is_leaf ) { @args = ( $leaf, $leaf_mask, undef, undef, $true, $false ); } else { @args = ( $closed, $closed_mask, $opened, $opened_mask, $false, $true ); } return ( $tree->insert_node( $parent, undef, $text, 5, @args ) ); } # Callback run when the mouse is clicked inside the CTree. It does # nothing more than printing out the text label at the row and column # in the tree. sub selection_made { my ( $ctree, $row, $column ) = @_; my $node = $ctree->node_nth( $row ); my $text = $ctree->node_get_text( $node, $column ); # I think this should work, but I get a segmentation fault #my $text = $ctree->get_text( $row, $column ); print ( "($row, $column) => $text\n" ); } # Given a pre-defined xpm, return the pixmap and the mask associated # with it. sub initialize_pixmap { my @xpm = @_; my $pixmap; my $mask; my $style = $window->get_style()->bg( 'normal' ); ($pixmap, $mask) = Gtk::Gdk::Pixmap->create_from_xpm_d( $window->window, $style, @xpm ); return ( $pixmap, $mask ); } # END EXAMPLE PROGRAM
CTree Example Screenshot
Object
+--- Widget
+--- Container
+--- Bin
+--- Window
+--- Dialog
The Dialog widget is very simple, and is actually just a window with a few things pre-packed into it for you. Included in the Dialog widget is a window , vbox , and an action_area .
Dialogs simply creates a window, and then packs a VBox into the top, which contains a separator and then an HBox called the action_area .
The Dialog widget can be used for pop-up messages to the user,
and other similar tasks. It is really basic, and there is only
one function for the dialog box, which is:
$dialog = new Gtk::Dialog();
$button = new Gtk::Button( "Close" );
which creates the dialog box, and it is now up to you to use
it. You could pack a button in the
action_area
by doing something like this:
$dialog->action_area->pack_start( $button, $true, $true, 0 );
$button->show();
And you could add to the vbox area by packing, for instance, a
label in it, try something like this:
$label = new Gtk::Label( "Dialogs are groovy!" );
$dialog->vbox->pack_start( $label, $true, $true, 0 );
$label->show();
As an example in using the dialog box, you could put two buttons in the action_area, a Cancel button and an Ok button, and a label in the vbox area, asking the user a question or giving an error etc. Then you could attach a different signal to each of the buttons and perform the operation the user selects.
If the simple functionality provided by the default vertical and horizontal boxes in the two areas doesn't give you enough control for your application, then you can simply pack another layout widget into the boxes provided. For example, you could pack a table into the vertical box.
Иерархия наследования
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 );
}
Описание Gtk-Perl | ||
---|---|---|
Предыдущая | Следующая |
Некоторые виджеты GTK не являются объектами X т.к. являются исключительно дочерними. Они не могут получать события при изменении размера и т.п. Если бы хотите большего от таких типов виджетов - то виджет области события - то, что Вам необходимо.
На первый взгляд виджет области события практически бесполезен. Он ничего не отрисовывает и не отвечает ни на какие события. Однако он действительно обеспечивает панель X для дочернего виджета. Это важно, т.к. много виджетов GTK не имеют связанной X панели. Не имея X панели, виджет экономит память и улучшает работу, но с другой стороны и имеет много недостатков. Виджет без X панели не может получать события и не является перерисовывающимся в зависимости от действия пользователя с программой. Хотя название EventBox подчеркивает обработку события, виджет может также использоваться и для отсечения:
Для создания нового виджета области события используется функция:
$event = new Gtk::EventBox();
Дочерний виджет может быть добавлен на этот виджет области события так:
$event_box->add( $child_widget );
Нижеследующий пример показывает использование виджета области события. На панели можно кликнуть, вызвав выход и изменять её размеры.
#!/usr/bin/perl -w use Gtk ; use strict ; set_locale Gtk; init Gtk; my $false = 0; my $true = 1; my $window; my $event_box; my $label; # Создаем панель $window = new Gtk::Window( "toplevel" ); $window->set_title( "Виджет области события" ); $window->signal_connect( "destroy", sub { Gtk-> exit ( 0 ); } ); $window->border_width( 10 ); # Создание виджета области события и добавление его на наш toplevel (??) $event_box = new Gtk::EventBox(); $window->add( $event_box ); $event_box->show(); # Создание длинного лейбла $label = new Gtk::Label( "Нажмите тут и закончите, закончите, закончите, закончите..." ); $event_box->add( $label ); $label->show(); # укоротить. $label->set_usize( 110, 20 ); # Забиндить на нем событие $event_box->set_events( 'button_press_mask'); $event_box->signal_connect( "button_press_event", sub { Gtk-> exit ( 0 ); } ); # необходимая для X панели строка $event_box->realize(); # 58 - некоторое число 'hand1', которое не работает в силу некоторых причин $event_box->window->set_cursor( new Gtk::Gdk::Cursor( 58 ) ); $window->show(); main Gtk; exit ( 0 ); # конец примера
скриншот
Предыдущий | На главную | Следующий |
Текущая позиция | вверх | Позиционируемый виджет |
Object
+--- Widget
+--- Container
+--- Bin
+--- Window
+--- FileSelectionDialog
The file selection dialog is a quick and simple way to display a dialog box to prompt the user for a filename. It comes complete with Ok, Cancel, and Help buttons, and it's a great way to cut down on programming time.
To create a new file selection box use:
$file_dialog = new Gtk::FileSelection( $title );
To set the filename, for example to bring up a specific
directory, or give a default filename, use this function:
$file_dialog->set_filename( $filename );
To grab the text that the user has entered or clicked on, use
this function:
$file_dialog->get_filename();
You can match a pattern to a filename in the current directory
using the following function:
$file_dialog->complete( $pattern );
If a match can be made, the matched filename will appear in the text entry field of the file selection dialog. If a partial match can be made, the list of files will contain those filenames which have been partially matched.
An example of a pattern would be *.txt or gtk*.
The File Selection Dialog can show some file operation buttons.
You can show these buttons using:
$file_dialog->show_fileop_buttons();
$file_dialog->hide_fileop_buttons();
These buttons can be hidden using:
You can also access the widgets contained within the file
selection widget. These are:
dir_list
file_list
selection_entry
selection_text
main_vbox
ok_button
cancel_button
help_button
Most likely you will want to use the ok_button, cancel_button, and help_button widgets in signaling their use.
Included here is an example stolen from testgtk.c, modified to run on its own. As you will see, there is nothing much to creating a file selection widget. While in this example the Help button appears on the screen, it does nothing as there is not a signal attached to it.
#!/usr/bin/perl -w use Gtk ; use strict ; set_locale Gtk; init Gtk; my $false = 0; my $true = 1; my $file_dialog; # Create a new file selection widget $file_dialog = new Gtk::FileSelection( "File Selection" ); $file_dialog->signal_connect( "destroy", sub { Gtk-> exit ( 0 ); } ); # Connect the ok_button to file_ok_sel function $file_dialog->ok_button->signal_connect( "clicked", \&file_ok_sel, $file_dialog ); # Connect the cancel_button to destroy the widget $file_dialog->cancel_button->signal_connect( "clicked", sub { Gtk-> exit ( 0 ); } ); # Lets set the filename, as if this were a save dialog, and we are giving # a default filename $file_dialog->set_filename( "penguin.png" ); $file_dialog->show(); main Gtk; exit ( 0 ); # Get the selected filename and print it to the console sub file_ok_sel { my ( $widget, $file_selection ) = @_; my $file = $file_selection->get_filename(); print ( "$file\n" ); } # END EXAMPLE PROGRAM
File Dialog Example Screenshot
Обзор Gtk-Perl | ||
---|---|---|
Предыдущая | Следующая |
Фиксированный объект позволяет Вам помещать виджеты в пределах созданной панели. Положение виджетов также может быть изменено динамически.
Есть только три функции связанные с неподвижным виджетом:
$fixed = new Gtk::Fixed();
$fixed->put( $widget, $x, $y );
$fixed->move( $widget, $x, $y );
Функция new() позволяет вам создать новый фиксированный объект.
Функция put() помещает $widget в "неподвижное" положение, определяемое координатами $x и $y.
Функция move() двигает виджет на новую позицию.
Этот пример иллюстрирует использование объекта фиксированного положения.
#!/usr/bin/perl -w use Gtk ; use strict ; set_locale Gtk; init Gtk; my $false = 0; my $true = 1; my $x = 50; my $y = 50; my $window; my $fixed; my $button; # Создаем новую панель $window = new Gtk::Window( "toplevel" ); $window->set_title( "Фиксированный объект"); $window->signal_connect( "destroy", sub { Gtk-> exit ( 0 ); } ); # Ширина границы панели $window->border_width( 10 ); # Создаем фиксированный объект $fixed = new Gtk::Fixed(); $window->add( $fixed ); $fixed->show(); for my $i ( 1..3 ) { # Создаем кнопку с надписью "Поехали!! " $button = new Gtk::Button( "Поехали!! " ); # когда кнопка испустит сигнал нажато # будет вызвана функция move_button() возвращающая координаты новой кнопки # в соответствии с параметрами фиксированного объекта. $button->signal_connect( "clicked", \&move_button, $fixed ); # добавляем кнопку в панель, где определен фиксированный объект. $fixed->put( $button, $i * 50, $i * 50 ); # Показываем результат. $button->show(); } # Показываем всю панель $window->show(); main Gtk; exit ( 0 ); ### подпрограммы # Вызов этой функции передвигает кнопку на новое место # внутри фиксированного объекта. sub move_button { my ( $widget, $fixed ) = @_; $x = ( $x + 30 ) % 300; $y = ( $y + 50 ) % 300; $fixed->move( $widget, $x, $y ); } # конец примера
Пример работы программы
Предыдущая | на главную | Следующая |
Объединение по свойству | вверх | Текущая позиция |
Object
+--- Widget
+--- Container
+--- Notebook
+--- FontSelection
The FontSelection is a widget that allows the user to choose fonts and font styles. Most programmers don't use the FontSelection directly, but instead use a FontSelectionDialog .
The following function creates a FontSelection:
$font_selection = new Gtk::FontSelection();
To get the font from a FontSelection, call:
$font_selection->get_font();
If you only want the name of the currently selected font, you
would call:
$font_selection->get_font_name();
To set the currently selected font, you would call:
$font_selection->set_font_name( $font_name );
Where
$font_name
is a string with the name of the font to load. This function
returns a true value if the font was found, and a false value if
one wasn't.
To limit the fonts shown, you can set a filter using:
font_dialog->set_filter( $filter_type,
Where the options are:
$font_type,
$foundries,
$weights,
$slants,
$setwidths,
$spacings,
$charsets );
- $filter_type
The filter type may be either 'base' or 'user'. A base filter is permanent, but a user filter may be changed by the user.
- $font_type
The types of fonts to show. This may be any combination of 'bitmap', 'scalable', 'scalable_bitmap', or 'all'.
- $foundries
A list of strings containing the foundry names which will be shown, nor an empty list to show all foundries.
- $weights
A list of strings containing the weight names which will be shown, or an empty list to show all weights.
- $slants
A list of strings containing the slant names which will be shown, or an empty list to show all slants.
- $setwidths
A list of strings containing the setwidth names which will be shown, or an empty list to show all setwidths.
- $spacings
A list of strings containing the spacing names which will be shown, or an empty list to show all spacings.
- $charsets
A list of strings containing the charset names which will be shown, or an empty list to show all charsets.
FontSelection's have an area where the text can be previewed.
The text in this area can be get and set using:
$font_selection->get_preview_text();
$font_selection->set_preview_text( $text );
Описание Gtk-Perl | ||
---|---|---|
Предыдущая | Следующая |
Object
+--- Widget
+--- Container
+--- Bin
+--- Window
+--- FontSelectionDialog
Диалог выбора шрифта позволяет пользователям выбирать шрифты и стили, используя внутренний FontSelection виджет.
Вот функции управления диалогом:
$font_dialog = new Gtk::FontSelectionDialog( $title );
Для получения выбранного в диалоге шрифта вызовем:
$font_dialog->get_font();
Что бы получить название текущего выбранного шрифта, выполните:
$font_dialog->get_font_name();
Установить шрифт в качестве текущего в этом диалоге можно с помощью вызова:
font_dialog->set_font_name( $font_name );
Предыдущая | На главную | Следующая |
Выбор файла | Up | Статус бар |
Описание Gtk-Perl | ||
---|---|---|
Предыдущая | Следующая |
Фреймы используют для группировки и выделения нескольких виджетов в одном визуальном контейнере. Можно добавить фрейму подпись, что делает логику группировки элементов более очевидной и облегчает восприятие информации пользователем. Местоположение подписи фрейма и вид бордюра можно изменять.
Создаем фрейм:
$frame = new Gtk::Frame( $label );
$frame->set_label( $label );
Подпись к нему по умолчанию будет распложена в левом верхнем углу. Если
$label
равен null, то подписи у фрейма не будет. Изменит текст подписи позволяет
метод:
А местонахождение подписи меняется методом:
$frame->set_label_align( $xalign, $yalign );
где
$xalign
и
$yalign
принимает значения между
0.0
и
1.0.
$xalign
означает позиции подписи относительно верхней горизонтальной линии
фрейма.
$yalign
пока не поддерживается. По умолчанию
$xalign
равно
0.0
что, как было замечено, помещает подпись в левый верхний угол.
Следующая функция измения стиля рамки фрейма:
$frame->set_shadow_type( $type );
'none'
где
$type
может принимать одно из следующих значений:
'in'
'out'
'etched_in' (по умолчанию)
'etched_out'
Проилюстрируем использование фреймов.
#!/usr/bin/perl -w use Gtk ; use strict ; set_locale Gtk; init Gtk; my $false = 0; my $true = 1; my $i; my $window; my $frame; my $button; # Создаем окно $window = new Gtk::Window( "toplevel" ); $window->set_title( "Frame Example" ); $window->signal_connect( "destroy", sub { Gtk-> exit ( 0 ); } ); $window->set_usize( 300, 300 ); $window->border_width( 10 ); # Создаем фрейм $frame = new Gtk::Frame(); $window->add( $frame ); # Устанавливаем подпись фрейму $frame->set_label( "Gtk Frame Widget" ); # Помещаем подпись в правый верхний угол фрейма $frame->set_label_align( 1.0, 0.0 ); # Меняем стиль рамки $frame->set_shadow_type( 'etched_out' ); $frame->show(); $window->show(); main Gtk; exit ( 0 ); # КОНЕЦ ПРИМЕРА
Frame Example Screenshot
Описание Gtk-Perl | ||
---|---|---|
Предыдущая | Следующая |
Эти части документа описывают возможности Gtk которые можно применить ко всем виджетам Gtk в целом. Они включают в себя таймеры, контроль ввода/вывода, цветовые гаммы, стили виджетов, файлы ресурсов и перетаскивания мышкой.
Предыдущая | На главную | Следующая |
Уровни прокрутки | Таймеры, контроль ввода/вывода и функции ожидания |
Начиная введение в Gtk-perl, приведем пример простейшей программы. Эта программа создает маленькое окошко с одной кнопкой, на которой написано "Прощай, Мир!". Нажимая на кнопку или закрывая окно, мы закончим действие программы.
#!/usr/bin/perl -w
use Gtk; # загрузить Gtk-perl модуль
use strict; # хорошая идея для всех нетривиальных perl-скриптов
set_locale Gtk; # локализация
init Gtk; # инициализация Gtk-Perl
# для удобства объявим переменные true и false
my $false = 0;
my $true = 1;
# создаем виджет
my $window = new Gtk::Window( "toplevel" );
my $button = new Gtk::Button( "Прощай, Мир!" );
# регистрация отзыва
$window->signal_connect( "delete_event", \&CloseAppWindow );
$button->signal_connect( "clicked", \&CloseAppWindow );
# показать кнопку
$button->show();
# установить атрибуты окна и показать его
$window->border_width( 15 );
$window->add( $button );
$window->show();
# вызываем Gtk
main Gtk;
# конец программы
exit(0);
### Вызвать подпрограмму, закрывающую окно
sub CloseAppWindow{
Gtk->exit(0);
return $false
}
Разберем работу программы.
use Gtk; необходимо во всех Gtk-Perl программах. Данная строчка позволяет Перлу использовать переменные, функции, структуры, и т.д., которые определены в GTK.
init Gtk; также необходимо включать во все Ctk-Perl программы. Эта строка инициализирует модуль Gtk и определяет некоторые вещи вроде цветовой палитры или вида графического вывода.
set_locale Gtk; локализация, необходимая для корректного написания языков, с отличной от латиницы символикой.
new Ctk::Window() создает новое окно. Window Manager определяет как и где быдет выводиться создаваемое окно. Все GUI виджеты располагаются внутри нового окна, также вы можете создавать больше окон в своей программе. Вы также можете создавать диалоговые окна, используя new Gtk::Dialog();
new Gtk::Button(); создает новое окно. В нашем примере мы создаем одну кнопку с тектовым полем. Что произойдет если не поставить текст внутри кнопки? Gtk автоматически подстраивает размер окна в зависимости от длинны набранного на кнопке текста.
Функция border_width() берет container(например window) и устанавливает размер свободного места вокруг кнопки. Параметр, передаваемый функции(в пикселах), является шириной отступа.
signal_connect() связывает обработку события или сигнала с вызовом подпрограммы, например по нажатию на кнопке мышью. Сигнал вызывает подпрограмму, которая завершает работу программы. В нашем примере первый аргумент, передаваемый функции signal_connect() является строкой с именем события, которое вы хотите сгенерировать по нажатию кнопки и второй аргумет является ссылкой на подпрограмму, обрабатывающую это событие. Различные сигналы могут требовать различных аргументов, передаваемых функции signal_connect().
Функция add() создает виджет и добавлет его в контейнет(в нашем примере на окно). Если вы не добавите эту функцию, то не увидите кнопку, потому, что её не будет внутри созданного Gtk окна.
Функция show() делает виджет видимым. Не выполняйте show() до того, как определите все свойства виджета. Если создается несколько дочерних виджетов, то их необходимо создавать до родительского виджета(т.е. показать кнопку до показа содержащего её окна).
main Gtk; запускает основной обработчик событий Gtk. Эта строчка должна всегда находится в каждой Cgk-Perl программе. Когда компилятор достигнет этой строки, Gtk приостановит события для X-сервера(такие как нажатие клавиши или мышиной кнопки), таймауты или file IO до получения соответствующего сигнала.
Последняя подпрограмма вызывается, когда происходит нажате кнопки или закрыте окна.
Предыдущая | Начало | Следующая |
О Gtk-Perl | Вверх | Обзор виджетов |
Описание Gtk-Perl | ||
---|---|---|
Предыдущий | Следующий |
Эти части описывают основные концепции графического программирования при помощи GTK-Perl В рассмотрение включены битовые картинка, изображения, контурные изображения, цвета и текст.
Предыдущая | на главную | Следующая |
Таймеры, ввод/вывод и функции ожидания(idle) | Битовая графика |
The HandleBox is a container widget that allows its children to detach from a window. This is usually used for detachable toolbars, as shown in the Toolbar example .
You can create a HandleBox with the following function:
$handlebox = new Gtk::HandleBox();
You can set the HandleBox's shadow type using:
$handlebox->set_shadow_type( $shadow_type );
Where
$shadow_type
is either
'none',
'in',
'out',
'etched_in', or
'etched_out'.
You can set which side of the HandleBox the handle is drawn
using:
$handlebox->set_handle_position( $handle_position );
Where
$handle_position
is either
'left',
'right',
'top', or
'bottom'.
You can also set the snap edge of a HandleBox. The snap edge is
the edge of the detached child that must be aligned with the
corresponding edge of the "ghost" left behind when the child was
detached to reattach the torn-off window. The snap edge is set
using:
$handlebox->set_snap_edge( $snap_edge );
The values for
$snap_edge
are the same as for
$handle_position
above. Usually, the snap edge should be chosen so that it stays
in the same place on the screen when the handlebox is torn off.
If the snap edge is not set, then an appropriate value will be
guessed from the handle position. If the handle position is
'right' or
'left',
then the snap edge will be
'top',
otherwise it will be
'left'.
Обзор Gtk Perl | ||
---|---|---|
Предыдущая | Следующая |
Цель этого описания - дать обзор Gtk-Perl в целом. После его прочтения Вы получите представление о том, что такое Gtk, Gtk-Perl, виджеты, контейнеры, как виджеты используют сигналы и события.
Предыдущая | Главная | Следующая |
Обзор Gtk-Perl | О Gtk-Perl |
А теперь пример. Объяснения и комментарии следуют.
#!/usr/bin/perl -w use Gtk ; use strict ; set_locale Gtk; init Gtk; my $false = 0; my $true = 1; # Эта the GtkItemFactoryEntry структура используется для генерации новых меню.. # Запись может включать в себя следующие пункты. # Item 1: path - Местонахождение пункта в меню. Буква после подчеркивания указывает на # на клавишу быстрого вызова, этого пункта после открытия меню. # Item 2: The accelerator key for the entry # Item 3: The callback function. # Item 4: The callback action. This changes the parameters with # which the function is called. The default is 0. # Item 5: The item type, used to define what kind of an item it is. # Here are the possible values: # NULL -> "<Item>" # "" -> "<Item>" # "<Title>" -> create a title item # "<Item>" -> create a simple item # "<CheckItem>" -> create a check item # "<ToggleItem>" -> create a toggle item # "<RadioItem>" -> create a radio item # <path> -> path of a radio item to link against # "<Separator>" -> create a separator # "<Branch>" -> create an item to hold sub items (optional) # "<LastBranch>" -> create a right justified branch my @menu_items = ( { path => '/_File', type => '<Branch>' }, { path => '/File/_New', accelerator => '<control>N', callback => \&print_hello }, { path => '/File/_Open', accelerator => '<control>O', callback => \&print_hello }, { path => '/File/_Save', accelerator => '<control>S', callback => \&print_hello }, { path => '/File/Save _As' }, { path => '/File/sep1', type => '<Separator>' }, { path => '/File/Quit', callback => sub { Gtk-> exit ( 0 ); } }, { path => '/_Options', type => '<Branch>' }, { path => '/Options/Test' }, { path => '/_Help', type => '<LastBranch>' }, { path => '/_Help/About' } ); my $window; my $main_vbox; my $menubar; # Create the window $window = new Gtk::Window( 'toplevel' ); $window->signal_connect( 'destroy', sub { Gtk-> exit ( 0 ); } ); $window->set_title( "Item Factory" ); $window->set_usize( 300, 200 ); $main_vbox = new Gtk::VBox( $false, 1 ); $main_vbox->border_width( 1 ); $window->add( $main_vbox ); $main_vbox->show(); # Create the menu bar $menubar = create_menu_bar( $window ); $main_vbox->pack_start( $menubar, $false, $true, 0 ); $menubar->show(); $window->show(); main Gtk; exit ( 0 ); ### Subroutines # Obligatory basic callback sub print_hello { print ( "Hello World!\n" ); } # Crete the menu bar, initialize its menus, and return the menu bar. sub create_menu_bar { my ( $window ) = @_; my $menubar; my $item_factory; my $accel_group; $accel_group = new Gtk::AccelGroup(); # This function initializes the item factory. # Param 1: The type of menu - can be 'Gtk::MenuBar', 'Gtk::Menu', # or 'Gtk::OptionMenu'. # Param 2: The path of the menu. # Param 3: The accelerator group. The item factory sets up # the accelerator table while generating menus. $item_factory = new Gtk::ItemFactory( 'Gtk::MenuBar', '<main>', $accel_group ); # This function generates the menu items. Pass the item factory, # the number of items in the array, the array itself, and any # callback data for the the menu items. $item_factory->create_items( @menu_items ); # Attach the new accelerator group to the window. $window->add_accel_group( $accel_group ); # Finally, return the actual menu bar created by the item factory. #*menubar = gtk_item_factory_get_widget (item_factory, "<main>"); return ( $item_factory->get_widget( '<main>' ) ); } # END EXAMPLE PROGRAM
Item Factory Example Screenshot
Иерархия наследования
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 );
Вставить скриншот
Описание Gtk-Perl | ||
---|---|---|
Предыдущая | Следующая |
Объект расположения подбен фиксированному объекту расположеня, за исключением того, что может делать бесконечную область прокрутки (где бесконечность меньше 232). Система панелей X имеет ограничение на размер ширины или высоты панели в 32767 пикселей. Объект расположения обходит это ограничение при помощи необычной панели и т.н. bit gravitie так, что вы можете видеть "гладкий" скролл, даже в случае мнгоих дочерних виджетов в области прокрутки.
Объект расположения создается при помощи функции:
$layout = new Gtk::Layout( $hadjustment, $vadjustment );
Как вы можете видеть, возможно произвольно определять выравнивание (Adjustment) объектов, которые будет скроллится.
Можно также добавлять и двигать виждеты для скроллинга при помощи
следующих двух функций:
$layout->put( $widget, $x, $y );
$layout->move( $widget, $x, $y );
Размер скроллинга может быть выставлен при помощи следующей функции
$layout->set_size( $width, $height );
Виджет уровня прокрутки - один из очень немногих виджетов в наборе GTK, который активно перерисовывает мебя на экране.
Если Вы хотите сделать очень большое изменениие на виджете уровня прокрутки
- вам
необходимо использовать две нижепреведенные функции, которые отключают и
после включают перерисовку.
$layout->freeze();
$layout->thaw();
Последние четыре функции предназначены для управления коризонтальными и
вертикальным виджетами выравнивания:
$layout->get_hadjustment();
$layout->get_vadjustment();
$layout->set_hadjustment( $adjustment );
$layout->set_vadjustment( $adjustment );
Предыдущая | на главную | Следующая |
Позиционируемый виджет | Вверх | Базовые возможности |
The List widget is designed to act as a vertical container for widgets that should be of the type ListItem. A List widget has its own window to receive events and its own background color which is usually white.
In order to keep from confusing you, a List (capitalized) refers to a Gtk::List widget, while a list (lowercase) refers to a Perl list (which may also be referred to, somewhat inaccurately, as arrays).
There is two fields inside the structure definition of the List widget that will be of great interest to us, they are selection and selection_mode .
The selection field of a List is a list of all items that are currently selected, or the empty list if the selection is empty. So to learn about the current selection we read the selection field, but do not modify it since the internal fields are maintained by the List functions.
The selection_mode of the List determines the selection facilities of a List and therefore the contents of the selection field. The selection_mode may be one of the following:
'single' - The selection is either empty or its list contains a single selected item.
'browse' - The selection is empty if the list contains no widgets or insensitive ones only, otherwise it contains a list with one list item.
'multiple' - The selection is empty if no list items are selected or list of all the selected items.
'extended' - Any number of elements may be selected. Click-drag selects a range of elements. The Ctrl key may be used to enlarge the selection, and Shift key to select between the focus and the child pointed to.
The default is 'multiple'.
The 'selection changed' signal will be invoked whenever the selection field of a List has changed. This happens when a child of the List got selected or deselected.
The 'select_child' signal is invoked when a child of the List is about to get selected. This happens mainly on calls to select_item(), select_child(), button presses and sometimes indirectly triggered on some else occasions where children get added to or removed from the List.
The 'unselect_child' signal is invoked when a child of the List is about to get deselected. This happens mainly on calls to unselect_item(), unselect_child(), button presses and sometimes indirectly triggered on occassions where children get added to or removed from the List.
To create a new List, use:
$list = new Gtk::List();
Items may be added to the List using:
$list->insert_items( @items, $position );
where
@items
is the list of items to add, and
$position
is the starting position of the items.
You can also append and prepend items to the List using:
$list->append_items( @items );
$list->prepend_items( @items );
To remove items from the list, use:
$list->remove_items( @items );
Where
@items
is a list of the items you want removed.
You can also remove a range of items using:
$list->clear_items( $start, $end );
Items can be selected using:
$list->select_item( $index );
$list->select_child( $child );
which will also invoke either the
'select_item'
or the
'select_child'
signal on the list item.
Unselecting works in a similar way:
$list->unselect_item( $index );
$list->unselect_child( $child );
If you want the index for a List child, use:
$index = $list->child_position( $child );
If a failure occurs, a value of
-1
is returned.
The selection mode can be set using:
$list->set_selection_mode( $mode );
Where
$mode
can be
'single',
'browse',
'multiple', or
'extended'.
Object
+--- Widget
+--- Container
+--- Bin
+--- Item
+--- ListItem
The ListItem widget is designed to act as a container holding up to one child, providing functions for selection/deselection just like the List widget requires them for its children.
A ListItem has its own window to receive events and has its own background color which is usually white.
As it is directly derived from an Item it can be treated as such. See the Item widget for more on this. Usually a ListItem just holds a label to identify, e.g., a filename within a List -- therefore the convenience function new_with_label() is provided. The same effect can be achieved by creating a Label on its own, setting its alignment to xalign=0 and yalign=0.5 with a subsequent container addition to the ListItem.
As one is not forced to add a GtkLabel to a GtkListItem, you could also add another widget (such as GtkVBox, GtkArrow, etc.) to the GtkListItem.
To create a ListItem, call one of the following functions:
$item = new Gtk::ListItem();
$item = new Gtk::ListItem( $label );
If you send a string as an argument, it creates the ListItem
with a Label as the sole child of the ListItem.
To select a ListItem:
$item->select();
which will also emit the
'select'
signal on the ListItem.
Following is an example program that will print out the changes of the selection of a List, and lets you "arrest" list items into a prison by selecting them with the rightmost mouse button.
#!/usr/bin/perl -w use Gtk ; use strict ; set_locale Gtk; init Gtk; my $false = 0; my $true = 1; my $separator; my $window; my $vbox; my $scrolled_window; my $frame; my $gtklist; my $button; my $list_item; my $buffer; # Create the window $window = new Gtk::Window( 'toplevel' ); $window->set_title( "List Example" ); $window->signal_connect( 'destroy', sub { Gtk-> exit ( 0 ); } ); # Inside the window we need a box to arrange the widgets vertically $vbox = new Gtk::VBox( $false, 5 ); $vbox->set_border_width( 5 ); $window->add( $vbox ); $vbox->show(); # This is the scrolled window to put the List widget inside $scrolled_window = new Gtk::ScrolledWindow( undef, undef ); $scrolled_window->set_usize( 250, 150 ); $vbox->add( $scrolled_window ); $scrolled_window->show(); # Create the List widget. Connect the sigh_print_selection() signal handler # function to the "selection_changed" signal of the List to print out the # selected items each time the selection has changed. $gtklist = new Gtk::List(); $scrolled_window->add_with_viewport( $gtklist ); $gtklist->show(); $gtklist->signal_connect( 'selection_changed', \&sigh_print_selection ); # We create a "Prison" to put a list item in ;) $frame = new Gtk::Frame( "Prison" ); $frame->set_usize( 200, 50 ); $frame->set_border_width( 5 ); $frame->set_shadow_type( 'out' ); $vbox->add( $frame ); $frame->show(); # Connect the sigh_button_event() signal handler to the List, which will # handle the "arresting" of list items. $gtklist->signal_connect( 'button_release_event', \&sigh_button_event, $frame ); # Create a separator $separator = new Gtk::HSeparator(); $vbox->add( $separator ); $separator->show(); # Finally create a button and connect its "clicked" signal to the # destruction of the window $button = new Gtk::Button( "Close" ); $vbox->add( $button ); $button->show(); $button->signal_connect( 'clicked', sub { $window->destroy(); } ); # Now we create 5 list items, each having its own label and add them to # the List using add(). for my $i ( 0..4 ) { my $label; my $string; $buffer = "ListItemContainer with Label #" . $i; $label = new Gtk::Label( $buffer ); $list_item = new Gtk::ListItem(); $list_item->add( $label ); $label->show(); $gtklist->add( $list_item ); $list_item->show(); $string = $label->get(); } # Here, we are creating another 5 labels, this time sending the label to # the new() function. for my $i ( 5..9 ) { $buffer = "List Item with Label $i"; $list_item = new Gtk::ListItem( $buffer ); $gtklist->add( $list_item ); $list_item->show(); } # Finally we want to see the window, don't we? ;) $window->show(); # Fire up the main event loop of gtk main Gtk; exit ( 0 ); ### Subroutines # This is the signal handler that got connected to button press/release # events of the List sub sigh_button_event { my ( $gtklist, $frame, $event ) = @_; # We only do something if the third (rightmost mouse button) # was released if ( ( defined( $event->{ 'type' } ) ) and ( defined( $event->{ 'button' } ) ) and ( $event->{ 'type' } eq 'button_release' ) and ( $event->{ 'button' } == 3 ) ) { my @dlist = $gtklist->selection; my $new_prisoner = $dlist[0]; my $list_item; # Look for already imprisoned list items, we will put them back # into the list. foreach $list_item ( $frame->children() ) { $list_item->reparent( $gtklist ); } # If we have a new prisoner, remove him from the List and put him # into the frame "Prison". We need to unselect the item first. if ( $new_prisoner ) { $gtklist->unselect_child( $new_prisoner ); $new_prisoner->reparent( $frame ); } } return $true; } # This is the signal handler that gets called if List emits the # "selection_changed" signal sub sigh_print_selection { my ( $gtklist ) = @_; # Fetch the currently selected list item which will be our next # prisoner my @dlist = $gtklist->selection; # If there are no selected items there is nothing more to do than # just telling the user so unless ( @dlist ) { print "Selection cleared\n"; } } # END EXAMPLE PROGRAM
List Example Screenshot
These chapters are designed to document widgets used for list and tree data. After completing these chapters you should know how to create lists and trees and manipulate their data.
What users think of as menus are really three parts. First, there is the MenuBar at the top of the window. Second, inside the MenuBar are several Menus. And third, each Menu usually consists of one or more MenuItems.
Both the MenuBar widget and the Menu widget are subclasses of MenuShell.
Each MenuShell has the ability to append, prepend, or insert
child widgets:
$menushell->append( $child );
$menushell->prepend( $child );
$menushell->insert( $child, $position );
The MenuShell can be erased from the screen by:
$menushell->deactivate()
A child in the MenuShell can be selected using:
$menushell->select_item( $child );
A child in the MenuShell can be activated using:
$menushell->activate_item( $child );
Object
+--- Widget
+--- Container
+--- MenuShell
+--- MenuBar
A MenuBar can be created using:
$menubar = new Gtk::MenuBar();
Menu bars are usually placed at the top of the window. Normally, you would create a VBox and add it to the window. You should add the menu bar to the top of that VBox.
The only other function for menu bars (that doesn't come from
MenuShell, that is) sets the shadow type:
$menubar->set_shadow_type( $shadow_type );
Where
$shadow_type
is either
'none',
'in',
'out',
'etched_in', or
'etched_out'.
Menus are created using:
$menu = new Gtk::Menu();
If you want to move a child from one position to another, you
can do so using:
$menu->reorder_child( $child, $position );
Where
$child
is the child to move, and
$position
is the new position for the child.
Menus can have a title associated with them. This title is set
using:
$menu->set_title( $title );
The tearoff state of the menu can be set using:
$menu->set_tearoff_state( $tear_off );
Where
$tear_off
is a true or false value that determines whether the menu can
tear off. A menu is normally displayed as a drop down menu that
persists as long as the menu is active, but a tearoff menu is
enclosed in a window which persists until the window is closed.
Finally, if you want the menu to act as a popup menu, you would
call:
$menu->popup( $parent_menu_shell,
Where
$parent_menu_shell and
$parent_menu_item
will be undefined if the menu is not associated with a menu bar.
For
$activate_time
you can usually get away with
$event->{ 'time' }
but if you desire that the menu go away after releasing the
mouse button, you should put in a
0.
The
$button
argument will usually come from
$event->{ 'button' }.
And finally,
\&menu_position_function
is a reference to a user supplied function used to position the
menu. Most people will just use
undef,
which defaults the menu's top-left position to the location of
the mouse click.
@optional_data,
if included, is sent as the argument to
\&menu_position_function.
$parent_menu_item,
$activate_time,
$button,
\&menu_position_function,
@optional_data );
Expect this function to change soon. It is really supposed to
have the
$button
and
$activate_time
arguments switched around, like this:
$menu->popup( $parent_menu_shell,
$parent_menu_item,
$button,
$activate_time,
\&menu_position_function,
@optional_data );
Object
+--- Widget
+--- Container
+--- Bin
+--- Item
+--- MenuItem
Creating a MenuItem is as simple as calling one the following
functions:
$menuitem = new Gtk::MenuItem();
$menuitem = new Gtk::MenuItem( $label );
You can select, deselect, and activate a MenuItem using:
$menuitem->select();
$menuitem->deselect();
$menuitem->activate();
If you want to make a MenuItem a submenu, you would do so using:
$menuitem->set_submenu( $menu );
Also, you can remove a submenu using:
$menuitem->remove_submenu();
Lastly, if you want the menu right justified on the menubar,
such as help menus often are (on Unix systems, anyway), you can
use the following function before attaching it to the MenuBar:
$menu_item->right_justify();
There are two ways to create menus: there's the easy way, and there's the hard way. The "hard" way is to create all the menus using the above calls directly. The easy way is to use the ItemFactory calls. This is much simpler, but there are advantages and disadvantages to each approach.
The Itemfactory is much easier to use, and to add new menus to, although writing a few wrapper functions to create menus using the manual method could go a long way towards usability. With the Itemfactory, it is not possible to add images or the character '/' to the menus.
In the true tradition of teaching, we'll show you the hard way first. The ItemFactory widget is described in its own chapter .
There are three widgets that go into making a menubar and submenus:
a menu item, which is what the user wants to select, e.g., "Save"
a menu, which acts as a container for the menu items, and
a menubar, which is a container for each of the individual menus.
This is slightly complicated by the fact that menu item widgets are used for two different things. They are both the widgets that are packed into the menu, and the widget that is packed into the menubar, which, when selected, activates the menu.
Once a Menu is created; it is never actually shown (with the show() function), it is just a container for the menu items. I hope this will become more clear when you look at the example below.
Once you've created a menu item you have to put it into a
menu. This is done using the
append()
function. In order to capture when the item is selected by the
user, we need to connect to the
'activate'
signal. So, if we wanted to create a standard
File
menu, with the options
Open,
Save, and
Quit,
the code would look something like:
$file_menu = new Gtk::Menu();
# Create the menu items
$open_item = new Gtk::MenuItem( "Open" );
$save_item = new Gtk::MenuItem( "Save" );
$quit_item = new Gtk::MenuItem( "Quit" );
# Add them to the menu
$file_menu->append( $open_item );
$file_menu->append( $save_item );
$file_menu->append( $quit_item );
# Attach the callback functions to the activate signal
$open_item->signal_connect( 'activate', \&file_open );
$save_item->signal_connect( 'activate', \&file_save );
$quit_item->signal_connect( 'activate', \&file_quit );
# We do not need the show the menu, but we do need to show the menu items
$open_item->show();
$save_item->show();
$quit_item->show();
At this point we have our menu. Now we need to create a menubar
and a menu item for the
File
entry, to which we add our menu. The code looks like this:
$menu_bar = new Gtk::MenuBar();
$window->add( $menu_bar );
$menu_bar->show();
$file_item = new Gtk::MenuItem( "File" );
$file_item->show();
Now we need to associate the menu with $file_menu. This is done with the set_submenu() function.
All that is left to do is to add the menu to the menubar, which is accomplished using the append() function.
Here is a summary of the steps needed to create a menu bar with menus attached:
Create a new menu using new Gtk::Menu()
Use multiple calls to new Gtk::MenuItem() for each item you wish to have on your menu. And use append() to put each of these new items on to the menu.
Create a menu item using new Gtk::MenuItem(). This will be the root of the menu, the text appearing here will be on the menubar itself.
Use set_submenu() to attach the menu to the root menu item (the one created in the above step).
Create a new menubar using new Gtk::MenuBar(). This step only needs to be done once when creating a series of menus on one menu bar.
Use append() to put the root menu onto the menubar.
Creating a popup menu is nearly the same. The difference is that the menu is not posted "automatically" by a menubar, but explicitly by calling the popup() function from a button-press event, for example. Take these steps:
Create an event handling function and use the event to find out where to pop up the menu.
In the event handler, if the event is a mouse button press, treat event as a button event (which it is) and use it as shown in the sample code to pass information to popup().
Bind that event handler to a widget with signal_connect().
That should about do it. Let's take a look at an example to help clarify.
#!/usr/bin/perl -w use Gtk ; use strict ; set_locale Gtk; init Gtk; my $false = 0; my $true = 1; my $window; my $menu; my $menubar; my $root_menu; my $menu_item; my $vbox; my $button; # create a new window $window = new Gtk::Window( 'toplevel' ); $window->set_usize( 200, 100 ); $window->set_title( "GTK Menu Test" ); $window->signal_connect( 'delete_event', sub { Gtk-> exit ( 0 ); } ); # Init the menu-widget, and remember -- never show() the menu widget!! # This is the menu that holds the menu items, the one that will pop up # when you click on the "Root Menu" in the app $menu = new Gtk::Menu(); # Next we make a little loop that makes three menu-entries for "test-menu". # Notice the call to append(). Here we are adding a list of menu items to # our menu. Normally, we'd also catch the "clicked" signal on each of the # menu items and setup a callback for it, but it's omitted here to save # space. for my $i ( 0..2 ) { my $buffer; # Copy the names into the buffer $buffer = "Test-undermenu - $i"; # Create a new menu-item with a name... $menu_item = new Gtk::MenuItem( $buffer ); # and add it to the menu. $menu->append( $menu_item ); # Do something interesting when the menuitem is selected $menu_item->signal_connect( 'activate', sub { print ( "$buffer\n" ); } ); # Show the widget $menu_item->show(); } # This is the root menu, and will be the label displayed on the menu bar. # There won't be a signal handler attached, as it only pops up the rest # of the menu when pressed. $root_menu = new Gtk::MenuItem( "Root Menu" ); $root_menu->show(); # Now we specify that we want our newly created "menu" to be the menu # for the "root menu" $root_menu->set_submenu( $menu ); # A vbox to put a menu and a button in: $vbox = new Gtk::VBox( $false, 0 ); $window->add( $vbox ); $vbox->show(); # Create a menu-bar to hold the menus and add it to our main window $menubar = new Gtk::MenuBar(); $vbox->pack_start( $menubar, $false, $false, 2 ); $menubar->show(); # Create a button to which to attach menu as a popup $button = new Gtk::Button( "Press Me" ); $button->signal_connect( 'event', \&button_press, $menu ); $vbox->pack_end( $button, $true, $true, 2 ); $button->show(); # And finally we append the menu-item to the menu-bar -- this is the # "root" menu-item I have been raving about =) $menubar->append( $root_menu ); # always display the window as the last step so it all splashes on # the screen at once. $window->show(); main Gtk; exit ( 0 ); ### Subroutines # Respond to a button-press by posting a menu passed in as widget. # Note that the "widget" argument is the menu being posted, NOT # the button that was pressed. sub button_press { my ( $button, $menu, $event ) = @_; if ( defined( $event->{ 'type' } ) and ( $event->{ 'type' } eq 'button_press' ) ) { $menu->popup( undef, undef, $event->{'time'}, $event->{'button'}, undef ); # Tell calling code that we have handled this event; the buck # stops here. return ( $true ); } # Tell calling code that we have not handled this event; pass it on. return ( $false ); } # END EXAMPLE PROGRAM
Menu Example Screenshot
You may also set a menu item to be insensitive and, using an accelerator table, bind keys to menu functions.
The NoteBook Widget is a collection of "pages" that overlap each other, each page contains different information with only one page visible at a time. This widget has become more common lately in GUI programming, and it is a good way to show blocks of similar information that warrant separation in their display.
The first function call you will need to know, as you can
probably guess by now, is used to create a new notebook widget.
$notebook = new Gtk::Notebook();
Once the notebook has been created, there are a number of functions that operate on the notebook widget. Let's look at them individually.
The first one we will look at is how to position the page
indicators. These page indicators or "tabs" as they are
referred to, can be positioned in four ways: top, bottom, left,
or right.
$notebook->set_tab_pos( $position );
'left'
Where
$position
will be one of the following, which are pretty self explanatory:
The default is
'top'
.
'right'
'top'
'bottom'
Next we will look at how to add pages to the notebook. There are
three ways to add pages to the NoteBook. Let's look at the first
two together as they are quite similar.
$notebook->append_page( $child, $tab_label );
$notebook->prepend_page( $child, $tab_label );
These functions add pages to the notebook by inserting them from
the back of the notebook (append), or the front of the notebook
(prepend).
$child
is the widget that is placed within the notebook page, and
$tab_label
is the label for the page being added. The
$child
widget must be created separately, and is typically a set of
options setup within one of the other container widgets, such as a
packing box or table.
The final function for adding a page to the notebook contains all
of the properties of the previous two, but it allows you to
specify what position you want the page to be in the notebook.
$notebook->insert_page( $child, $tab_label, $position );
The parameters are the same as
append() and
prepend()
except it contains an extra parameter,
$position.
This parameter is used to specify what place this page will be
inserted into, with the first page having a position of zero.
Now that we know how to add a page, lets see how we can remove a
page from the notebook.
$notebook->remove_page( $page_num );
This function takes the page specified by
$page_num
and removes it from the notebook.
To find out what the current page is in a notebook use the function:
$notebook->get_current_page();
And to find out what page number a page is, use:
$notebook->page_num( $child );
This function will return a
-1
if
$child
isn't a page in
$notebook.
If you want to change a child's page number, you may do so with:
$notebook->reorder_child( $child, $position );
These next two functions are simple calls to move the notebook
page forward or backward. Simply provide the respective function
call with the notebook widget you wish to operate on. Note: When
the NoteBook is currently on the last page, and
next_page()
is called, the notebook will wrap back to the first
page. Likewise, if the NoteBook is on the first page, and
prev_page()
is called, the notebook will wrap to the last page.
$notebook->next_page();
$notebook->prev_page();
This next function sets the "active" page. If you wish the
notebook to be opened to page 5 for example, you would use this
function. Without using this function, the notebook defaults to
the first page.
$notebook->set_page( $page_num );
The next two functions add or remove the notebook page tabs and
the notebook border respectively.
$notebook->set_show_tabs( $show_tabs );
$notebook->set_show_border( $show_border );
The next function is useful when the you have a large number of
pages, and the tabs don't fit on the page. It allows the tabs to
be scrolled through using two arrow buttons.
$notebook->set_scrollable( $scrollable );
The border width around the bookmarks may be set using:
$notebook->set_tab_border( $border_width );
Also, you can decide whether all the tabs are the same size or not
using:
$notebook->set_homogeneous_tabs( $homogeneous );
Where
$homogeneous
may be a true or false value.
Now let's look at an example, it is expanded from the testgtk.c code that comes with the GTK distribution. This small program creates a window with a notebook and six buttons. The notebook contains 11 pages, added in three different ways, appended, inserted, and prepended. The buttons allow you to rotate the tab positions, add/remove the tabs and border, remove a page, change pages in both a forward and backward manner, and exit the program.
#!/usr/bin/perl -w use Gtk ; use strict ; set_locale Gtk; init Gtk; my $false = 0; my $true = 1; my $window; my $button; my $table; my $notebook; my $frame; my $label; my $checkbutton; my $bufferf; my $bufferl; # Create the window $window = new Gtk::Window( "toplevel" ); $window->signal_connect( "delete_event", sub { Gtk-> exit ( 0 ); } ); $window->border_width( 10 ); $table = new Gtk::Table( 3, 6, $false ); $window->add( $table ); # Create a new notebook, place the position of the tabs $notebook = new Gtk::Notebook(); $notebook->set_tab_pos( 'top' ); $table->attach_defaults( $notebook, 0, 6, 0, 1 ); $notebook->show(); # Let's append a bunch of pages to the notebook for my $i ( 0..4 ) { $bufferf = "Append Frame " . ( $i + 1 ); $bufferl = "Page " . ( $i + 1 ); $frame = new Gtk::Frame( $bufferf ); $frame->border_width( 10 ); $frame->set_usize( 100, 75 ); $frame->show(); $label = new Gtk::Label( $bufferf ); $frame->add( $label ); $label->show(); $label = new Gtk::Label( $bufferl ); $notebook->append_page( $frame, $label ); } # Now let's add a page to a specific spot $checkbutton = new Gtk::CheckButton( "Check me please!" ); $checkbutton->set_usize( 100, 75 ); $checkbutton->show(); $label = new Gtk::Label( "Add Page" ); $notebook->insert_page( $checkbutton, $label, 2 ); # Now finally let's prepend pages to the notebook for my $i ( 0..4 ) { $bufferf = "Prepend Frame " . ( $i + 1 ); $bufferl = "Page " . ( $i + 1 ); $frame = new Gtk::Frame( $bufferf ); $frame->border_width( 10 ); $frame->set_usize( 100, 75 ); $frame->show(); $label = new Gtk::Label( $bufferf ); $frame->add( $label ); $label->show(); $label = new Gtk::Label( $bufferl ); $notebook->prepend_page( $frame, $label ); } # Set what page to start at (page 4) $notebook->set_page( 3 ); # Create a bunch of buttons $button = new Gtk::Button( "Close" ); $button->signal_connect( "clicked", sub { Gtk-> exit ( 0 ); } ); $table->attach_defaults( $button, 0, 1, 1, 2 ); $button->show(); $button = new Gtk::Button( "Next Page" ); $button->signal_connect( "clicked", sub { $notebook->next_page(); } ); $table->attach_defaults( $button, 1, 2, 1, 2 ); $button->show(); $button = new Gtk::Button( "Prev Page" ); $button->signal_connect( "clicked", sub { $notebook->prev_page(); } ); $table->attach_defaults( $button, 2, 3, 1, 2 ); $button->show(); $button = new Gtk::Button( "Tab Position" ); $button->signal_connect( "clicked", \&rotate_book, $notebook ); $table->attach_defaults( $button, 3, 4, 1, 2 ); $button->show(); $button = new Gtk::Button( "Tabs/Border On/Off" ); $button->signal_connect( "clicked", \&tabsborder_book, $notebook ); $table->attach_defaults( $button, 4, 5, 1, 2 ); $button->show(); $button = new Gtk::Button( "Remove Page" ); $button->signal_connect( "clicked", \&remove_book, $notebook ); $table->attach_defaults( $button, 5, 6, 1, 2 ); $button->show(); $table->show(); $window->show(); main Gtk; exit ( 0 ); ### Subroutines # This function rotates the position of the tabs sub rotate_book { my ( $button, $notebook ) = @_; my %rotate = ( top => 'right', right => 'bottom', bottom => 'left', left => 'top' ); $notebook->set_tab_pos( $rotate{ $notebook->tab_pos } ); } # Add/Remove the page tabs and the borders sub tabsborder_book { my ( $button, $notebook ) = @_; my $tval = $false; my $bval = $false; if ( $notebook->show_tabs == 0 ) { $tval = $true; } if ( $notebook->show_border == 0 ) { $bval = $true; } $notebook->set_show_tabs( $tval ); $notebook->set_show_border( $bval ); } # Remove a page from the notebook sub remove_book { my ( $button, $notebook ) = @_; my $page; $page = $notebook->get_current_page(); $notebook->remove_page( $page ); # Need to refresh the widget -- This forces the widget to redraw itself. $notebook->draw( undef ); } # END EXAMPLE PROGRAM
Notebook Example Screenshot
Object
+--- Widget
+--- Container
+--- Bin
+--- Button
+--- OptionMenu
An OptionMenu is a widget that allows the user to select from a valid set of choices. The current choice is shown in the OptionMenu, and if the user clicks on the OptionMenu, it displays a popup menu consisting of all the valid choices.
This simple widget is creating using:
$option = new Gtk::OptionMenu();
To add a menu, create a new popup menu, as described in the
section on the
menu widget
,
without any tearoffs, submenus, or accelerators, and add it to
the OptionMenu using:
$option->set_menu( $popup_menu );
As you might suspect, you can retrieve the menu associated with
an OptionMenu using:
$popup_menu = $option->get_menu();
If you want to remove a menu from an OptionMenu, you may do so
with:
$option->remove_menu();
Finally, if you want to select an item in the menu, you would
use:
$option->set_history( $index );
where
$index
is the index of the menu item to select. The index value ranges
from 0 (first item) to n-1, where n is the number of items in
the menu.
The paned window widgets are useful when you want to divide an area into two parts, with the relative size of the two parts controlled by the user. A groove is drawn between the two portions with a handle that the user can drag to change the ratio. The division can either be horizontal (the HPaned widget) or vertical (the VPaned widget).
To create a new paned window, call one of:
$paned = new Gtk::HPaned();
$paned = new Gtk::VPaned();
After creating the paned window widget, you need to add child
widgets to its two halves. To do this, use one of the the
following sets of functions:
$paned->pack1( $child, $resize, $shrink );
$paned->add1( $child );
$paned->pack2( $child, $resize, $shrink );
$paned->add2( $child );
add1() and pack1() adds the child widget to the left or top half of the paned window. add2() and pack2() adds the child widget to the right or bottom half of the paned window.
The $resize argument specifies whether the child should expand when the paned widget is resized, and the $shrink argument specifies whether the child can be made smaller than its requested size.
The
add1()
function is equivelent to calling
$paned->pack1( $child, $false, $true );
And the
add2()
function is equivelent to calling
$paned->pack2( $child, $false, $false );
A paned widget can be changed visually using the following two
functions.
$paned->set_handle_size( $size );
$paned->set_gutter_size( $size );
The first of these sets the size of the handle and the second sets the size of the gutter that is between the two parts of the paned window.
As an example, we will create part of the user interface of an imaginary email program. A window is divided into two portions vertically, with the top portion being a list of email messages and the bottom portion the text of the email message. Most of the program is pretty straightforward. A couple of points to note: text can't be added to a Text widget until it is realized. This could be done by calling realize(), but as a demonstration of an alternate technique, we connect a handler to the 'realize' signal to add the text. Also, we need to add the 'shrink' option to some of the items in the table containing the text window and its scrollbars, so that when the bottom portion is made smaller, the correct portions shrink instead of being pushed off the bottom of the window.
#!/usr/bin/perl -w use Gtk ; use strict ; set_locale Gtk; init Gtk; my $false = 0; my $true = 1; my $window; my $paned; my $list; my $text; # Create the window $window = new Gtk::Window( "toplevel" ); $window->set_title( "Paned Windows" ); $window->signal_connect( "destroy", sub { Gtk-> exit ( 0 ); } ); $window->border_width( 10 ); $window->set_usize( 450, 400 ); # create a vpaned widget and add it to our toplevel window $paned = new Gtk::VPaned(); $window->add( $paned ); $paned->set_handle_size( 10 ); $paned->set_gutter_size( 15 ); $paned->show(); # Now create the contents of the two halves of the window $list = create_list(); $paned->add1( $list ); $list->show(); # Create the text area. $text = create_text(); $paned->add2( $text ); $text->show(); $window->show(); main Gtk; exit ( 0 ); ### Subroutines # Create a list of messages and return it sub create_list { my $scrolled_window; my $list; my $list_item; my @buffer; # Create a new scrolled window, with scrollbars only if needed $scrolled_window = new Gtk::ScrolledWindow( " ", " " ); $scrolled_window->set_policy( 'automatic', 'automatic' ); # Create a new list and put it in the scrolled window $list = new Gtk::List(); $scrolled_window->add_with_viewport( $list ); $list->show(); # Add some messages to the window for my $i ( 0..9 ) { $buffer[ $i ] = "Message \#" . $i; $list_item = new Gtk::ListItem( $buffer[ $i ] ); $list->add( $list_item ); $list_item->show(); } return ( $scrolled_window ); } # Add some text to our text widget - this is a callback that is invoked # when our window is realized. We could also force our window to be # realized with gtk_widget_realize, but it would have to be part of # a hierarchy first sub realize_text { my ( $text ) = @_; $text->freeze(); $text->insert( " ", $text->style->black, $text->style->white, "From: pathfinder\@nasa.gov\n" . "To: mom\@nasa.gov\n" . "Subject: Made it!\n" . "\n" . "We just got in this morning. The weather has been\n" . "great - clear but cold, and there are lots of fun\n" . "sights.\n" . "Sojourner says hi. See you soon.\n" . " -Path\n" ); $text->thaw(); } # Create a scrolled text area that displays a "message" sub create_text { my $table; my $text; my $hscrollbar; my $vscrollbar; # Create a table to hold the text widget and scrollbars $table = new Gtk::Table( 2, 2, $false ); # Put a text widget in the upper left hand corner. Note the use of # 'shrink' in the y direction $text = new Gtk::Text( " ", " " ); $table->attach( $text, 0, 1, 0, 1, [ 'fill', 'expand' ], [ 'fill', 'expand', 'shrink' ], 0, 0 ); $text->show(); # Put a HScrollbar in the lower left hand corner $hscrollbar = new Gtk::HScrollbar( $text->hadj ); $table->attach( $hscrollbar, 0, 1, 1, 2, [ 'expand', 'fill' ], 'fill', 0, 0 ); $hscrollbar->show(); # And a VScrollbar in the upper right $vscrollbar = new Gtk::VScrollbar( $text->vadj ); $table->attach( $vscrollbar, 1, 2, 0, 1, 'fill', [ 'expand', 'fill', 'shrink' ], 0, 0 ); $vscrollbar->show(); # Add a handler to put a message in the text widget when it is realized $text->signal_connect( "realize", \&realize_text ); return ( $table ); } # END EXAMPLE PROGRAM
Paned Example Screenshot
Описание Gtk-Perl | ||
---|---|---|
Предыдущая | Следующая |
Object
+--- Widget
+--- Misc
+--- Pixmap
Битовая графика - структуры данных, которые содержат изображения. Эти изображения могут использоваться где угодно, но, как правило, обычно используются как иконки на рабочем столе X, или как курсоры.
Битовая графика, состоящая из 2-х цветов, называется битовым массивом (битмапом - bitmap) и для его использования существует несколько дополнительных фукций
Для понимания того, что такое битовая графика, необходимо понимать, как работает система XWindow. Приложения под X-ами не обязательно могут быть запущены на томже компьютере, на котором работает пользователь. Различные приложения, называемые клиентами, общаются с одной программой, которая показывает графику и работает с клавиатурой или мышью. Эту программу, которая работает непосредственно с пользователем, называют сервером или X-сервером. Так как общение возможно и по сети, то необходимо держать соединение с X-сервером. Это означает, что битовое изображение содержится в памяти X-сервера и основные свойства изображения для его показа не должны постоянно передаваться клиенту, вместо этого передается команда "по координатам XYZ показывается такой-то цвет". В случае даже если Вы не будете использовать X-сервер, то нижеприведенные конструкции без проблем могут быть перенесены под X.
Для использования битовой графики в GTK, мы в первую очередь должны построить битовую структуру используя методы GDK. Битовое изображение может быть создано либо прямо из памяти, либо прочитано из файла. Мы сделаем тем и другим способом.
$gdkpixmap = Gtk::Gdk::Pixmap->create_from_data( $window,
Этот метод используется для создания двухцветного изображения прямо из
памяти.
Каждый бит данных предстявляет из себя флаг, согласно которому каждый пиксел
либо включен либо выключен.
Ширина и высота определяют число пикселей. Указатель GdkWindow привязывает
изображение
к конкретному окну, т.к. битовая графика имеет смысл только в контексте
панели, на которой
она должна быть отображена.
$data,
$width,
$height );
$gdkpixmap = Gtk::Gdk::Pixmap->create_from_data( $window,
Этот метод используется для того, чтобы создать изображение заданной глубины
(числа цветов) от
определенного двуцветного массива.
$foreground и
$background
являются соответственно нижним и верхним цветами (в смысле каждый
охотник желает
знать где сидит фазан)
$data,
$width,
$height,
$depth,
$foreground,
$background );
$gdkpixmap = Gtk::Gdk::Pixmap->create_from_xpm( $window,
Формат XPM - удбочитаемое представление для оконной системы Unix XWindow.
Он широко используется и файлы в этом
формате можно создать многочисленными утилитами. Файл *.xpm должен содержать
изображение в том формате,
которое соответствует расширению, в этом случае он будет прочитан и загружен
как битовая графика. Маска
определяет, какие биты изображения являются непрозрачными. Все другие биты
будет окрашены в соответствии с цветом,
определенным в переменной $transparent_color.
$mask,
$transparant_color,
$filename );
$gdkpixmap = Gtk::Gdk::Pixmap->create_from_xpm_d( $window, my @xpm_data = ( "16 16 3 1",
Маленькие изображения могут быть включены в прямо в программу. В этом случае
битовая графика будет
создана без открытия дополнительных файлов. Пример такого включения:
$mask,
$transparent_color,
$data );
" c None",
". c #000000000000",
"X c #FFFFFFFFFFFF",
" ",
" ...... ",
" .XXX.X. ",
" .XXX.XX. ",
" .XXX.XXX. ",
" .XXX..... ",
" .XXXXXXX. ",
" .XXXXXXX. ",
" .XXXXXXX. ",
" .XXXXXXX. ",
" .XXXXXXX. ",
" .XXXXXXX. ",
" .XXXXXXX. ",
" ......... ",
" ",
" " );
Как только мы создали битовое изображение, мы можем его показать как виждет
GTK. Для этого необходимо создать
специальный GTK виджет, который бы содержал битовое изображение GDK. Это
можно сделать так:
$pixmap = new Gtk::Pixmap( $gdkpixmap, $mask );
Другие вызовы этого типа виждетов:
$pixmap->get_type();
$pixmap->set( $val, $mask );
$pixmap->get( $val, $mask );
set() используется для смены виджета с битовой графикой, используемого в данным момент. $val является битовой графикой, созданной при помощи GDK.
Нижеследующий пример показывает использование кнопки с картинкой:
#!/usr/bin/perl -w use Gtk ; use strict ; set_locale Gtk; init Gtk; my $false = 0; my $true = 1; # XPM данные для иконки "Открыть файл" my @xpm_data = ( "16 16 4 1", " c None s None", ". c black", "X c #808080", "o c white", " ", " .. ", " .Xo. ... ", " .Xoo. ..oo. ", " .Xooo.Xooo... ", " .Xooo.oooo.X. ", " .Xooo.Xooo.X. ", " .Xooo.oooo.X. ", " .Xooo.Xooo.X. ", " .Xooo.oooo.X. ", " .Xoo.Xoo..X. ", " .Xo.o..ooX. ", " .X..XXXXX. ", " ..X....... ", " .. ", " "); my $window; my $pixmapwid; my $button; my $pixmap; my $mask; my $style; $window = new Gtk::Window( "toplevel" ); $window->signal_connect( "delete_event", sub { Gtk-> exit ( 0 ); } ); $window->border_width( 10 ); $window->show(); # закачиваем данные из gdk $style = $window->get_style()->bg( 'normal' ); ( $pixmap, $mask ) = Gtk::Gdk::Pixmap->create_from_xpm_d( $window->window, $style, @xpm_data ); #битовая графика присваивается виждету $pixmapwid = new Gtk::Pixmap( $pixmap, $mask ); $pixmapwid->show(); # кнопка содержит виджет с битовой графикой $button = new Gtk::Button(); $button->add( $pixmapwid ); $button->show(); $button->signal_connect( "clicked", sub { print ( "button clicked\n" ); } ); $window->add( $button ); main Gtk; exit ( 0 ); # конец примера
скриншот
Подгружая данные из файла в текущей директории, названного icon.xpm, мы
создали бы изображение таким образом:
( $pixmap, $mask ) = Gtk::Gdk::Pixmap->create_from_xpm( $window->window,
$style;
"./icon.xpm" );
$pixmapwid = new Gtk::Pixmap( $pixmap, $mask );
$pixmapwid->show();
Неудобство использования пиксмапов в том, что они отображаются всегда как квадратные, независимо от того, что на них нарисовано. Т.е. необходимо создать более приемлемые формы изображения. Например для создания игры хочетсяч иметь круглые кнопки. Один из путей использования - контурные панели.
Контурные панели это обычная графика, в которой фоновые пикселы являются прозрачными. В этом смысле если фоновое изображение многоцветно, то мы не переписываем его как квадратное... Нижеследующий пример показывает изображение огородной одноколесной тачки (без перегноя :) на рабочем столе:
#!/usr/bin/perl -w use Gtk ; use strict ; set_locale Gtk; init Gtk; my $false = 0; my $true = 1; my @wheelbarrow = ( '48 48 64 1', ' c None', '. c #DF7DCF3CC71B', 'X c #965875D669A6', 'o c #71C671C671C6', 'O c #A699A289A699', '+ c #965892489658', '@ c #8E38410330C2', '# c #D75C7DF769A6', '$ c #F7DECF3CC71B', '% c #96588A288E38', '& c #A69992489E79', '* c #8E3886178E38', '= c #104008200820', '- c #596510401040', '; c #C71B30C230C2', ': c #C71B9A699658', '> c #618561856185', ', c #20811C712081', '< c #104000000000', '1 c #861720812081', '2 c #DF7D4D344103', '3 c #79E769A671C6', '4 c #861782078617', '5 c #41033CF34103', '6 c #000000000000', '7 c #49241C711040', '8 c #492445144924', '9 c #082008200820', '0 c #69A618611861', 'q c #B6DA71C65144', 'w c #410330C238E3', 'e c #CF3CBAEAB6DA', 'r c #71C6451430C2', 't c #EFBEDB6CD75C', 'y c #28A208200820', 'u c #186110401040', 'i c #596528A21861', 'p c #71C661855965', 'a c #A69996589658', 's c #30C228A230C2', 'd c #BEFBA289AEBA', 'f c #596545145144', 'g c #30C230C230C2', 'h c #8E3882078617', 'j c #208118612081', 'k c #38E30C300820', 'l c #30C2208128A2', 'z c #38E328A238E3', 'x c #514438E34924', 'c c #618555555965', 'v c #30C2208130C2', 'b c #38E328A230C2', 'n c #28A228A228A2', 'm c #41032CB228A2', 'M c #104010401040', 'N c #492438E34103', 'B c #28A2208128A2', 'V c #A699596538E3', 'C c #30C21C711040', 'Z c #30C218611040', 'A c #965865955965', 'S c #618534D32081', 'D c #38E31C711040', 'F c #082000000820', ' ', ' .XoO ', ' +@#$%o& ', ' *=-;#::o+ ', ' >,<12#:34 ', ' 45671#:X3 ', ' +89<02qwo ', 'e* >,67;ro ', 'ty> 459@>+&& ', '$2u+ ><ipas8* ', '%$;=* *3:.Xa.dfg> ', 'Oh$;ya *3d.a8j,Xe.d3g8+ ', ' Oh$;ka *3d$a8lz,,xxc:.e3g54 ', ' Oh$;kO *pd$%svbzz,sxxxxfX..&wn> ', ' Oh$@mO *3dthwlsslszjzxxxxxxx3:td8M4 ', ' Oh$@g& *3d$XNlvvvlllm,mNwxxxxxxxfa.:,B* ', ' Oh$@,Od.czlllllzlmmqV@V#V@fxxxxxxxf:%j5& ', ' Oh$1hd5lllslllCCZrV#r#:#2AxxxxxxxxxcdwM* ', ' OXq6c.%8vvvllZZiqqApA:mq:Xxcpcxxxxxfdc9* ', ' 2r<6gde3bllZZrVi7S@SV77A::qApxxxxxxfdcM ', ' :,q-6MN.dfmZZrrSS:#riirDSAX@Af5xxxxxfevo', ' +A26jguXtAZZZC7iDiCCrVVii7Cmmmxxxxxx%3g', ' *#16jszN..3DZZZZrCVSA2rZrV7Dmmwxxxx&en', ' p2yFvzssXe:fCZZCiiD7iiZDiDSSZwwxx8e*>', ' OA1<jzxwwc:$d%NDZZZZCCCZCCZZCmxxfd.B ', ' 3206Bwxxszx%et.eaAp77m77mmmf3&eeeg* ', ' @26MvzxNzvlbwfpdettttttttttt.c,n& ', ' *;16=lsNwwNwgsvslbwwvccc3pcfu<o ', ' p;<69BvwwsszslllbBlllllllu<5+ ', ' OS0y6FBlvvvzvzss,u=Blllj=54 ', ' c1-699Blvlllllu7k96MMMg4 ', ' *10y8n6FjvllllB<166668 ', ' S-kg+>666<M<996-y6n<8* ', ' p71=4 m69996kD8Z-66698&& ', ' &i0ycm6n4 ogk17,0<6666g ', ' N-k-<> >=01-kuu666> ', ' ,6ky& &46-10ul,66, ', ' Ou0<> o66y<ulw<66& ', ' *kk5 >66By7=xu664 ', ' <<M4 466lj<Mxu66o ', ' *>> +66uv,zN666* ', ' 566,xxj669 ', ' 4666FF666> ', ' >966666M ', ' oM6668+ ', ' *4 ', ' ', ' ' ); my $window; my $pixmap; my $fixed; my $gdkpixmap; my $mask; my $style; my $normal; my $gc; # Создаем основное окно и вешаем на него обработчик сигнала delete_event для закрытия # приложения. Заметим, что основное окное не имеет заголовка наверху # так как мы его делаем popup окном. $window = new Gtk::Window( "popup" ); $window->signal_connect( "delete_event", sub { Gtk-> exit ( 0 ); } ); $window->show(); # Строчки для битовой графики и виджета битовой графики $style = Gtk::Widget->get_default_style(); $normal = $style->bg( 'normal' ); $gc = $style->black_gc; ( $gdkpixmap, $mask ) = Gtk::Gdk::Pixmap->create_from_xpm_d( $window->window, $normal, @wheelbarrow ); $pixmap = new Gtk::Pixmap( $gdkpixmap, $mask ); $pixmap->show(); # Показывая битовую графику мы используем фиксированный виджет $fixed = new Gtk::Fixed(); $fixed->set_usize( 200, 200 ); $fixed->put( $pixmap, 0, 0 ); $window->add( $fixed ); $fixed->show(); # маскируется все, кроме изображения $window->shape_combine_mask( $mask, 0, 0 ); # показываем окно $window->set_uposition( 400, 400 ); $window->show(); main Gtk; exit ( 0 ); # конец примера
Скриншот
Чтобы сделать виджет отзывающимся на сигнал, мы присваиваем ему свойство
откликаться на нажатие кнопки.
несколько строк кода показывают, как сделать так, чтобы нажатием мышшиной
кнопки по картинке виджет закончил свою работу.
$window->set_events( [ $window->get_events(), 'button_press_mask' ] );
$window->signal_connect( "button_press_event", sub { Gtk->exit( 0 ); } );
#!/usr/bin/perl -w use Gtk ; use strict ; set_locale Gtk; init Gtk; my $false = 0; my $true = 1; my $window; my $box; my $button; # Create the window $window = new Gtk::Window( "Пример кнопки" ); $window->set_title( "Кнопка с картинкой!" ); $window->border_width( 10 ); $window->realize(); $window->signal_connect( "destroy", sub { Gtk-> exit ( 0 ); } ); $window->signal_connect( "delete_event", sub { Gtk-> exit ( 0 ); } ); # этот вызов нашего бокса создает функцию - ? (This calls our box creating function) $box = xpm_label_box( $window, "info.xpm", "Замерзни!" ); $button = new Gtk::Button(); $button->signal_connect( "clicked", sub { print ( "Замер-р-р-р-з-з-з-заю!!!\n" ); } ); # Показываем все наши виджеты $box->show(); $button->add( $box ); $button->show(); $window->add( $button ); $window->show(); # расслабляемся и готовимся отдохнуть! main Gtk; exit ( 0 ); # Создаем новый горизонтальный бокс с лейблом и помещаем туда картинку # и засовываем в бокс. sub xpm_label_box { my ( $parent, $xpm_filename, $label_text ) = @_; my $box; my $style; my $pixmap; my $mask; my $pixmapwid; my $label; # Создаем область отрисовки для xpm и лейбл $box = new Gtk::HBox( $false, 0 ); # берем цвет кнопки как фоновый для картинки. $style = $parent->get_style()->bg( 'normal' ); # теперь для xpm ( $pixmap, $mask ) = Gtk::Gdk::Pixmap->create_from_xpm( $parent->window, $style, $xpm_filename ); $pixmapwid = new Gtk::Pixmap( $pixmap, $mask ); # создаем лейбл для кнопки $label = new Gtk::Label( $label_text ); # передаем картинку и лейбл в горизонтальный виджет $box->pack_start( $pixmapwid, $false, $false, 3 ); $box->pack_start( $label, $false, $false, 3 ); $box->border_width( 2 ); $pixmapwid->show(); $label->show(); return ( $box ); } # конец примера
Прежде чем запстить программу, необходимо загрузить изображение image и сохранить его в директорию с кодом приведенной программы. Если изображения не будет, то $pixmap не будет содержать информации и программа не будет работать корректно.
Как только вы произвели все вышеприведенные операции, то появится следующая панель, яб даже сказал, панелька: Once you have done this, the above program should look like this:
скриншот
Функция xpm_label_box() может использоваться любым виджетом, являющимся контейнером.
Вызов в Notice in xpm_label_box() подобен вызову get_style(). Каждый виджет имеет стиль, содержащий теневой и основной цвета для различных ситуаций, выбора фона и пр. Эти значения установлены по умолчанию в каждом виджете и являются необходимыми для вызова многих функций GDK, например $pixmap->create_from_xpm(), которая создает нормальный фоновый цвет. Использя ресурс-файлы стиль виджетов может быть переопределен.
Также отметим, что realize() вызывается после установления ширины границы окна. Эта функция использует GDK для создания панелей XWindow, связаных с виджетом. Она автоматически вызывается когда вы вызываете функцию show() для виджета. Но вызов функции create_from_xpm() требдует, чтобы аргумент $window обратился к реальной панели X.т.к. это необходимо виджету до вызова GDK (туманно и неясно, что это за зверь)
Предыдущая | На главную | Следующая |
Графика | Вверх | Административные сведения |
Виджеты состояния процесса Содержание Пример Диалог подгружения Иерархия наследования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 и может быть представлен как:показ текста определяется функцией с булевым аргументом:
- %p - проценты
- %v - значение
- %l - нижний предел
- %u - верхний предел
$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 =) { $value =~ s/^.*\[//g; $value =~ s/ //g; $value =~ s/\%\]//g; chomp $value; $pbar->set_value( ++$value ) if ( $value =~ /^[0-9]+$/ ); # Run the main loop as long as events are pending # Запуск основной части программы(???) Gtk->main_iteration while ( Gtk->events_pending ); } close TMP; # завершение загрузки, удаление прогрессбара и информирование пользователя $vbox->remove( $pbar ); $label->set_text( "Download Complete" ); # Create the close button $button = new Gtk::Button( "Close" ); $button->signal_connect( 'clicked', sub { Gtk->exit( 0 ); } ); $vbox->pack_start( $button, $false, $false, 0 ); $button->show(); main Gtk; exit( 0 );
Если есть желание получить список радиокнопок, то необходимо использовать функцию:
@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-я кнопка): (вставить скриншот)
Иерархия наследования
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', закрывающим окно.
Обзор Gtk-Perl Предыдущая Следующая
Часть 30. Линейки
Иерархия наследования
Object
+--- Widget
+--- Ruler
Линейка используется для индикации положения курсора мыши. Она могжет быть как вертикальной, так и горизонтальной. В обоих случая линейка занимают всю отведенную окну, в котором она создана, область. Текущее положение курсора мыши на линейке отмечает маленький треугольник.
Прежде, чем использовать, линейку необходимо создать. Горизонтальная и вертикальная создается следующими методами:
$hruler = new Gtk::HRuler();
$vruler = new Gtk::VRuler();
Создав линейку, мы можем указать ее единицу измерения 'pixels', 'inches' или 'centimeters':
По умолчанию используются 'pixels'.$ruler->set_metric( $metric );
Другой важной характеристикой является отображение насечек на шкале и подписей к ним. Описать это можно с помощью метода
$lower и $upper определяют соответственно минимальное и максимальное значение шкалы, а $max_size максимально возможное значение, которое может быть отображено данной линейкой. #!!!! этот параметр очень странно работает... $position определяет начальное положение индикатора на линейке.$ruler->set_range( $lower, $upper, $position, $max_size );
Можно задать размер вертикльной линейки в 800 пикселей выполнив:
Подписи к делениям будут каждые 100 пискселов. Если вдруг мы захотим установить размер от 7 до 16, то нужно выполнить:$vruler->set_range( 0, 800, 0, 800 );
$vruler->set_range( 7, 16, 0, 20 );
Как было замечено, индикатором позиции курсора выступает мальенкий треугольник. Если линейка используется именно для отображения позиции курсора, то сигнал 'motion_notify_event' необходимо соединить с событием 'motion_notify_event' линейки. Для этого достаточно выполнить команду:
$area->signal_connect( "motion_notify_event",
sub { $ruler->motion_notify_event( $_[1] ); } );30.1. Пример использования линеек.
Следующий пример создает арену с вертикальной и горизонтальной линейками. Размер арены 600 на 400 пикселов. Горизонтальная линейка будет отображать значения с 7 до 13. А вертикальная - с 0 до 400, с подписью к делениям каждые 100 пикселов.
Расположим арену и линейки внутри таблицы.
Итак, пример:
#!/usr/bin/perl -w use Gtk ; use strict ; set_locale Gtk; init Gtk; my $false = 0; my $true = 1; my $xsize = 600; my $ysize = 400; my $window; my $table; my $area; my $hrule; my $vrule; # создаем окно $window = new Gtk::Window( "toplevel" ); $window->signal_connect( "delete_event", sub { Gtk-> exit ( 0 ); } ); $window->border_width( 10 ); # Таблица, в которую поместим линейки и арену $table = new Gtk::Table( 3, 2, $false ); $window->add( $table ); # Создаем арену. $area = new Gtk::DrawingArea(); $area->size( $xsize, $ysize ); $table->attach( $area, 1, 2, 1, 2, [ 'expand', 'fill' ], 'fill', 0, 0 ); $area->set_events( [ 'pointer_motion_mask', 'pointer_motion_hint_mask' ] ); # Горизонтальная линейка будет наверху. # Говорим, чтобы событие горизонтального перемещения курсора мыши # нужно посылать соответствующему обработчику этой линейки. $hrule = new Gtk::HRuler(); $hrule->set_metric( 'pixels' ); $hrule->set_range( 7, 13, 0, 20 ); $area->signal_connect( "motion_notify_event", sub { $hrule->motion_notify_event( $_[1] ); } ); $table->attach( $hrule, 1, 2, 0, 1, [ 'expand', 'shrink', 'fill' ], 'fill', 0, 0 ); # Вертикальную линейку разместим слева. # Аналогично соединим событие перемещения мыши (вертикальное) # через арену и соответствующий обработчкик линейки. $vrule = new Gtk::VRuler(); $vrule->set_metric( 'pixels' ); $vrule->set_range( 0, $ysize, 10, $ysize ); $area->signal_connect( "motion_notify_event", sub { $vrule->motion_notify_event( $_[1] ); } ); $table->attach( $vrule, 0, 1, 1, 2, [ 'fill', 'expand', 'shrink' ], 'fill', 0, 0 ); # и... вылетит птичка. )) # Показываем все. $area->show(); $hrule->show(); $vrule->show(); $table->show(); $window->show(); main Gtk; exit ( 0 ); # Конец примера
![]()
Скриншот
Если вы присмотритесь, то заметите, что указатель мыши не отображается на скриншоте (дело в программе, которую я использовал для его создания). Но вы можете точно указать позицию, в которой он был благодаря линейкам.
Предыдущая На главную Следующая Виджеты подсказок Вверх Выбор цвета
Иерархия наследования
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 );
Иерархия наследования
Object +--- Widget +--- Range +--- ScrollbarЭтот наиболее часто используемый виджет может быть использован только для прокрутки некоторых других виджетов, таких как список, лист или viewport. В других случаях вы должны использовать скейл-виджеты в силу того, что они наиболее дружественные и более характерные. Есть два различных вида скроллбаров, вертикальный и горизонтальный, создаются такими функциями:new Gtk::HScrollbar( $adjustment ); new Gtk::VScrollbar( $adjustment );$adjustment может быть уже определен. Вравнивание может быть нулевым в том случае, если вы хотите передать значение этой переменной из другого виджета, тоесть наследовать.
Chapter 44. Scrolled Windows
Inheritance Hierarchy
Object
+--- Widget
+--- Container
+--- Bin
+--- ScrolledWindow
Scrolled windows are used to create a scrollable area with another widget inside it. You may insert any type of widget into a scrolled window, and it will be accessible regardless of the size by using the scrollbars.
The following function is used to create a new scrolled window.
$scrolled_window = new Gtk::ScrolledWindow( $hadjustment,
$vadjustment );Where the first argument is the adjustment for the horizontal direction, and the second, the adjustment for the vertical direction. These are almost always set to a null value.
$scrolled_window->set_policy( $hscrollbar_policy,
$vscrollbar_policy );This sets the policy to be used with respect to the scrollbars. The first argument sets the policy for the horizontal scrollbar, and the second the policy for the vertical scrollbar.
The policy may be either 'automatic' or 'always'. 'automatic' will automatically decide whether you need scrollbars, whereas 'always' will always leave the scrollbars there.
You can then place your object into the scrolled window using the following function.
$scrolled_window->add_with_viewport( $child );
The location of the child widget with respect to the scrollbars can be set using:
where $placement can be 'top_left (the default), 'top_right, 'bottom_left', or 'bottom_right'. A value of 'top_left' means that the widget is in the top left, with the scrollbars to the right and bottom of the widget.$scrolled_window->set_placement( $placement );
You can get and set the adjustments for the horizontal and vertical scrollbars using:
$scrolled_window->get_hadjustment();
$scrolled_window->get_vadjustment();
$scrolled_window->set_hadjustment( $adjustment );
$scrolled_window->set_vadjustment( $adjustment );See the chapter on Adjustment for information on adjustments and how to use them.
44.1. Scrolled Window Example
Here is a simple example that packs a table with 100 toggle buttons into a scrolled window.
Scrolled Window Example Source
#!/usr/bin/perl -w use Gtk ; use strict ; set_locale Gtk; init Gtk; my $false = 0; my $true = 1; my $window; my $scrolled_window; my $table; my $button; my $buffer; # Create a new dialog window for the scrolled window to be # packed into. $window = new Gtk::Dialog(); $window->signal_connect( "destroy", sub { Gtk-> exit ( 0 ); } ); $window->set_title( "Scrolled Window Example" ); $window->border_width( 0 ); $window->set_usize( 300, 300 ); # create a new scrolled window. $scrolled_window = new Gtk::ScrolledWindow( " ", " " ); $scrolled_window->border_width( 10 ); # the policy is one of "automatic", or "always". "automatic" will # automatically decide whether you need scrollbars, whereas "always" # will always leave the scrollbars there. The first one is the # horizontal scrollbar, the second one is the vertical scrollbar. $scrolled_window->set_policy( "automatic", "always" ); # The dialog window is created with a vbox packed into it $window->vbox->pack_start( $scrolled_window, $true, $true, 0 ); $scrolled_window->show(); # create a table of 10 by 10 squares. $table = new Gtk::Table( 10, 10, $false ); # set the spacing to 10 on x and 10 on y $table->set_row_spacings( 10 ); $table->set_col_spacings( 10 ); # pack the table into the scrolled window $scrolled_window->add_with_viewport( $table ); $table->show(); # this simply creates a grid of toggle buttons on the table # to demonstrate the scrolled window. for my $i ( 0..9 ) { for my $j ( 0..9 ) { $buffer = "button (" . $i . ", " . $j . ")\n"; $button = new Gtk::ToggleButton( $buffer ); $table->attach_defaults( $button, $i, $i + 1, $j, $j + 1 ); $button->show(); } } # Add a "close" button to the bottom of the dialog. Notice that instead # of exiting directly, we are instead telling the $window to close. This # way, if we want different behavior when closing the window, we only need # to change one signal_connect(). An even better way would be to call a # function to close the window. $button = new Gtk::Button( "Close" ); $button->signal_connect_object( "clicked", \&Gtk::widget_destory, $window ); # this makes it so the button is the default. $button->can_default( $true ); $window->action_area->pack_start( $button, $true, $true, 0 ); # This grabs this button to be the default button. Simply hitting # the "Enter" key will cause this button to activate. $button->grab_default(); $button->show(); $window->show(); main Gtk; exit ( 0 ); # END EXAMPLE PROGRAM
![]()
Scrolled Window Example Screenshot
Try playing with resizing the window. Notice how the scrollbars react. You may also wish to use the set_usize() call to set the default size of the window or other widgets.
Иерархия наследования
Object +--- Widget +--- SeparatorsСепараторы являются самыми простоыми виджетами. Это всего-лишь линии с тенью на воне общего виджета. Существуют два типа вертикальные и горизонтальные:
$hseparator = new Gtk::HSeparator(); $vseparator = new Gtk::VSeparator();Единственное только то, что сепараторы не используются как разделители меню. В качестве разделителя тут используется пустое MenuItem.
Обзор Gtk-Perl Предыдущий Следующий
Часть 5. Сигналы и события
- Содержание
- 5.1. Теория сигналов и событий
- 5.2. события
- 5.3. Созвращаемое значение вызова
- 5.4. Испускание сигналов
- 5.5. Удаление вызовов
- 5.6. Временное отключение вызовов
- 5.7. Общение с обработчиком сигналов
- 5.8. Испускание и распространение сигналов
5.1. Теория сигналов и вызовов
GTK - управляемый событиями инструментарий сигналов, которые содержатся в main Gtk до того, как событие произойдет и пройдет контроль в соответствующей функции.
Прохождение контроля реализуется при помощи идеи сигналов. Эти сигналы не похожи на системные сигналы Unix и не осуществляются при помощи их использования, хотя терминология практически идентична. Когда происходит что-то подобное нажатию кнопки мыши, то соответствующий сигнал "испускается" виджетом, на котором была нажата кнопка. Реализация этой схемы и является одной из основных функций GTK. Есть как сигналы, которые наследуют все виджеты(например 'destroy') так и сигналы, которые являются специфичными для какого-то типа виджетов, например сигнал 'toggled' на кнопке toggle.
Чтобы заставить виджет выполнить действие, устанавливаем обработчик сигнала на вызов определенной функции. Например как-то так:
$object->signal_connect( "signal_name", \&signal_func );
$object->signal_connect( signal_name => \&signal_func );
$object->signal_connect( "signal_name", \&signal_func, $optional_data ... );
$object->signal_connect( "signal_name", \&signal_func, @optional_data );Первые две строчки идентичны, вторые две так-же одинаковы, так как аргументы посылаются списком скаляров. Конечно, возможно посылать акгументы и списком, на усмотрение разработчика.
Левая переменная signal_connect() - виджет, который будет вызывать сигнал. Первый аргумент - строка, представляющая сигнал, который в дальнейшем будет регистрироваться. Второй аргумент - ссылка на вызываемую по сигналу подпрограмму. Эту подпрограмму называют вызовом обработчика. Если необходимо отдать ему некоторые данные, то их надо указать в списке после второго аргумента.
Если вы не разбираетесь в ссылках Perl, то обычному вызову подпрограммы предшествует "\&" и передавая таким образом ссылки на подпрограмму, вы не можете передавать подпрограмме параметры в скобках.
Для передачи одного сигнала подпрограмме необходимо использовать примерно такой код:
$object->signal_connect( "signal_name", sub { do_something; } );
Вызывающая фукция обычко определяется примерно так:
sub callback_func
{
my ( $widget, @data ) = @_;
...
}Первый аргумент посылает вызов всегда как виджет, который бы сгенерировал данный сигнал и остальная часть аргументов - дополнительные данные, посланные при помощи функции signal_connect() Запомните, что Perl не заставляет объявлять или использовать аргументы, присланные подпрограмме и это является хорошим тоном при программировании.
Стоит заметить, что вышеприведенное описание функции обработчика сигнала иллюстрирует только общую схему работы. Некоторые виджеты испускают различые по схеме работы сигналы. Например виджет CList 'select_row' передает параметры колонками и столбцами.
5.2. События
В добавление к4 описанному механизму передачи сигналов, существует ряд событий, которые похожи на систему событий X. Запрос может быть добавлен к следующим событиям:
event
button_press_event
button_release_event
motion_notify_event
delete_event
destroy_event
expose_event
key_press_event
key_release_event
enter_notify_event
leave_notify_event
configure_event
focus_in_event
focus_out_event
map_event
unmap_event
property_notify_event
selection_clear_event
selection_request_event
selection_notify_event
proximity_in_event
proximity_out_event
drag_begin_event
drag_request_event
drag_end_event
drop_enter_event
drop_leave_event
drop_data_available_event
other_event
В порядке вызова элементов для каждого из этих событий используется функция signal_connect(), в случае, если необходимо вызвать сигнал, используя только один из вышеупомянутых имен вместо названия сигнала. Последний аргумент, передаваемый в вызывающую функцию - структура событий. Например в начале вызова можно написать:
my ( $widget, $data, $event ) = @_;
или, есил Вы хотите передать список:
my ( $widget, @data ) = @_;
my $event = pop( @data );Некоторыми наиболее употребляемыми полями в структуре (вызовов - ??) явялются button , keyval , и type .
Структура button содержит помер нажатой кнопки(1,2 или 3). Структура keyval содержит имя кнопки, которая была нажата на клавиатуре(если была). И структура type содержит нижеперечисленные строчки:
'nothing'
'delete'
'destroy'
'expose'
'motion_notify'
'button_press'
'2button_press'
'3button_press'
'button_release'
'key_press'
'key_release'
'enter_notify'
'leave_notify'
'focus_change'
'configure'
'map'
'unmap'
'property_notify'
'selection_clear'
'selection_request'
'selection_notify'
'proximity_in'
'proximity_out'
'drag_begin'
'drag_request'
'drop_enter'
'drop_leave'
'drop_data_avail'
'cLIent_event'
'visibiLIty_notify'
'no_expose'
Такая структурированность типов сигналов довольно просто позволяет определить причину события. Если нажали кнопку мыши, то какую? Пример:
sub some_event
{
my ( $widget, @data ) = @_;
my $event = pop( @data );
if ( ( defined( $event->{'type'} ) ) and
( $event->{'type'} eq 'button_press' ) )
{
if ( $event->{'button'} == 3 )
{
# right click
}
else
{
# non-right click
}
}
}Но необходимо отметить, что вышеприведенный код будет работать только в том случае, если вызов является сгрупированным с одним из событий, упомянутых выше. Сигналы не посылают своей структуры если неизвестно, сколько аргументов послано и нет необходимости в этой информации.
5.3. Возвращаемое вызовом значение
Тип, возвращаемый функцией signal_connect() является признаком, который идентифыицирует функцию вызова. Вы можете иметь сколько вызовов на каждый сигнал и объект, скольно вам необходимо и каждый вызов будет завершен в порядке очереди, в которой они следовали.
5.4. Испускание сигналов
Если вы хотите испустить специфический сигнал, вы можете сделать это при помощи функции
$widget->signal_emit( $id );
$widget->signal_emit_by_name( $signal_name );
Агрумент первого вызова является идентификатором тега, который возвращается signal_connect(). Аргумент во второй форме является строкой, определяемой именем сигнала.
Также некоторые виджеты имеют функции, испускающие некоторые общие сигналы. Например функция destroy() генерирует сигнал 'destroy' и функция activate() генерирует сигнал 'activate' Эти функции, схожие по названию, рекомендуется использовать в виджетах, чтобы эмулировать сигналы.
5.5. Удаление вызовов
Id вызова, которые возвращается функцией signal_connect() также позволяет удалить вызов из списка вызовов при помощи функции signal_disconnect() например так:
$widget->signal_disconnect( $id );
Если необходимо удалить все сигналы, то для этого служит функция
$widget->signal_handlers_destroy();
Этот запрос удаляет все текущие сигналы из объекта, заданные первым аргументом. ЭТа процедура выполняется автоматически при уничтожении виджета и нет необходимости заботиться о данной функции.
5.6. Временное выключение вызовов
Вы также можете временно отключать действие сигналов с помощью группы функций:
$widget->signal_handler_block( $callback_id );
$widget->signal_handler_block_by_func( \&callback, $data );
$widget->signal_handler_block_by_data( $data );
$widget->signal_handler_unblock( $callback_id );
$widget->signal_handler_unblock_by_func( \&callback, $data );
$widget->signal_handler_unblock_by_data( $data );5.7. Общение с обработчиком сигналов
Ниже приведен краткий обзор функций, позволяющих работать с обработчиком сигналов, этот список приведен только для того, чтобы показать что это возможно, но более подробную информацию можно получить в документации к GTK+
$id = $object->signal_connect( $signal_name,
\&function,
@optional_data );
$id = $object->signal_connect_after( $signal_name,
\&function,
@optional_data );
$id = $object->signal_connect_object( $signal_name,
\&function,
$slot_object );
$id = $object->signal_connect_object_after( $signal_name,
\&function,
$slot_object );
# I'm unsure of this one
$id = $object->signal_connect_full( $name,
\&function,
$callback_marshal,
@optional_data,
\&destroy_function,
$object_signal,
$after );
# I'm not sure of this one either
$id = $object->signal_connect_interp( $name,
\&function,
@optional_data,
\&destroy_function,
$after );
$id = $object->signal_connect_object_while_alive( $signal,
\&function,
$alive_object );
$id = $object->signal_connect_while_alive( $signal,
\&function,
@optional_data,
$alive_object );
$object->signal_disconnect( $id );
$object->signal_disconnect_by_func( \&function,
@optional_data );5.8. Испускание и распространение сигналов
Эмиссия сигнала - процесс, посредством которого GTK управляет всеми хандлерами для определенного объекта и сигнала. Сначала, отметьте, что возвращаемое значение в результате эмиссии сигнала - возвращаемое значение последнего выполненного хэндлера. Так как сигналы типа 'last', то обработка будет производиться при помощи дефолтным хендлером, если не запрашивать signal_connect_after().
Если событие(например "button_press_event") определено, то
Начинается обработка события в том виджете, где произошло событие
Испустить базовый сигнал "event". Если обработчик возвратит TRUE, остановить всю обработку.
Иначе, испустите специфический сигнал "button_press_event". Если обработчик возвратит TRUE, остановить всю обработку.
Иначе переход к породившему виджету и переиграть предыдущие шаги.
Плодолжайте до тех пор, пока некоторый обработчик сигнала не возвратит истину или когда будет достигнут верхний виджет.
Некоторые следствия вышеупомянутого:
Возвращаемое значение обработчика(хэндлера) не будет иметь никакого эффетка, если это обработчик по умолчанию, если не была вызвана функция signal_connect_after().
Чтобы обработчик сигнала был неуправляем, необходимо вызвать signal_connect() и использовать signal_emit_stop_by_name() возвращенное значение только ли эффект размноженного сигнала, не текущая эмиссия.
Предыдущая Главная Следующая Обзор контейнеров Вверх Основные контейнеры
Обзор Gtk-Perl Предыдущая Следующая
Chapter 24. Виджеты накрутки
Иерархия наследования
Виджет накрутки используется для того, чтобы пользователь мог выбрать значение из какого-то определенного диапазона. Он состоит из тектового бокса со стрелочками, позволяющими при нажатии на них увеличивать или уменьшать значение числа в текстовом боксе. В текстовом боксе также можно вручную отредактировать числовое значение.
Виджет накрутки может иметь нулевое значение или дробные значения и в зависимости от времени удержания инкремента/декремента скорость прибавления увеличивается.
Виджет накрутки использует выравнивание чтобы сохранять информацию о диапазоне значений, в котором находится значение текстового поля.
Вспомните, что виджет диапазона объявляется следующей функцией:
Аттрибуты диапазона используются виджетом накрутки в таком виде:$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 соответственно. Накрутчик можно создать следующим образом:
Переменная $climb_rate принимает значения между 0.0 и 1.0 и показывает величину изменения скорости увеличения значения в текстовом боксе накрутчика. Переменная $digits определяет число десятичных долей, которые будут выведены в спине.$spin = new Gtk::SpinButton( $adjustment, $climb_rate, $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();
Если необходимо изменить значение накрутчика, то это возможно при помощи следующей функции:
Параметр $direction может принимать одно из приведенных значений$spin->spin( $direction, $increment );
'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 );
Изменить правила поведения накрутчика можно при помощи нижеприведенной функции
Возможные значения $policy принимают одно из двух вариантов: 'always' или 'if_valid'.$spin->set_update_policy( $policy );
Эти политики определяют поведение накрутчика, разбирая вставленный текст и сопоставляя необходимым образом его со значениями базовой политики выравнивания.
В случае '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
![]()
Скриншот с накрутчиками
Предыдущая | Домой | Следующая |
Текстовые виджеты | Вверх | Меню |
Описание Gtk-Perl | ||
---|---|---|
Предыдущая | Следующая |
Object
+--- Widget
+--- Container
+--- Box
+--- HBox
+--- Statusbar
Статус бары это простые виджеты, которые используются для отображения текстовых сообщений. Они сохраняют стек сообщений, которые помещены в них, так что попытка повторного вызова верхнего сообщения стека (popping) вызовет отображение _предыдущего_ текстового сообщения.
Чтобы позволить различным блокам приложения использовать один статус бар для отображения сообщений, окно статус бара использует Идентификаторы Контекста вызова (Context Identifiers), которые в дальнейшем применяются для для идентификации различных "пользователей". Отображаемое сообщение находитя всегда на верху стека, в независимости от контекста вызова. Вообще, сообщения упорядочены в стеке по методу LIFO: последний-вошел-первый-вышел, без какой-либо зависимости от контекста.
Создаем статус бар командой:
$statusbar = new Gtk::Statusbar();
Новый Идентификатор Контекста можно получить методом get_context_id, передав
в качестве аргумента короткое описание создаваемого контекста.
$statusbar->get_context_id( $context_description );
Есть три функции для работы со статус барами:
$statusbar->push( $context_id, $text );
$statusbar->pop( $context_id );
$statusbar->remove( $context_id, $message_id );
Первая, push(), используется для добавления новых сообщений в статус бар. Она возвращает идентификатор сообщения, который позволяет удалять их функцией gtk_statusbar_remove из стека статус бара.
Функция pop() удаляет верхнее сообщение стека указанного Идентификатора Контекста.
Следующий пример создает статус бар и две кнопки: одна помещает сообщения на статус бар, а другая вызывает их на статус барз из стека.
#!/usr/bin/perl -w use Gtk ; use strict ; set_locale Gtk; init Gtk; my $false = 0; my $true = 1; my $window; my $vbox; my $button; my $statusbar; my $context_id; my $count = 1; # Создаем окно приложения $window = new Gtk::Window( "toplevel" ); $window->set_usize( 200, 100 ); $window->set_title( "GTK Statusbar Example" ); $window->signal_connect( "delete_event", sub { Gtk-> exit ( 0 ); } ); $vbox = new Gtk::VBox( $false, 1 ); $window->add( $vbox ); $vbox->show(); # Создаем статус бар $statusbar = new Gtk::Statusbar(); $vbox->pack_start( $statusbar, $true, $true, 0 ); $statusbar->show(); # Создаем новый Идентификатор Контекста, который будем дальше использовать для управления стеком $context_id = $statusbar->get_context_id( "Statusbar Example" ); # Cоздаем кнопку добавления сообщений $button = new Gtk::Button( "Push Item" ); $button->signal_connect( "clicked", \&push_item, $context_id ); $vbox->pack_start( $button, $true, $true, 2 ); $button->show(); # Создаем кнопку отображения верхнего сообщения стека $button = new Gtk::Button( "Pop Last Item" ); $button->signal_connect( "clicked", \&pop_item, $context_id ); $vbox->pack_start( $button, $true, $true, 2 ); $button->show(); $window->show(); main Gtk; exit ( 0 ); ### Функции # Помещаем сообщение в стек. И увеличиваем значение счетчика. sub push_item { my ( $widget, $context_id ) = @_; my $buff = ( "Item " . $count++ ); $statusbar->push( $context_id, $buff ); } # Вызываем верхнее сообщеие из стека sub pop_item { my ( $widget, $context_id ) = @_; $statusbar->pop( $context_id ); } # Конец примера
Скриншот
Предыдущая | На главную | Следующая |
Диалог выбора шрифта | Вверх | Передвигаемые окна с виджетами |
Иерархия наследования
Object
+--- Widget
+--- Container
+--- Table
Создать таблицу можно так:
$table = new Gtk::Table($num_rows,$num_columns,$homogeneous);
где первый аргумент - число строк, а второй - число столбцов. Аргумент $homogeneous показывает, как будут меняться размеры ячеек таблицы в зависимости от размера элементов таблицы в этой ячейке. Если эта переменная true то размер ячейки таблицы подстраивается под размер самого большого элемента в таблице. Если значение переменной $homogeneous=false то размер ячейки подстраивается под максимальный размер элемента в строке и столбце. Нуумерация строк и столбцов таблицы начинается с 0.
Помещение виджетов в таблицу.
Для помещения виджета в таблицу используют следующую функцию:
$table->attach( $child, $left_attach, $right_attach,
$top_attach, $bottom_attach, $xoptions,
$yoptions, $xpadding, $ypadding );
В левой части запроса - создаваемый потомок, который является первым аргументом. Второй и третий аргументы определяют, где разместить виджет и как много ячеек надо использовать. Если есть желание поместить кнопку внизу таблицы 2х2 и чтобы заполнение было только данную ячейку, то необходимо присвоить переменным следующие значения: $left_attach=1, $right_attach=2, $top_attach=1, $bottom_attach=2. Если нужно чтобы виджет располагался на верхней строке, то переменные должны быть такими: $left_attach = 0, $right_attach = 2, $top_attach = 0, $bottom_attach = 1.
Переменные $xoptions и $yoptions используются для специальных настроек и могут быть составными:
fill - если ячейка больше чем виджет, и 'fill' определен, то виджет будет расширен, чтобы использовать все имеющееся место. shrink - если виджет(таблица, всякий элемент можно назвать виджетом) был размещен на меньшем месте, чем ему требуется(обычно в том случае, когда пользователь изменяет размер окна), то виджет исчезнет. expand - расширяет таблицу, чтобы использовать все место.
Чтобы определить эти опции, необходимо вставить их в кавычки: 'option' или для совместного использования ['option1', 'option2']. Подобно боксам, сожно создать обрамление, указав его размер в пикселах. Модификация функции attach() - attach_defaults(), которая позволяет не учитывать х и у и расположение. Х и Y опции установлены по умолчанию в ['fill', 'expand'] и X и Y установлены в 0.
Размер таблицы и интервалы
Функции set_row_spacing() и set_col_spacing() устанавливают интервал между строками/столбцами в указанной строке или столбце:
$table->set_row_spacing( $row, $spacing );
$table->set_col_spacing( $column, $spacing );
для столбцов дополнение идет справа, для строк дополнение сверху(? проверить).
Можно установить последовательные интервалы для всех строк и/или столбцов, используя
$table->set_row_spacing( $row, $spacing );
$table->set_col_spacing( $column, $spacing );
Если необходимо изменить таблицу после её создания, то можно воспользоваться функцией
$table->resize( $rows, $columns );
Если надо все по дефолту, то пишем
$table->set_homogeneous( $homogeneous );
(тут вставить картинку с таблицей)
Программа, рисующая эту картинку:
#!/usr/bin/perl -w
use Gtk;
use strict;
set_locale Gtk;
init Gtk;
my $false = 0;
my $true = 1;
my $window;
my $button;
my $table;
# Create the window
$window = new Gtk::Window( "toplevel" );
$window->signal_connect( "delete_event", sub { Gtk->exit( 0 ); } );
$window->title( "Table" );
$window->border_width( 20 );
# Create a 2x2 table
$table = new Gtk::Table( 2, 2, $true );
$window->add( $table );
# создать кнопку
$button = new Gtk::Button( "button 1" );
$button->signal_connect( "clicked", \&ButtonClicked, "button 1" );
# вставить первую кнопку в верхнюу левую ячейку таблицы
$table->attach_defaults( $button, 0, 1, 0, 1 );
$button->show();
# создать вторую кнопку
$button = new Gtk::Button( "button 2" );
$button->signal_connect( "clicked", \&ButtonClicked, "button 2" );
# вставить вторую кнопку в верхнюу правую ячейку таблицы
$table->attach_defaults( $button, 1, 2, 0, 1 );
$button->show();
$button = new Gtk::Button( "Quit" );
$button->signal_connect( "clicked", sub { Gtk->exit( 0 ); } );
# вставить кнопку выхода в нижнюю ячейку таблицы
$table->attach_defaults( $button, 0, 2, 1, 2 );
$button->show();
$table->show();
$window->show();
main Gtk;
exit( 0 );
sub ButtonClicked{
my ( $button, $text ) = @_;
print( "Hello again $text was pressed\n" );
}
Содержание
Создание и конфигурация текстового бокса
Манипуляции с текстом
Клавиатурное шаманство
Пример текстового виджета
Текстовый виджет поволяет показывать и редактировать многострочный текст. Он также поддерживает цветной текст и различные фонты и может смешивать эти фонты в различных комбинациях. Также этот виджет имеет много команд, совместимых с редактором 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();
Toolbars are usually used to group some number of widgets in order to simplify customization of their look and layout. Typically a toolbar consists of buttons with icons, labels and tooltips, but any other widget can also be put inside a toolbar. Finally, items can be arranged horizontally or vertically and buttons can be displayed with icons, labels, or both.
Creating a toolbar is done with the following function:
$toolbar = new Gtk::Toolbar( $orientation, $style );
where
$orientation
may be either
'horizontal'
or
'vertical'.
and
$style
is either
'text',
'icons', or
'both'.
The style applies to all the buttons created with the `item' functions (not to buttons inserted into toolbar as separate widgets).
After creating a toolbar one can append, prepend and insert
items (that means simple text strings) or elements (that means
any widget types) into the toolbar. To describe an item we need
a label text, a tooltip text, a private tooltip text, an icon
for the button and a callback function for it. For example, to
append or prepend an item you may use the following functions:
$toolbar->append_item( $text,
These functions return a Button which you could then use to add
callbacks for signal and event handling.
$tooltip_text,
$tooltip_private_text,
$pixmap );
$toolbar->prepend_item( $text,
$tooltip_text,
$tooltip_private_text,
$pixmap );
If you want to use
insert_item(),
the only additional parameter which must be specified is the
position in which the item should be inserted, thus:
$toolbar->insert_item( $text,
$tooltip_text,
$tooltip_private_text,
$pixmap,
$position );
Toolbars can also be used to hold any type of widget. The
following functions are similar to the ones already mentioned,
but use a Widget instead of text and pixmap:
$toolbar->append_widget( $widget,
$tooltip_text,
$tooltip_private_text );
$toolbar->prepend_widget( $widget,
$tooltip_text,
$tooltip_private_text );
$toolbar->insert_widget( $widget,
$tooltip_text,
$tooltip_private_text,
$position );
To simplify adding spaces between toolbar items, you may use the
following functions:
$toolbar->append_space();
$toolbar->prepend_space();
$toolbar->insert_space( $position );
While the size of the added space can be set globally for a
whole toolbar with the function:
$toolbar->set_space_size( $space_size );
Also, you may choose between two styles of spaces. The space may
be either an empty space, or a line. Setting this is as simple as
a call to:
$toolbar->set_space_style( $space_style );
Where
$space_style
is either
'empty' or
'line'.
Items, widgets, and space are each examples of elements.
Usually, you will want to used on the the functions above for
convenience, but the following functions are also available:
$toolbar->append_element( $child_type,
The arguments are:
$widget,
$text,
$tooltip_text,
$tooltip_private_text,
$icon,
\&callback,
@callback_data );
$toolbar->prepend_element( $child_type,
$widget,
$text,
$tooltip_text,
$tooltip_private_text,
$icon,
\&callback,
@callback_data );
$toolbar->insert_element( $child_type,
$widget,
$text,
$tooltip_text,
$tooltip_private_text,
$icon,
\&callback,
@callback_data,
$position );
- $child_type
The child type may be either 'space', 'button', 'togglebutton', 'radiobutton', or 'widget'.
- $widget
The widget to add to the toolbar.
- $text
The elements label.
- $tooltip_text
The text for the button tooltip.
- $tooltip_private_text
used for context sensitive help about the toolbar element.
- $icon
the pictoral representation of the element's function.
- \&callback
a reference to the subroutine to be executed when the button is pressed.
- @callback_data
the data you wish to be passed to the callback.
- $position
the position to insert the element (insert only).
If it's required, the orientation of a toolbar and its style can
be changed on the fly using the following functions:
$toolbar->set_orientation( $orientation );
$toolbar->set_style( $style );
$toolbar->set_tooltips( $enable );
Where
$orientation
is either
'horizontal' or
'vertical'.
The
$style
is used to set appearance of the toolbar items by using one of
'icons',
'text', or
'both'.
The relief styles of the toolbar buttons can be easily set using:
$toolbar->set_button_relief( $relief_style );
Where
$relief_style
is either
'normal',
'halt', or
'none'.
The relief style of a toolbar may be retrieved using:
$toolbar->get_button_relief();
To show some other things that can be done with a toolbar, let's take a look at the program below. It has been brought to my attention that depending on the version of Gtk-Perl you are using, you may need to replace 'radiobutton' with 'radio_button', and replace 'togglebutton' with 'toggle_button'.
This example uses pixmaps, which are explained later .
#!/usr/bin/perl -w use Gtk ; use strict ; set_locale Gtk; init Gtk; my $false = 0; my $true = 1; my @gtk_xpm = ( '32 39 5 1', '. c none', '+ c black', '@ c #3070E0', '# c #F05050', '$ c #35E035', '................+...............', '..............+++++.............', '............+++++@@++...........', '..........+++++@@@@@@++.........', '........++++@@@@@@@@@@++........', '......++++@@++++++++@@@++.......', '.....+++@@@+++++++++++@@@++.....', '...+++@@@@+++@@@@@@++++@@@@+....', '..+++@@@@+++@@@@@@@@+++@@@@@++..', '.++@@@@@@+++@@@@@@@@@@@@@@@@@@++', '.+#+@@@@@@++@@@@+++@@@@@@@@@@@@+', '.+##++@@@@+++@@@+++++@@@@@@@@$@.', '.+###++@@@@+++@@@+++@@@@@++$$$@.', '.+####+++@@@+++++++@@@@@+@$$$$@.', '.+#####+++@@@@+++@@@@++@$$$$$$+.', '.+######++++@@@@@@@++@$$$$$$$$+.', '.+#######+##+@@@@+++$$$$$$@@$$+.', '.+###+++##+##+@@++@$$$$$$++$$$+.', '.+###++++##+##+@@$$$$$$$@+@$$@+.', '.+###++++++#+++@$$@+@$$@++$$$@+.', '.+####+++++++#++$$@+@$$++$$$$+..', '.++####++++++#++$$@+@$++@$$$$+..', '.+#####+++++##++$$++@+++$$$$$+..', '.++####+++##+#++$$+++++@$$$$$+..', '.++####+++####++$$++++++@$$$@+..', '.+#####++#####++$$+++@++++@$@+..', '.+#####++#####++$$++@$$@+++$@@..', '.++####++#####++$$++$$$$$+@$@++.', '.++####++#####++$$++$$$$$$$$+++.', '.+++####+#####++$$++$$$$$$$@+++.', '..+++#########+@$$+@$$$$$$+++...', '...+++########+@$$$$$$$$@+++....', '.....+++######+@$$$$$$$+++......', '......+++#####+@$$$$$@++........', '.......+++####+@$$$$+++.........', '.........++###+$$$@++...........', '..........++##+$@+++............', '...........+++++++..............', '.............++++...............' ); my $dialog; my $handlebox; my $toolbar; my $icon; my $mask; my $iconw; my $close_button; my $icon_button; my $text_button; my $both_button; my $tooltips_button; my $entry; $dialog = new Gtk::Dialog(); $dialog->set_title( "Toolbar Example" ); $dialog->set_usize( 600, 300 ); $dialog->signal_connect( "delete_event", sub { Gtk-> exit ( 0 ); } ); # we need to realize the window because we use pixmaps for # items on the toolbar in the context of it $dialog->realize(); # To make it nice we'll put the toolbar into the handle box, so # that it can be detached from the main window. A handle box is # just another box that can be used to pack widgets into. The # difference is that it can be detached from a parent window. This # is often used for a detachable toolbar. $handlebox = new Gtk::HandleBox(); $dialog->vbox->pack_start( $handlebox, $false, $false, 5 ); # toolbar will be horizontal, with both icons and text, and with # 5 pixel spaces between items and finally, we'll also put it into # our handlebox $toolbar = new Gtk::Toolbar( 'horizontal', 'both' ); $toolbar->border_width( 5 ); $toolbar->set_space_size( 5 ); $handlebox->add( $toolbar ); # now we create icon with mask: we'll reuse it to create # icon widgets for toolbar items ( $icon, $mask ) = Gtk::Gdk::Pixmap->create_from_xpm_d( $dialog->window, $dialog->style->white, @gtk_xpm ); # our first item is <Close> button $iconw = new Gtk::Pixmap( $icon, $mask ); $close_button = $toolbar->append_item( "Close", "Close this app", "Private", $iconw ); $close_button->signal_connect( "clicked", sub { Gtk-> exit ( 0 ); } ); $toolbar->append_space(); # now, let's make our radio buttons group... $iconw = new Gtk::Pixmap( $icon, $mask ); $icon_button = $toolbar->append_element( 'radiobutton', new Gtk::RadioButton(), "Icon", "Only icons in toolbar", "Private", $iconw ); $icon_button->signal_connect( "clicked", \&radio_event, $toolbar ); $toolbar->append_space(); # following radio buttons refer to previous ones $iconw = new Gtk::Pixmap( $icon, $mask ); $text_button = $toolbar->append_element( 'radiobutton', $icon_button, "Text", "Only texts in toolbar", "Private", $iconw ); $text_button->signal_connect( "toggled", \&radio_event, $toolbar ); $toolbar->append_space(); $iconw = new Gtk::Pixmap( $icon, $mask ); $both_button = $toolbar->append_element( 'radiobutton', $text_button, "Both", "Icons and text is toolbar", "Private", $iconw ); $both_button->signal_connect( "toggled", \&radio_event, $toolbar ); $toolbar->append_space(); $both_button->set_active( $true ); # following radio buttons refer to previous ones $iconw = new Gtk::Pixmap( $icon, $mask ); $tooltips_button = $toolbar->append_element( 'togglebutton', " ", "Tooltips", "Toolbar with or without tips", "Private", $iconw ); $tooltips_button->signal_connect( "toggled", \&toggle_event, $toolbar ); $toolbar->append_space(); $tooltips_button->set_active( $true ); # to pack a widget into toolbar, we only have to # create it and append it with an appropriate tooltip $entry = new Gtk::Entry(); $toolbar->append_widget( $entry, "This is just an entry", "Private" ); # well, it isn't created within thetoolbar, so we must still show it $entry->show(); $toolbar->show(); $handlebox->show(); $dialog->show(); main Gtk; exit ( 0 ); ### Subroutines # when one of the buttons is toggled, we just # check which one is active and set the style of the toolbar # accordingly sub radio_event { my ( $widget, $toolbar ) = @_; if ( $text_button->active ) { $toolbar->set_style( 'text' ); } elsif ( $icon_button->active ) { $toolbar->set_style( 'icons' ); } elsif ( $both_button->active ) { $toolbar->set_style( 'both' ); } } # check given toggle button and enable/disable tooltips sub toggle_event { my ( $widget, $toolbar ) = @_; $toolbar->set_tooltips( $widget->active ); } # END EXAMPLE PROGRAM
Toolbar Example Screenshot
Описание Gtk-Perl | ||
---|---|---|
Предыдущий | Следующий |
Вам может показаться интересным, как вы можете заставить GTK выполнять
полезную работу при вызове
main Gtk.
Для этого у Вас есть несколько возможностей. Используя приведенную функцию,
вы можете создавать функцию задержки, которая будет периодически вызываться.
$timer = Gtk->timeout_add( $interval, \&function,
@function_data );
Первый аргумент - интервал (в миллисекундах) между вызовами вашей функции.
Второй аргумент - функция, которую вы хотите авызвать
и третий - данные для вызываемой функции.
Возвращаемое значение - число, которое может быть использовано для остановки
задержки при помощи
Gtk->timeout_remove( $timer );
Вы также можете остановить функцию задержки возвращая ложное значение из вызываемой вами функции, в противном случае - истинное.
Объявление вашего вызова должно быть похожим на нечто такое:
sub timeout_callback
{
my ( @data ) = @_;
...
}
Изящная особенность GDK (библиотеки, лежащей в основе GTK) - способность
контролировать
данные в файловых дескрипторах (возвращаемых функциями open()
или
socket()).
Эта возможность моет быть полезной для сетевых приложений. Функция
$id = Gtk::Gdk->input_add( $source, $condition,
\&function, @data );
берет файловый декриптор первым аргументом, а вторым аргументом можно задать
то, что необходимо контролировать с помощью GDK
Возможные варианты:
'read' - вызывает нужную функцию, когда в файловом дексрипторе есть данные и их надо прочитать
'write' - вызывает нужную функцию, когда файловый дескриптор готов к записи.
Я уверен, что Вы уже поняли, что третий аргумент - фукнция, которую необходимо вызвать, а четвертый - данные для этой функции.
Возвращаемое значение - некое значение, которое может быть использовано
для остановки контроля файлового дескриптора
например при помощи такой функции:
Gtk::Gdk->input_remove( $id );
Вызов функции может быть определен например так:
sub input_callback
для которой источник и условие срабатывания были определены ранее
{
my ( $source, $condition, @data ) = @_;
...
}
Что если Вы имеете некоторую функцию, которую бы вам хотелось вызываеть в
случае, когда ничего не происходит?
$idle = Gtk->idle_add( \&function, @data );
Этот вызов GTK происходит, в случае например, холостой работы (м.б. что-то
в данных не прошло по всем условиям),
Чтобы убрать этот вызов - необходимо написать так:
Gtk->idle_remove( $idle );
Объяснять значения аргументов я не буду, т.к. они очень сильно похожи на описанные выше. Соответственно по срабатыванию данного условия вызывается функция function. Ложное значение будет прерывать выполнение idle_add()
Предыдущая | В начало | Следующая |
Базовые возможности | Вверх | Графика |
Иерархия наследования
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' сигнал;
Описание Gtk-Perl | ||
---|---|---|
Предыдущая | Следующая |
Object
+--- Data
+--- Tooltips
Подсказки (всплывающие подсказки) - это небольшие строки текста, которые выскакивают (всплывают), когда вы останавливаете курсор над кнопкой или другим виджетом на несколько секунд.
Виджеты, которые не принимаеют событий (виджиты, которые не имеют собственного окна) не будут работать с подсказками.
Итак, просто создаем объект подсказок и используем его для задания
текста подсказок
другим объектам.
new Gtk::Tooltips();
Создав подсказку и виджет, пояснения к поведению которого нам нужно
задать,
используем этот простой метод:
$tooltips->set_tip( $widget, $tip_text, $tip_private );
В качестве первого аргумента указываем виджет к которому мы хотим добавить
всплывающую
подсказку, вторым аргументом задаем текст подсказки. Последним аргументом
идет строка,
которая может быть использована как идентифакатор при использовании GTK
TipsQuery
виджета, который используют для контекстной помощи.
Сейчас оставим это поле пустым.
Приведем короткий пример:
$button = new Gtk::Button( "Button" );
$tooltips = new Gtk::Tooltips();
$tooltps->set_tip( $button, "This is the button", "" );
Рассмотрим другие методы, которые могут быть использованы с подказками. Я просто перечислю их с коротким описанием их действий.
Включить или отключить набор подсказок можно методами:
$tooltips->enable();
$tooltips->disable();
Установить период в милисекундах, на который нужно задержать курсор над
данным виджетом,
что бы появилась подсказка:
$tooltips->set_delay( $delay );
По умолчанию используется промежуток в 500 милисекунд (пол секунды).
И в заключении, вы можете установить цвет фонового и лицевого цвета
подсказки
используя:
$tooltips->set_colors( $background, $foreground );
Вот и все методы. :-)
Предыдущая | На главную | Следующая |
Группы радиокнопок | Вверх | Координатная сетка |
The purpose of tree widgets is to display hierarchically-organized data. The Tree widget itself is a vertical container for widgets of type TreeItem. Tree itself is not terribly different from CList - both are derived directly from Container, and the Container methods work in the same way on Tree widgets as on CList widgets. The difference is that Tree widgets can be nested within other Tree widgets. We'll see how to do this shortly.
The Tree widget has its own window, and defaults to a white background, as does CList. Also, most of the Tree methods work in the same way as the corresponding CList ones. However, Tree is not derived from CList, so you cannot use them interchangeably.
A Tree is created in the usual way, using:
$tree = new Gtk::Tree();
Like the CList widget, a Tree will simply keep growing as more items are added to it, as well as when subtrees are expanded. For this reason, they are almost always packed into a ScrolledWindow. You might want to use set_usize() on the scrolled window to ensure that it is big enough to see the tree's items, as the default size for ScrolledWindow is quite small.
Now that you have a tree, you'll probably want to add some items
to it. The section on the
Tree Item Widget
below explains the gory details of TreeItem. For now, it'll
suffice to create one, using:
$tree = new_with_label Gtk::TreeItem( $label );
You can then add it to the tree using one of the following:
$tree->append( $tree_item );
$tree->prepend( $tree_item );
Note that you must add items to a Tree one at a time - there is
no equivalent to the
items()
functions of a Gtk::CList.
A subtree is created like any other Tree widget. A subtree is
added to another tree beneath a tree item, using:
$tree_item->set_subtree( $subtree );
You do not need to call show() on a subtree before or after adding it to a TreeItem. However, you must have added the TreeItem in question to a parent tree before calling set_subtree(). This is because, technically, the parent of the subtree is not the TreeItem which "owns" it, but rather the Tree which holds that TreeItem.
When you add a subtree to a TreeItem, a plus or minus sign appears beside it, which the user can click on to "expand" or "collapse" it, meaning, to show or hide its subtree. TreeItems are collapsed by default. Note that when you collapse a TreeItem, any selected items in its subtree remain selected, which may not be what the user expects.
As with CList, the Tree type has a
selection
field, and it is possible to control the behaviour of the tree
(somewhat) by setting the selection type using:
$tree->set_selection_mode( $mode );
The semantics associated with the various selection modes are
described in the section on the
CListWidget
.
As with the CList widget, the
'select_child',
'unselect_child'
(not really - see the discussion about Tree signals below for an
explanation), and
'selection_changed'
signals are emitted when list items are selected or
unselected. However, in order to take advantage of these
signals, you need to know
which
Tree widget they will be emitted by, and where to find the list
of selected items.
This is a source of potential confusion. The best way to explain this is that though all Tree widgets are created equal, some are more equal than others. All Tree widgets have their own X window, and can therefore receive events such as mouse clicks (if their TreeItems or their children don't catch them first!). However, to make 'single' and 'browse' selection types behave in a sane manner, the list of selected items is specific to the topmost Tree widget in a hierarchy, known as the "root tree".
Thus, accessing the selection field directly in an arbitrary Tree widget is not a good idea unless you know it's the root tree.
Finally, the 'select_child' (and 'unselect_child', in theory) signals are emitted by all trees, but the 'selection_changed' signal is only emitted by the root tree. Consequently, if you want to handle the 'select_child' signal for a tree and all its subtrees, you will have to call signal_connect() for every subtree.
The Fields in the Tree (from the C structure) looks like this:
container
children
root_tree
tree_owner
selection
level
indent_value
current_index
selection_mode
view_mode
view_line
In addition, is_root_tree() returns a boolean value which indicates whether a tree is the root tree in a Tree hierarchy, while root_tree() returns the root tree.
Instead of directly accessing the children field of a Tree widget, it's probably best to access them using the children() function, inherited from the Container Widget.
The tree_owner field is defined only in subtrees, where it points to the TreeItem widget which holds the tree in question. The level field indicates how deeply nested a particular tree is; root trees have level 0, and each successive level of subtrees has a level one greater than the parent level. This field is set only after a Tree widget is actually mapped (i.e. drawn on the screen).
The 'selection_changed' signal will be emitted whenever the selection field of a Tree has changed. This happens when a child of the Tree is selected or deselected.
The select_child signal is emitted when a child of the Tree is about to get selected. This happens on calls to select_item(), select_child(), on all button presses and calls to item_toggle() and toggle(). It may sometimes be indirectly triggered on other occasions where children get added to or removed from the Tree.
The 'unselect_child' signal is emitted when a child of the Tree is about to get deselected. As of GTK 1.0.4, this seems to only occur on calls to unselect_item() or unselect_child(), and perhaps on other occasions, but not when a button press deselects a child (the 'select_child' signal is emitted instead), nor on emission of the 'toggle' signal by toggle().
To insert a tree item into a Tree, use:
$tree->insert( $tree_item, $position );
where
$position
is the position in the tree.
To remove items from a tree, use:
$tree->remove_items( @items );
Note that removing an item from a tree dereferences and
(usually) destroys it
and
its subtree, if it has one,
and
all subtrees in that subtree. If you want to remove only one item,
you can use
remove().
To remove a series of items, use:
$tree->clear_items( $start, $end );
which removes the items from position
$start
to position
$end
from a Tree. The same warning about dereferencing applies here,
as
clear_items()
simply constructs a list and passes it to
remove_items().
To select the child at a position in the tree, use:
$tree->select_item( $postition );
which will emit the
'select_item'
signal for the child at position
$position,
thus selecting the child (unless you unselect it in a signal
handler).
Conversely, to unselect the child at a position, use:
$tree->unselect_item( $position );
which emits the
'unselect_item'
signal for the child at position
$position,
thus unselecting the child.
To select a tree item, use:
$tree->select_child( $tree_item );
Which emits the
'select_item'
signal for the child
$tree_item,
thus selecting it.
And to select a tree item, use:
$tree->unselect_child( $tree_item );
Which emits the
'unselect_item'
signal for the child
$tree_item,
thus unselecting it.
If you want to get the position in the tree of a child, then
$tree->child_position( $child );
is for you. It returns the position in the tree of
$child,
unless
$child
is not in the tree, in which case it returns
-1.
The selection mode of a tree can be set using:
$tree->set_selection_mode( $mode );
where the selection mode can be one of
'single'
(the default),
'browse',
'multiple', or
'extended'.
This is only defined for root trees, which makes sense, since
the root tree "owns" the selection. Setting it for subtrees has
no effect at all; the value is simply ignored.
The "view mode" can be set using:
$tree->set_view_mode( $mode );
The "view mode" can be either
'line'
(the default) or
'item'.
The view mode propagates from a tree to its subtrees when they
are mapped, and shouldn't be set exclusively to a subtree
(setting it on a subtree after it has been mapped, would have a
somewhat unpredictable effect).
The term "view mode" is rather ambiguous - basically, it controls the way the highlight is drawn when one of a tree's children is selected. If it's 'line', the entire TreeItem widget is highlighted, while for 'item', only the child widget (usually the label) is highlighted.
Drawing of connecting lines between tree items can be toggled
using:
$tree->set_view_lines( $show_lines );
If
$show_lines
is a true value, the connecting lines are drawn, and if it is a
false value, then they aren't.
The root ree of a Tree object can be retreived using:
$tree->root_tree();
The selection list of the root tree can be retreived using:
$tree->selection();
The TreeItem widget, like CListItem, is derived from Item, which in turn is derived from Bin. Therefore, the item itself is a generic container holding exactly one child widget, which can be of any type. The TreeItem widget has a number of extra fields, but the only one we need be concerned with is the subtree field.
The fields available for the TreeItem struct looks like this:
item
subtree
pixmaps_box
plus_pix_widget
minus_pix_widget
pixmaps
expanded
The pixmaps_box field is an EventBox which catches clicks on the plus/minus symbol which controls expansion and collapsing. The pixmaps field points to an internal data structure. Since you can always obtain the subtree of a TreeItem with the subtree() function it's probably advisable never to touch the insides of a TreeItem unless you know what you're doing.
A TreeItem usually holds a label, so the convenience function
new_with_label Gtk::TreeItem()
is provided. The same effect can be achieved using code like the
following:
$tree_item = new Gtk::TreeItem();
$label = new Gtk::Label( $text );
$label->set_alignment( 0.0, 0.5 );
$tree_item->add( $label );
$show( $label );
As one is not forced to add a Label to a TreeItem, you could also add an HBox or an Arrow, or even a Notebook (though your app will likely be quite unpopular in this case) to the TreeItem.
If you remove all the items from a subtree, it will be destroyed
and unparented, unless you reference it beforehand, and the
TreeItem which owns it will be collapsed. So, if you want it to
stick around, do something like the following:
$tree->ref();
$owner = $tree->tree_owner;
$tree->remove( $item );
if ( $tree->parent )
{
$tree->unref();
}
else
{
$owner->expand();
$owner->set_subtree( $tree );
}
Finally, drag-n-drop does work with TreeItems. You just have to make sure that the TreeItem you want to make into a drag item or a drop site has not only been added to a Tree, but that each successive parent widget has a parent itself, all the way back to a toplevel or dialog window, when you call dnd_drag_set() or dnd_drop_set(). Otherwise, strange things will happen.
TreeItem inherits the 'select', 'deselect', and 'toggle' signals from Item. In addition, it adds two signals of its own, 'expand' and 'collapse'.
The 'expand' signal is emitted when the tree item's subtree is about to be expanded, that is, when the user clicks on the plus sign next to the item, or when the program calls expand().
The
'collapse'
signal is emitted when the tree item's subtree is about to be
collapsed, that is, when the user clicks on the minus sign next
to the item, or when the program calls
collapse().
$tree_item->remove_subtree();
This removes all of tree_item's subtree's children (thus
unreferencing and destroying it, any of its children's subtrees,
and so on...), then removes the subtree itself, and hides the
plus/minus sign.
This is a somewhat more complex example than I normally include, but I felt it was appropriate. As well as demonstrating the Tree widget, this example also uses quite a bit of the CList widget. From this, we could easily add a button bar or menu, and add functionality such as delete, copy, or move a file, which would make this a lightweight file manager.
#!/usr/bin/perl -w use Gtk ; use strict ; set_locale Gtk; init Gtk; my $false = 0; my $true = 1; my $root_dir = "/"; my @titles; my $window; my $pane; my $vbox; my $tree_scrolled_win; my $list_scrolled_win; my $entry; my $tree; my $leaf; my $subtree; my $item; my $list; # Create a window $window = new Gtk::Window( 'toplevel' ); $window->set_usize( 725, 500 ); $window->set_title( "File Viewer" ); $window->signal_connect( "delete_event", sub { Gtk-> exit ( 0 ); } ); # Create a horizontal pane $pane = new Gtk::HPaned(); $window->add( $pane ); $pane->set_handle_size( 10 ); $pane->set_gutter_size( 8 ); $pane->show(); # Create a VBox for the Entry and Tree Scrolled Window $vbox = new Gtk::VBox( $false, 0 ); $pane->add1( $vbox ); $vbox->show(); # Create the Text Entry $entry = new Gtk::Entry(); $vbox->pack_start( $entry, $false, $false, 4 ); $entry->signal_connect( 'activate', \&entry_activate ); $entry->show(); # Create a ScrolledWindow for the tree $tree_scrolled_win = new Gtk::ScrolledWindow( undef, undef ); $tree_scrolled_win->set_usize( 150, 400 ); $vbox->pack_start( $tree_scrolled_win, $true, $true, 0 ); $tree_scrolled_win->set_policy( 'automatic', 'automatic' ); $tree_scrolled_win->show(); # Create a ScrolledWindow for the list $list_scrolled_win = new Gtk::ScrolledWindow( undef, undef ); $pane->add2( $list_scrolled_win ); $list_scrolled_win->set_policy( 'automatic', 'automatic' ); $list_scrolled_win->show(); # Create root tree $tree = new Gtk::Tree(); $tree_scrolled_win->add_with_viewport( $tree ); $tree->set_selection_mode( 'single' ); $tree->set_view_mode( 'item' ); $tree->show(); # Create root tree item widget $leaf = new_with_label Gtk::TreeItem( $root_dir ); $tree->append( $leaf ); $leaf->signal_connect( 'select', \&select_item, $root_dir ); $leaf->set_user_data( $root_dir ); $leaf->show(); # Create the subtree if ( has_sub_trees( $root_dir ) ) { $subtree = new Gtk::Tree(); $leaf->set_subtree( $subtree ); $leaf->signal_connect( 'expand', \&expand_tree, $subtree ); $leaf->signal_connect( 'collapse', \&collapse_tree ); $leaf->expand(); } # Create list box @titles = qw( Filename Size Permissions Owner Group Time Date ); $list = new_with_titles Gtk::CList( @titles ); $list_scrolled_win->add( $list ); $list->set_column_width( 0, 100 ); $list->set_column_width( 1, 50 ); $list->set_column_width( 2, 80 ); $list->set_column_width( 3, 50 ); $list->set_column_width( 4, 50 ); $list->set_column_width( 5, 50 ); $list->set_column_width( 6, 100 ); $list->set_selection_mode( 'multiple' ); $list->set_shadow_type( 'none' ); $list->show(); $window->show(); main Gtk; exit ( 0 ); ### Subroutines # Callback for expanding a tree - find subdirectories and add them to # tree sub expand_tree { my ( $item, $subtree ) = @_; my $dir; my $dir_entry; my $path; my $item_new; my $new_subtree; $dir = $item->get_user_data(); chdir ( $dir ); foreach $dir_entry ( <*> ) { if ( -d $dir_entry ) { $path = $dir . "/" . $dir_entry; $path =~ s|//|/|g; $item_new = new_with_label Gtk::TreeItem( $dir_entry ); $item_new->set_user_data( $path ); $item_new->signal_connect( 'select', \&select_item, $path ); $subtree->append( $item_new ); $item_new->show(); if ( has_sub_trees( $path ) ) { $new_subtree = new Gtk::Tree(); $item_new->set_subtree( $new_subtree ); $item_new->signal_connect( 'expand', \&expand_tree, $new_subtree ); $item_new->signal_connect( 'collapse', \&collapse_tree ); } } } chdir ( ".." ); } # Callback for collapsing a tree -- removes the subtree sub collapse_tree { my ( $item ) = @_; my $subtree = new Gtk::Tree(); $item->remove_subtree(); $item->set_subtree( $subtree ); $item->signal_connect( 'expand', \&expand_tree, $subtree ); } # Test whether a directory has subdirectories sub has_sub_trees { my ( $dir ) = @_; my $file; foreach $file ( <$dir/*> ) { return $true if ( -d $file ); } return ( $false ); } # Called whenever an item is clicked on the tree widget. sub select_item { my ( $widget, $path ) = @_; $entry->set_text( $path ); show_files( $path ); } # Called when enter is pressed in the Entry widget sub entry_activate { my ( $entry ) = @_; my $path = $entry->get_text(); if ( -d $path ) { show_files( $path ); } else { $entry->set_text( "/" ); } } # Show all the files in a path. sub show_files { my ( $path ) = @_; my $file; $list->clear(); for $file ( <$path/*> ) { unless ( -d $file ) { my @lstat = lstat( $file ); my ( $mode, $uid, $gid, $size, $mtime) = ( @lstat )[ 2, 4, 5, 7, 9 ]; my @time = localtime( $mtime ); my ( $mon, $day, $year, $hour, $min ) = ( @time )[ 4, 3, 5, 2, 1 ]; $min = "0" . $min if ( $min < 10 ); my $time = $hour . ":" . $min; my $month = ( "Jan", "Feb", "Mar", "Apr", "May", "Jun", "Jul", "Aug", "Sep", "Oct", "Nov", "Dec" )[$mon]; my $date = $month . " " . $day . ", " . ( 1900 + $year ); my $user = getpwuid( $uid ); my $group = getgrgid( $gid ); $file =~ s|/.*/||g; $list->append( $file, $size, $mode, $user, $group, $time, $date ); } } } # END EXAMPLE PROGRAM
Tree Example Screenshot
Описание Gtk-Perl | ||
---|---|---|
Предыдущая | Следующая |
Маловероятно, что Вы когда нибудь будете использовать виджет текущей позиции непосредственно. Возможно, что Вы будете использовать что то типа прокрутки которая использует виджет текущей позиции
Виджет текущей позиции позволяет Вам помещать больший виджет используя полосы прокрутки (??? непонятно о чем он вообще, потом посмотреть заново).
Виджет текущей позиции можно создать при помощи следующей функции:
$viewport = new Gtk::Viewport( $hadjustment,
$vadjustment );
Видно, что можноопределить горизонтальное и вертикальное выравнивание, которое будет использовать виджет во время своего создания. Если при создании виджета параметры будут опущены, все произойдет "тихо и незаметно" (с) www.linux.org.ru ...
Реуглировать выравнивание на виджете после его создания можно при помощи
следующих четрыех функций:
$viewport->get_hadjustment();
$viewport->get_vadjustment();
$viewport->set_hadjustment( $adjustment );
$viewport->set_vadjustment( $adjustment );
Для изменения внешнего вида используется только одна функция виджета текущей
позиции
$viewport->set_shadow_type( $type );
Значения для параметра
$type
могут быть такими:
'none'
'in'
'out'
'etched_in'
'etched_out'
Предыдущая | На главную | Следующая |
Фиксированные объекты | Вверх | Виджет области событий |
Обзор Gtk-Perl | ||
---|---|---|
Предыдущий | Следующий |
show() говорит Gtk-Perl что виджету выставлены все атрибуты и он может быть показан на экране. Можно так-же использовать hide() для скрытия виджета. Порядок, в котором будут выведены виждеты, не важен, но лучше, если виджет будет выведен сразу после его создания(некоторый стиль написания). Поотомки родительского виждета(window так-же явялется виждетом) появятся только тогда, когда будет показан их парент.
Иерархия виждетов показана в виде иерархии классов, в котором базовым для всего Gtk является класс Gtk::Object:
Gtk::Object
+-Gtk::Widget
| +-Gtk::Misc
| | +-Gtk::Label
| | | +-Gtk::AccelLabel
| | | +-Gtk::TipsQuery
| | +-Gtk::Arrow
| | +-Gtk::Image
| | +-Gtk::Pixmap
| +-Gtk::Container
| | +-Gtk::Bin
| | | +-Gtk::Alignment
| | | +-Gtk::Frame
| | | | +-Gtk::AspectFrame
| | | +-Gtk::Button
| | | | +-Gtk::ToggleButton
| | | | | +-Gtk::CheckButton
| | | | | +-Gtk::RadioButton
| | | | +-Gtk::OptionMenu
| | | +-Gtk::Item
| | | | +-Gtk::MenuItem
| | | | | +-Gtk::CheckMenuItem
| | | | | | +-Gtk::RadioMenuItem
| | | | | +-Gtk::TearoffMenuItem
| | | | +-Gtk::ListItem
| | | | +-Gtk::TreeItem
| | | +-Gtk::Window
| | | | +-Gtk::ColorSelectionDialog
| | | | +-Gtk::Dialog
| | | | | +-Gtk::InputDialog
| | | | +-Gtk::DrawWindow
| | | | +-Gtk::FileSelection
| | | | +-Gtk::FontSelectionDialog
| | | | +-Gtk::Plug
| | | +-Gtk::EventBox
| | | +-Gtk::HandleBox
| | | +-Gtk::ScrolledWindow
| | | +-Gtk::Viewport
| | +-Gtk::Box
| | | +-Gtk::ButtonBox
| | | | +-Gtk::HButtonBox
| | | | +-Gtk::VButtonBox
| | | +-Gtk::VBox
| | | | +-Gtk::ColorSelection
| | | | +-Gtk::GammaCurve
| | | +-Gtk::HBox
| | | +-Gtk::Combo
| | | +-Gtk::Statusbar
| | +-Gtk::CList
| | | +-Gtk::CTree
| | +-Gtk::Fixed
| | +-Gtk::Notebook
| | | +-Gtk::FontSelection
| | +-Gtk::Paned
| | | +-Gtk::HPaned
| | | +-Gtk::VPaned
| | +-Gtk::Layout
| | +-Gtk::List
| | +-Gtk::MenuShell
| | | +-Gtk::MenuBar
| | | +-Gtk::Menu
| | +-Gtk::Packer
| | +-Gtk::Socket
| | +-Gtk::Table
| | +-Gtk::Toolbar
| | +-Gtk::Tree
| +-Gtk::Calendar
| +-Gtk::DrawingArea
| | +-Gtk::Curve
| +-Gtk::Editable
| | +-Gtk::Entry
| | | +-Gtk::SpinButton
| | +-Gtk::Text
| +-Gtk::Ruler
| | +-Gtk::HRuler
| | +-Gtk::VRuler
| +-Gtk::Range
| | +-Gtk::Scale
| | | +-Gtk::HScale
| | | +-Gtk::VScale
| | +-Gtk::Scrollbar
| | +-Gtk::HScrollbar
| | +-Gtk::VScrollbar
| +-Gtk::Separator
| | +-Gtk::HSeparator
| | +-Gtk::VSeparator
| +-Gtk::Preview
| +-Gtk::Progress
| +-Gtk::ProgressBar
+-Gtk::Data
| +-Gtk::Adjustment
| +-Gtk::Tooltips
+-Gtk::ItemFactory
Знание этой иерархии важно, так как позволяет знать, какую функцию можно вызывать в кждом виджете. Для примера, SpinButton виджет относится к классу методов Entry, который в свою очередь является методом Editable и так далее.
Следующие виджеты не ассоциированы с окнами. Если вы хотите обработать событие, то вы можете использовать EventBox.
Gtk::Alignment
Gtk::Arrow
Gtk::Bin
Gtk::Box
Gtk::Image
Gtk::Item
Gtk::Label
Gtk::Pixmap
Gtk::ScrolledWindow
Gtk::Separator
Gtk::Table
Gtk::AspectFrame
Gtk::Frame
Gtk::VBox
Gtk::HBox
Gtk::VSeparator
Gtk::HSeparator
Далее будет показан каждый из виджетов и создана простая функция, выводящая их на экран. Другой хороший источник примеров можно найти в исходниках GtkPerl.
Для создания виджета используйте
$widget = new Gtk::Widget();
Но помните, что при создании некоторых виджетов может понадобится несколько функций new() подобно функции new_with_label() для кнопок и деревьев.
Уничтожить виджет можно при помощи строчки
$widget -> destroy();
Если будет получен вызов зарезервированный как destroy, то он быдет выполнен для текущего виджета, но не для объекта, породившего этот виджет.
Следующие две функции показа и скрытия виджета уже были использованы нами в формах,Они показывают и скрывают виджет:
$widget->show();
$widget->show_now();
$widget->show_all();
$widget->hide();
$widget->hide_all();
Отметим, что если не показан контейнер, то не показан и виджет, содержащийся в этом контейнере. Рекомендуется, чтобы widgets показывался до содержания контейнеров, хотя точный порядок обычно не имеет значения, если окно показывается последним.
$widget->realize();
$widget->unrealize();
Показ необходим, когда вы хотите создать видет используя GdkWindow с запросом к X серверу. При нормальном раскладе виджет будет показан когда будет запрошена функция show(), но иногда бывает необходимо вызвать realize() до вызова show(). Основное правило заключается в том, что как правило существует лучший выход из ситуации, которая провоцирет вызов realize() до вызова show(). Вобщем короче нужно четко знать что ты делаешь в таком случае и не рекомендуется использвать первую функцию без особой в том нужды.
Gtk-perl позволяет виждету считывать фокус с клавиатуры используя следующую
функцию
$widget->grab_focus();
Виджет также может быть установлен в режим по умолчанию, это можно сделать следующими строчками:
$widget->can_default( $default );
$widget->grab_default();
Запомните, что нужно вызывать can_default() до вызова grab_default(). Аргументом функции can_default() может быть истина или ложь, определяющие может ли быть виджет введен в режим по умолчанию.
Нечувствительный виджет не отвечает на ввод. Он может так-же обозначаться как бездействующий виджет. Установить чувствительность виджета можно, используя следующую функцию:
$widget->set_sensitive( $sensitive );
где аргументом функции являются истина или ложь. Однако, если виджет устанавливается в режим чувствительности, он не будет таковый, если его родитель не является чувствительным. Для тестирования чувствительности необходимо использовать следующие функции:
$widget->sensitive();
$widget->is_sensitive();
отличие этих функций в том, что первая только проверяет widgets на чувствительнсть, в то время как вторая проверяет чувствительность всей иерархии порожденых виждетов. Только вторая функция сообщит, является widget чувствительным или нет.
Помимо автоматической установки контейнера виджетов(имеется ввиду позиция и размер), можно вручную переопределять размеры и положение виждетов на экране, используюя функции
$widget->set_uposition( $x, $y );
$widget->set_usize( $width, $height );
Функция set_uposition() устанавливает левый верхний угод виджета на экране монитора на $x пикелов слева и $y пикселов сверху. Функция set_usize() устанавливает положение виджета с шириной в $width и высотой в $height пикселов сответственно. Необходимо быть осторожным при установке параметров виждетов, например если программа будет использоваться людьми со слабым зрением, то им нехобходимо увеличить размер управляющих кнопок, или просто позволить настроить программу под себя, В то-же время, если в программе используется показ деревьев каталогов, списков и или иных стандартных объектов, виджет должен быт стрго фиксирован в зависимости от числа и типа окна, дерева или иной специфичной для XWindow оболочки графической структуры.
Предыдущая | Наверх | Следующая |
Прощай, мир! | Вверх | Обзор контейнеров |
Если необходимо поставить надпись в титле 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'(положение окна определяется текущим положением мыши).