Программа: Служба погоды

Программа gtk-weather.php, показанная в примере 20.2, использует механизм SOAP и погодную веб-службу для информирования о погоде по всему миру. В своем интерфейсе она объединяет многочисленные элементы управления: меню, ускоряющие клавиши, кнопки, окна текстового ввода, метки, окна с прокруткой и колоночные списки.

Чтобы использовать программу gtk-weather.php, сначала найдите станции погоды, введя условия поиска в текстовом окне, и щелкните по кнопке Search.

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

Веб-служба, которую использует эта программа, называется Global-Weather; дополнительную информацию о ней см. на http://www.capescience.comwebservicesglobalweather/index.shtml.

Пример 20.2. gtk-weather.php
// Загружаем расширение GTK
dl('php_gtk.'. (((strtoupper(substr(PHP_OS,0,3))) == 'WIN')?'dll':'so'));
// Загружаем класс SOAP-клиента
require 'SOAP/Client.php';
// Создаем главное окно и устанавливаем его название и размер
$window = &new GtkWindow();
$window->set_title('PHP Cookbook GTK Demo');
$window->set_default_size(500,200);
// Главным контейнером размещения для окна является VBox
$vbox = &new GtkVBox();
$window->add($vbox);
// Создаем объект GtkAccelGroup для хранения ускоряющих клавиш
$accelgroup = &new GtkAccelGroup();
$window->add_accel_group($accelgroup);
// Строим меню, начиная с GtkMenuBar.


Аргументы функции pack_start()
// предотвращают расширение панели меню, если окно расширяется.
$menubar = &new GtkMenuBar();
$vbox->pack_start($menubar, false, false);
// Создаем меню «File» и его ускоряющую клавишу
$menu_file_item = &new GtkMenuItem('_File');
$menu_file_item_label = $menu_file_item->child;
$menu_file_item->add_accelerator('activate',$accelgroup,
$menu_file_item_label->parse_uline('_File'),
GDK_MOD1_MASK,0);
// Добавляем меню «File» в панель меню
$menubar->add($menu_file_item);
// Создаем подменю для опций в меню «File»
$menu_file_submenu = &new GtkMenu();
$menu_file_item->set_submenu($menu_file_submenu);
// Создаем опцию «Quit» внутри меню «File» и ее ускоритель
// GDK_MOD1_MASK означает, что ускорителем служит комбинация Alt-Q, а не Q
// GTK_ACCEL_VISIBLE означает, что ускоритель показывается в меню
$menu_file_choices_quit = &new GtkMenuItem('_Quit');
$menu_file_choices_quit_label = $menu_file_choices_quit->child;
$menu_file_choices_quit->add_accelerator('activate',$accelgroup,
$menu_file_choices_quit_label->parse_uline('_Quit'),GDK_MOD1_MASK,
GTK_ACCEL_VISIBLE);
// Добавляем опцию «File | Quit» в подменю «File»
$menu_file_submenu->append($menu_file_choices_quit);
// Создаем меню «Help» и его ускоряющую клавишу
$menu_help_item = &new GtkMenuItem('_Help');
$menu_help_item_label = $menu_help_item->child;
$menu_help_item->add_accelerator('activate',$accelgroup,
$menu_help_item_label->parse_uline('_Help'),
GDK_MOD1_MASK,0);
// Добавляем меню «Help» в панель меню
$menubar->add($menu_help_item);
// Создаем подменю для опций в меню «Help»
$menu_help_submenu = &new GtkMenu();
$menu_help_item->set_submenu($menu_help_submenu);
// Создаем опцию «About» в меню «Help» и ее ускоритель
$menu_help_choices_about = &new GtkMenuItem('_About');
$menu_help_choices_about_label = $menu_help_choices_about->child;
$menu_help_choices_about->add_accelerator('activate',$accelgroup,
$menu_help_choices_about_label->parse_uline('_About'),GDK_MOD1_MASK,
GTK_ACCEL_VISIBLE);
// Добавляем опцию «Help | About» в подменю «Help»
$menu_help_submenu->append($menu_help_choices_about);
// Схема размещения элементов управления поиска станций погоды в GtkTable
$table_1 = &new GtkTable(2,4);
$vbox->pack_start($table_1);
// Размещаем метку в первой строке слева
$label_sn = &new GtkLabel('Station Name: ');
$label_sn->set_alignment(1,0.5);
$table_1->attach($label_sn,0,1,0,1, GTK_FILL);
// Размещаем поле текстового ввода в середине первой строки
// Ускоритель позволяет для подтверждения нажать «Return» в поле
$entry_sn = &new GtkEntry();
$entry_sn->add_accelerator('activate',$accelgroup,GDK_KEY_Return,0,0);
$table_1->attach($entry_sn,1,2,0,1, GTK_FILL);
// Размещаем окно с прокруткой во второй строке таблицы
$scrolledwindow_1 = &new GtkScrolledWindow();
$scrolledwindow_1->set_policy(GTK_POLICY_AUTOMATIC, GTK_POLICY_AUTOMATIC);
$table_1->attach($scrolledwindow_1,0,4,1,2,
GTK_EXPAND | GTK_SHRINK | GTK_FILL,
GTK_EXPAND | GTK_SHRINK | GTK_FILL);
// Помещаем колоночный список в окно с прокруткой.


