The OpenNET Project / Index page

[ новости /+++ | форум | wiki | теги | ]

Каталог документации / Раздел "Perl" / Оглавление документа

Chapter 6. Расположение виджетов в форме

Table of Contents
6.1. Теория Packing Boxes
6.2. Детальное рассмотрение расположения виджетов в форме
6.3. Пример программы

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

Object
   +--- Widget
         +--- Container
               +--- Box

При создании приложения, вам будет необходимо расположить более одного виджета на формочке, ооветственной за все приложение. В первом примере была всего одна кнопка, и поэтому можно было использовать простую конструкцию $window->add() чтобы поместить виджет в окно. Но когда нужно поместить более одного виджета, необходимо их позиционировать относительно друг друга, с тем чтобы создать некий интерфейс к создаваемому Вами приложению.

6.1. Теория Packing Boxes

Packing boxes - невидимые widget контейнеры, в которых располагаются вджеты. Packing boxes имееют две формы: горизонтальную и вертикальную. При помещении widgets в горизонтальный бокс, объекты вставлены горизонтально слева направо или наоборот в зависимости от используемого запроса. В вертикальном боксе, widgets упакованы сверху донизу или наоборот. Вы можете использовать любую комбинацию боксов для расположения виджетов внутри или рядом с двругими Packing boxes, чтобы придать желательные эффект и дизайн вашему приложению.

Для создания нового горизонтального или вертикального бокса, нужно написать следующие строчки:

$hbox = new Gtk::HBox( $homogeneous, $spacing );

$vbox = new Gtk::VBox( $homogeneous, $spacing );

Если переменная $homogeneous , то виждет можно располагать в пределах, определяемых HBox и Vbox. Переменная $spacing определяет границу в пикселах, на которую отстоят виджеты друг от друга. Следующие функции используются для расположения объектов внутри бокса:

$box->pack_start( $child, $expand, $fill, $padding );

$box->pack_end( $child, $expand, $fill, $padding );

Функция pack_start() располагает элементы списка сверху в VBox и соответственно в слева направо в HBox. Действие функции pack_end() противоположно действию pack_start(). Добавленный объект может быть другим контейнером, например много виджетов - те-же самые контейнеры, за исключением что в таких случаях как правло используются либо pixmaps либо кнопки. Расположенный виджет в боксе является дочерним к этому боксу.

Если аргумент $expand истеннен, то виджеты расположены в боксе так, что заполняют все место, если аргумент ложен, то бокс сокращается до размера виджета. Присваивая параметру расширения ложное значение виждет будет выравниваться по левому или правому краю в зависимости от желания. Следует отметить, что присваивание переменной $homogeneous значения true аналогично присваиванию значения ture переменной $expand

Если аргумент $fill истеннен, тогда дополнительное место распределено между объектами. В другом случае дополнительное свободное место распределяется между виджетами. Такое распределение возможно когда $expand выставлен в положение true.

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

6.2. Детальное рассмотрение расположения виджетов в форме

Из-за этой гибкости боксы в 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

6.3. Пример программы

Приведенная ниже программа показывает, как реализовать некоторые из типов расположения структур в приложении:

Исходный код

#!/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 );
  }





Спонсоры:
Inferno Solutions
Hosting by Hoster.ru
Хостинг:

Закладки на сайте
Проследить за страницей
Created 1996-2020 by Maxim Chirkov
Добавить, Поддержать, Вебмастеру