Добавлено: как выяснилось позже, на Unix-платформах реализовать полноценный прогрессбар вполне реально. О том, как это сделать говорится в статьях Отображение прогрессбара и параллельное выполнение операции и Реальный пример применения прогрессбара.
Существует два типа прогрессбаров: пульсирующий и нарастающий. Если известно количество выполняемой работы, то применяется нарастающий, иначе - пульсирующий. Оба создаются конструктором класса GtkProgressBar().
Пульсирующий запускается методом pulse(). Шаг пульсирования указывается методом set_pulse_step().
Текст на нарастающий прогрессбар устанавливается методом set_text(), определить количество прошедших шагов можно с помощью get_fraction() (может быть от 0 до 1), а установить - set_fraction().
Данная программа никаких реальных действий не выполняет, поэтому для имитации действий я использовал timeout_add().
Полный код программы:
<?php
$window = new GtkWindow();
$window->set_position(Gtk::WIN_POS_CENTER);
$window->set_size_request(200, -1);
$window->connect_simple('destroy', array('Gtk', 'main_quit'));
$vbox = new GtkVBox();
$vbox->pack_start(new GtkLabel('Пульсирующий режим:'), FALSE, FALSE);
$pulse = new GtkProgressBar();
$pulse->set_pulse_step(0.05);
$vbox->pack_start($pulse, FALSE, FALSE);
$vbox->pack_start(new GtkLabel('Режим нарастания:'), FALSE, FALSE);
$normal = new GtkProgressBar();
$normal->set_text('0%');
$vbox->pack_start($normal, FALSE, FALSE);
$button_run = new GtkButton('Запустить');
$button_run->connect_simple('clicked', 'run', $pulse, $normal);
$vbox->pack_start($button_run, FALSE, FALSE);
$button_stop = new GtkButton('Остановить');
$button_stop->set_sensitive(FALSE);
$button_stop->connect_simple('clicked', 'stop');
$vbox->pack_start($button_stop, FALSE, FALSE);
$window->add($vbox);
$window->show_all();
Gtk::main();
function run($pulse, $normal)
{
global $timeout, $button_run, $button_stop;
$button_run->set_sensitive(FALSE);
$button_stop->set_sensitive(TRUE);
$pulse->pulse();
// Если полоса дошла до конца, то сбрасываем значение
if ($normal->get_fraction() == 1)
{
$normal->set_fraction(0);
$normal->set_text('0%');
return TRUE;
}
$normal->set_fraction($normal->get_fraction() + 0.1);
$normal->set_text($normal->get_fraction() * 100 . '%');
$timeout = Gtk::timeout_add(100, 'run', $pulse, $normal);
}
function stop()
{
global $timeout, $button_run, $button_stop;
$button_run->set_sensitive(TRUE);
$button_stop->set_sensitive(FALSE);
Gtk::timeout_remove($timeout);
}
?>
3 комментария:
http://framework.zend.com/manual/ru/zendx.console.process.unix.html
$process1 = new MyProcess();
$process1->start();
$process2 = new MyProcess();
$process2->start();
alex, спасибо. Реализацию данного способа я описал в соответствующей статье.
Спасибо, весьма интересно!
Правда, даже такую операцию как копирование одного файла большого объёма в Windows тоже можно выполнить с прогресс-баром, пусть и без многопоточности. Для этого придется копировать данные блоками, то есть не используя copy(), а читая данные блоками по несколько мегабайт (по 5 МБ, к примеру):
$handle1 = fopen("myvideo1.avi", "rb");
$handle2 = fopen("myvideo2.avi", "wb");
while (!feof($handle1))
{
fwrite($handle2, fread($handle1, 5000000));
// здесь код обновления прогресс-бара
}
fclose($handle1);
fclose($handle2);
Конечно, это обходное решение, но все же вполне работающее, да и, наверное, единственное что можно придумать в плане копирования.
Отправить комментарий