Размещение списка внутри
// окна с прокруткой, вместо непосредственного размещения в GtkTable,
// позволяет окну не расти неограниченно для отображения всего списка
$clist_sn = &new GtkCList(4,array('Code','Name','Region','Country'));
$scrolledwindow_1->add($clist_sn);
// Устанавливаем автоматическое изменение размера столбцов в списке
for ($i = 0; $i < 4; $i++) { $clist_sn->set_column_auto_resize($i,true); }
// Добавляем кнопку «Search» в первую строку
$button_search =&new GtkButton('Search');
$table_1->attach($button_search,2,3,0,1, GTK_FILL);
// Добавляем кнопку «Add» в первую строку
$button_add = &new GtkButton('Add');
$table_1->attach($button_add,3,4,0,1, GTK_FILL);
// Схема размещения элементов управления,
// показывающих погодные условия, в другом GtkTable
$table_2 = &new GtkTable(2,3);
$vbox->pack_start($table_2);
// Добавляем метку, отображающую количество показанных станций
$label_st = &new GtkLabel('Stations: 0');
$label_st->set_alignment(0,0.5);
$table_2->attach($label_st,0,1,0,1, GTK_FILL);
// Добавляем кнопку для обновления одиночной станции
$button_update_sel = &new GtkButton('Update Selected');
$table_2->attach($button_update_sel,1,2,0,1, GTK_FILL);
// Добавляем кнопку для обновления всех станций
$button_update_all = &new GtkButton('Update All');
$table_2->attach($button_update_all,2,3,0,1, GTK_FILL);
// Добавляем колоночный список для хранения погодных условий на станциях// Этот объединенный список также помещается в окно с прокруткой
$scrolledwindow_2 = &new GtkScrolledWindow();
$scrolledwindow_2->set_policy(GTK_POLICY_AUTOMATIC, GTK_POLICY_AUTOMATIC);
$table_2->attach($scrolledwindow_2,0,3,1,2,
GTK_EXPAND | GTK_SHRINK | GTK_FILL,
GTK_EXPAND | GTK_SHRINK | GTK_FILL);
$clist_st = &new
GtkCList(5,array('Code','Temp','Precipitation','Wind','Updated'));
$scrolledwindow_2->add($clist_st);
// Устанавливаем автоматическое изменение размера столбцов в списке
for ($i = 0; $i < 5; $i++) { $clist_st->set_column_auto_resize($i,true); }
// Связываем сигналы с функциями обратного вызова
// Нажатие на кнопку «Search» или выбор Return в текстовом поле приводит
// к поиску станций погоды, чьи имена совпадают с введенным текстом
$button_search->connect('clicked','wx_searchByName',
$entry_sn,$clist_sn,$window);
$entry_sn->connect('activate','wx_searchByName',
$entry_sn,$clist_sn,$window);
// Нажатие на кнопку «Add» приводит к добавлению станции погоды
// в конце списка
$button_add->connect('clicked','cb_add_station',
$clist_sn,$clist_st,$label_st);
// Нажатие на кнопку «Update Selected» обновляет нижнюю часть
// колоночного списка для одиночной станции
$button_update_sel->connect('clicked','wx_update_report',
$clist_st,$label_st,'selected');
// Нажатие на кнопку «Update All» обновляет все станции
// внизу колоночного списка
$button_update_all->connect('clicked','wx_update_report',
$clist_st,$label_st,'all');
// Закрытие окна или выбор элемента меню «File | Quit» приводит
// к выходу из программы
$window->connect('destroy','cb_shutdown');
$menu_file_choices_quit->connect('activate','cb_shutdown');
// Выбор элемента меню «Help | About» показывает информационное окно
$menu_help_choices_about->connect('activate','cb_about_box',$window);
// Эти функции обратного вызова отслеживают текущую выбранную строку
// (если таковая имеется) в каждом колоночном списке
$clist_sn->connect('select-row','cb_clist_select_row');
$clist_sn->connect('unselect-row','cb_clist_unselect_row');
$clist_st->connect('select-row','cb_clist_select_row');
$clist_st->connect('unselect-row','cb_clist_unselect_row');
// Интерфейс установлен и необходимые сигналы привязаны к функциям
// обратного вызова.


Время показывать окно и открывать
// цикл обработки сигналов GTK.
$window->show_all();gtk::main();
/*
* ФУНКЦИИ ОБРАТНОГО ВЫЗОВА И ДРУГИЕ ВСПОМОГАТЕЛЬНЫЕ ФУНКЦИИ
*/
// используем функцию searchByName() поверх SOAP для получения списка
// станций, имена которых соответствуют указанным условиям поиска
function wx_searchByName($button,$entry,$clist,$window) {
// создаем экземпляр нового SOAP-клиента
$sc = new SOAP_Client('http://live.capescience.com/ccx/GlobalWeather');
$search_term = trim($entry->get_text());
if ($search_term) {
// вызываем удаленную функцию, если предоставлены условия поиска
$res = $sc->call('searchByName',
array(new SOAP_Value('name','string',$search_term)),
'capeconnect:GlobalWeather:StationInfo',
'capeconnect:GlobalWeather:StationInfo#searchByName');
// вызываем диалог ошибки, если SOAP-функция завершается неудачно
if (PEAR::isError($res)) {
error_dialog($res->getMessage(),$window);
return false;
}
// вызываем диалог ошибки, если нет совпадений
if (! is_array($res)) {
error_dialog('No weather stations found.',$window);
return false;
}
// добавляем каждую станцию и ее информацию в колоночный список,
// вызывая функцию append() через вызовы функций freeze()
// и thaw(), чтобы получить отображение всех данных одновременно
$clist->freeze();
$clist->clear();
foreach ($res as $station) {
$clist->append(array($station->icao,$station->name,
$station->region,$station->country));
}
$clist->thaw();
}
}
// используем функцию getWeatherReport поверх SOAP для получения
// погодных условий на конкретной станции
function wx_getWeatherReport($code) {
$sc = new SOAP_Client('http://live.capescience.com/ccx/GlobalWeather');
$res = $sc->call('getWeatherReport',
array(new SOAP_Value('code','string',$code)),
'capeconnect:GlobalWeather:GlobalWeather',
'capeconnect:GlobalWeather:GlobalWeather#getWeatherReport');
if (PEAR::isError($res)) {
error_dialog($res->getMessage());return false;
} else {
return $res;
}
}
// добавляем отчет о погоде в переменной $res в колоночный список $clist
// если переменная $row равна нулю, то отчет добавляется к списку
// если $row не равна нулю, то отчет замещает строку $row в списке
function wx_add_report($clist,$label,$res,$row = null) {
// форматируем метку даты/времени
$timestamp = str_replace('T',' ',$res->timestamp);
$timestamp = str_replace('Z',' GMT',$timestamp);
$timestamp = strftime('%H:%M:%S %m/%d/%Y',strtotime($timestamp));
// форматируем информацию о ветре
$wind = sprintf("%.2f m/s from %s",
$res->wind->prevailing_speed,
$res->wind->prevailing_direction->compass);
$clist->freeze();
if (! is_null($row)) {
// замещаем информацию в строке с номером $row
$clist->set_text($row,1,$res->temperature->string);
$clist->set_text($row,2,$res->precipitation->string);
$clist->set_text($row,3,$wind);
$clist->set_text($row,4,$timestamp);
} else {
// добавляем информацию в конец колоночного списка
$clist->append(array($res->station->icao,
$res->temperature->string,
$res->precipitation->string,
$wind,
$timestamp));
// обновляем внутренний счетчик строк колоночного списка
$rows = 1 + $clist->get_data('rows');
$clist->set_data('rows',$rows);
// обновляем метку, показывающую счетчик станций
$label->set_text("Stations: $rows");
}
$clist->thaw();
}
// обновляем условия одной станции или всех станций
// в зависимости от значения $mode
function wx_update_report($button,$clist,$label,$mode) {
switch ($mode) {
case 'selected':
// если есть выбранная строка
$selected_row = $clist->get_data('selected_row');
if (($selected_row >= 0) && (! is_null($selected_row))) {$code = $clist->get_text($selected_row,0);
// берем отчет и обновляем колоночный список
if ($res = wx_getWeatherReport($code)) {
wx_add_report($clist,$label,$res,$selected_row);
}
}
break;
case 'all':
// для каждой строки колоночного списка
for ($i = 0, $j = $clist->get_data('rows'); $i < $j; $i++) {
// берем отчет и обновляем список
if ($res = wx_getWeatherReport($clist->get_text($i,0))) {
wx_add_report($clist,$label,$res,$i);
}
}
break;
}
}
// добавляем станцию в конец списка отчетов о погоде
function cb_add_station($button,$clist,$clist_2,$label) {
$selected_row = $clist->get_data('selected_row');
// если есть выбранная строка в начале списка станций
if ($selected_row >= 0) {
$code = $clist->get_text($selected_row,0);
// получаем отчет для этой станции
if ($res = wx_getWeatherReport($code)) {
// находим строку, если этот код уже находится в списке
$row = null;
for ($i = 0, $j = $clist_2->get_data('rows'); $i < $j; $i++) {
if ($clist_2->get_text($i,0) == $code) {
$row = $i;
}
}
// добавляем станцию и ее отчет внизу списка
// отчетов (или обновляем существующую строку)
wx_add_report($clist_2,$label,$res,$row);
}
}
}
// обновляем внутреннее значение выбранной строки колоночного списка,
// когда строка выбирается
function cb_clist_select_row($clist,$row,$col,$e) {
$clist->set_data('selected_row',$row);
}
// удаляем внутреннее значение выбранной строки колоночного списка,
// когда выбор строки снимается
function cb_clist_unselect_row($clist) {
$clist->set_data('selected_row',-1);
}
// показываем «About Box»
function cb_about_box($menu_item,$window) {
$about_box = &new GtkDialog();
$vbox = $about_box->vbox;
$action_area = $about_box->action_area;
$about_box->set_title('About');
$label = &new GtkLabel("This is the PHP Cookbook PHP-GTK Demo.");
$button = &new GtkButton('OK');
$button->connect('clicked','cb_dialog_destroy',$about_box);
$vbox->pack_start($label);
$action_area->pack_start($button);
$about_box->set_modal(true);
$about_box->set_transient_for($window);
$about_box->show_all();
}
// показываем окно диалога ошибки
function error_dialog($msg,$window) {
$dialog = &new GtkDialog();
$vbox = $dialog->vbox;
$action_area = $dialog->action_area;
$dialog->set_title('Error');
$label = &new GtkLabel("Error: $msg");
$button = &new GtkButton('OK');
$button->connect('clicked','cb_dialog_destroy',$dialog);
$vbox->pack_start($label);
$action_area->pack_start($button);
$dialog->set_modal(true);
$dialog->set_transient_for($window);
$dialog->show_all();
}
// закрываем окно диалога
function cb_dialog_destroy($button,$dialog) {
$dialog->destroy();
}
// выходим из главной программы
function cb_shutdown() { gtk::main_quit(); }.



Оцените статью: (0 голосов)
0 5 0

Статьи из раздела PHP на эту тему:
Анализ аргументов программы
Анализ аргументов программы с помощью getopt
Показ в окне графических элементов управления
Показ в окне нескольких графических элементов управления
Показ меню

Вернуться в раздел: PHP / 20. PHP на стороне клиента