29 марта 2010 г.

GtkDrawingArea. Динамическое изменение содержимого области

В данной статье я расскажу о том, как вручную нарисовать и анимировать прогресс-бар. Все используемые приёмы уже обсуждались ранее: о работе с GtkDrawingArea я рассказал в статье "GtkDrawingArea. Автоматическое рисование точек на холсте", а о реализации тайм-аута в "Секундомер". Поэтому расскажу лишь непосредственно о самой реализации программы.





Для начала дополним функцию do_exponse(), чтобы она помимо фона рисовала ещё и рамку прогресс-бара. Бар будет иметь размеры 360 пикселей в ширину и 30 в высоту. Далее в функции running() (нажатие на кнопку "Запустить") через каждые 10 миллисекунд будем вызывать running_update(), в которой будем закрашивать полосу прогресса оранжевым цветом по одному пикселю. Как только полоса доходит до конца - возвращаем FALSE, тем самым останавливая обновление.

Полный код программы:

<?php
 
// Размеры холста
define('WIDTH', 400);
define('HEIGHT', 70);
 
$window = new GtkWindow();
$window->set_position(Gtk::WIN_POS_CENTER);
$window->set_title('Работа с GtkDrawingArea');
$window->set_size_request(400, 100);
$window->connect_simple('destroy', array('Gtk', 'main_quit'));
 
$vbox = new GtkVBox();
 
$vbox->pack_start($hbox = new GtkHBox(), FALSE, FALSE);
$hbox->pack_start($button_run = new GtkButton('Запустить'), TRUE, TRUE);
$hbox->pack_start($button_reset = new GtkButton('Сбросить'), TRUE, TRUE);
 
$vbox->pack_start($drawing = new GtkDrawingArea());
 
$button_run->connect_simple('clicked', 'running', $drawing, $button_run);
$button_reset->connect_simple('clicked', 'do_expose', $drawing);
$drawing->connect('expose-event', 'do_expose');
 
$window->add($vbox);
$window->show_all();
Gtk::main();
 
/**
* Функция рисует точку случайного цвета со случайными размерами в случайном месте холста :)
* @param resource $widget Виджет GtkDrawingArea
*/

function running($widget)
{
global $button_run;
 
$button_run->set_sensitive(FALSE);
 
$color_black = new GdkColor(0, 0, 0);
$point_black = new GdkGc($widget->window);
$point_black->set_rgb_fg_color($color_black);
 
$color_white = new GdkColor(65535, 65535, 65535);
$point_white = new GdkGc($widget->window);
$point_white->set_rgb_fg_color($color_white);
 
$timeout = Gtk::timeout_add(10, 'update_running', $widget);
}
 
function update_running($widget)
{
global $i, $button_reset;
 
$color_orange = new GdkColor(65535, 30000, 0);
$point_orange = new GdkGc($widget->window);
$point_orange->set_rgb_fg_color($color_orange);
 
$widget->window->draw_rectangle($point_orange, TRUE, 21 + $i, 21, 1, 29);
 
$i++;
 
// Если полоса дошла до конца бара,
// то производим сброс переменной $i и останавливаем обновление
if ($i == 359)
{
$button_reset->set_sensitive(TRUE);
$i = 0;
return FALSE;
}
// Иначе, продолжаем
else
{
return TRUE;
}
}
 
function do_expose($widget)
{
global $button_reset, $button_run;
 
$button_run->set_sensitive(TRUE);
$button_reset->set_sensitive(FALSE);
 
// Рисуем фон
$color_white = new GdkColor(65535, 65535, 65535);
$background = new GdkGC($widget->window);
$background->set_rgb_fg_color($color_white);
 
$widget->window->draw_rectangle($background, TRUE, 0, 0, WIDTH, HEIGHT);
 
// Рисуем рамку для прогресс-бара
$color_black = new GdkColor(0, 0, 0);
$point_black = new GdkGc($widget->window);
$point_black->set_rgb_fg_color($color_black);
 
$widget->window->draw_rectangle($point_black, TRUE, 20, 20, 360, 1);
$widget->window->draw_rectangle($point_black, TRUE, 20, 50, 360, 1);
$widget->window->draw_rectangle($point_black, TRUE, 20, 20, 1, 30);
$widget->window->draw_rectangle($point_black, TRUE, 380, 20, 1, 30);
}
 
?>

Комментариев нет: