Журнал LinuxFormat - перейти на главную

LXF73:Gambas

Материал из Linuxformat
Перейти к: навигация, поиск

Содержание

Построение приложения

часть 3 Эдисон ошибался. Забудьте об упорном труде: с точки зрения доктора Марка Александра Бэйна (Dr Mark alexander Bain), гений на 100 % состоит из перекладывания работы на других. Так что садитесь, складывайте ноги на стол и позвольте Gambas сделать за вас всю работу…

Я, вероятно, уже упоминал об этом, но повторюсь: все хорошие программисты — ленивы. Это не значит, что они ничего не делают, нет, но они используют свой мозг, а не пальцы. Мы начали постигать это в прошлом месяце, когда рассматривали модули и классы. Сегодня мы продолжим превращение в идеального ленивого программиста, рассмотрев, как можно заставить Gambas сделать нечто, что будет хорошо выглядеть, с минимальными затратами.

Первое, что надо запомнить: обычно кто-то уже делал то, что вы пытаетесь сделать сейчас. Особенно это верно, если вы имеете дело с Linux. Предположим, например, что вы ищите владельца web-сайта. Это очень просто — откройте командную строку и наберите whois linuxformat.ru. Вы увидите большой список, содержащий море информации вроде названия домена, имени того кто его регистрировал, его физический адрес, дату регистрации и IP-адрес серверов Linux Format.

как сделать то же самое при помощи gambas?

если вы начали отвечать, что нужно поискать в доменных базах данных или начать поиск NIC-записи — остановитесь! Вероятно, вы не слушали того, что я вам говорил. если же вы ответили «надо схитрить» — купите себе пива, вы уже думаете как хороший программист. Главный вопрос: «как именно можно схитрить?».

Ответ: используйте оператор Gambas ShELL, чтобы заставить Linux сделать за вас всю тяжелую работу и использовать её результат в своей программе. Итак, давайте начнём с создания формы, на которой содержатся поле ввода, многострочное поле ввода и пара кнопок. Не забывайте, что имена объектов имеют значение. Сейчас я назвал поле ввода txtUrl, многострочное поле ввода txtResult и одну из кнопок btnWhois. код, обрабатывающий нажатие этой кнопки, таков:

PUBLIC SUB btnWhois_Click()
DIM filename AS String
filename = "/tmp/whois.tmp"
IF (txtUrl.Text) THEN
SHELL "whois " & txtUrl.Text & ">" & filename WAIT
txtResult.Text = File.Load(filename)
ELSE
txtResult.Text = ""
END IF
END

Он очень простой. Сначала мы определяем имя файла (/tmp/whois/tmp), а затем запускаем команду оболочки, которая берёт адрес из txtUrl и выполняет для него whois, а затем сохраняет результат в текстовом файле. Так что если вы ввели linuxformat.ru, то в результате будет выполнена следующая команда:

whois linuxformat.ru > /tmp/whois.tmp

Затем содержимое файла /tmp/whois.tmp помещается в многострочное поле ввода при помощи команды File.Load. Оператор IF просто гарантирует, что если вы оставите поле ввода пустым, то ошибки не произойдёт. Такой стиль кодирования не позволяет использовать ошибочные данные, что предотвращает падение программы.

другой способ состоит в обработке возникающих ошибок:

PUBLIC SUB btnWhois_Click()
DIM filename AS String
filename = "/tmp/whois.tmp"
TRY SHELL "whois " & txtUrl.Text & ">" & filename WAIT
IF ERROR THEN
txtResult.Text = ""
END IF
txtResult.Text = File.Load(filename)
END

Тут команда whois выполняется вне зависимости от того, что вы ввели, но результат обрабатывается по-разному в зависимости от того, была ошибка или нет. какой из методов лучше использовать — это ваш выбор, плюсы и минусы есть у обоих вариантов. Первый влечет необходимость обдумать и предотвратить все возможные ошибки, но зато даёт уверенность, что указание некорректных данных просто невозможно. Второй гарантирует, что все ошибки будут обработаны, но от программиста требуется позаботиться об удачном сообщении для пользователя. Но какой бы вы способ ни выбрали — важно, чтобы он был, и чтобы программа не рушилась.

Вторая кнопка нужна для закрытия формы, каждая форма нуждается в такой. Итак, если вы назвали кнопку btnClose, то код будет следующим:

PUBLIC SUB btnClose_Click()
ME.Close
END

Нужно упомянуть о значении параметра WAIT оператора ShELL. если вы использовали WAIT, то программа будет ожидать завершения команды перед тем, как продолжить работу. если же WAITE не был использован, то команда оболочки будет работать в фоновом режиме, одновременно с вашим приложением. Фоновый режим полезен, если вы хотите запустить команду оболочки и оставить её в работающем состоянии. как всегда, лучше всего рассмотреть это на примере из реальной жизни.


Представьте, что вам надо создать приложение с графическим интерфейсом пользователя, которое отслеживает сетевой трафик. Практически это значит, что вы хотите читать заголовки всех пакетов данных, путешествующих по вашей сети. Я надеюсь, что теперь вы точно не спросите «как мне это сделать?». Вместо этого вы зададите вопрос «Существует ли приложение Linux, которое уже делает всё, что нужно?». В нашем случае ответ: tcpdump.

как правило, вы запускаете tcpdump и наблюдаете вывод в консольном окне. Сделаем то же самое при помощи Gambas. как всегда, нам потребуется форма, в этот раз — с многострочным полем ввода (txtResult) и двумя кнопками (назовём их btnUpdate и btnClose).

добавим немножко кода

PUBLIC SUB tcpdump_update()
DIM command AS String
command = "if [ ! \"$(ps -ef | grep /usr/sbin/tcpdump | grep -v grep)\" ];
then" &
" sudo /usr/sbin/tcpdump > /tmp/bainm_tcpdump.tmp;" &
" fi"
SHELL command
txtResult.Text = File.Load("/tmp/bainm_tcpdump.tmp")
END
PUBLIC SUB btnUpdate_Click()
tcpdump_update
END

В этом примере команда, которая будет запущена в командной строке Linux, хранится в переменной command и выглядит следующим образом:

if [ ! "$(ps -ef | grep /usr/sbin/tcpdump | grep -v grep)" ]
then
sudo /usr/sbin/tcpdump > /tmp/bainm_tcpdump.tmp
fi

Вы спросите, почему бы мне просто не запустить

sudo /usr/sbin/tcpdump > /tmp/bainm_tcpdump.tmp

Ответ: потому, что команда запускается при каждом нажатии на кнопку. Так что в этом случае окажется запущено множество версий tcpdump. Мой скрипт выполняет проверку, запущено ли уже это приложение, перед тем как пытаться активировать его снова. Вы также можете спросить, что значит код grep -v grep. его задача проста — он удаляет ID дополнительных процессов, запущенных самим grep.

надоело нажимать на кнопку?

Наше приложение работает точно так, как заказывали — запускает tcpdump и показывает его вывод, но вот только пользователь должен всё время нажимать на кнопку, чтобы видеть результат. Мы можем автоматизировать этот процесс, добавив в программу таймер. Выберите таймер (его иконка похожа на часы) из панели инструментов и нарисуйте на своей форме. Не важно, где именно, поскольку таймер всё равно не отображается, когда программа запущена. Не забывайте сменить имя таймера на нечто полезное (я назвал его tcpdumpTimer). если дважды щелкните на этом объекте, Gambas откроет окно кода, и вы увидите:

PUBLIC SUB tcpdumpTimer_Timer()
END

Отредактируйте его следующим образом:

PUBLIC SUB tcpdumpTimer_Timer()
tcpdump_update
END

Если вы сейчас запустите программу, ничего не изменится, так как таймер по умолчанию отключен. Д ля того, чтобы его включить, перейдите к окну свойств и измените значение свойства Enable c False на True. Обратите внимание на параметр Delay. Это время в миллисекундах между запусками процедуры таймера. Задайте его равным 5000 (пять секунд), это позволит вам постоянно видеть изменения, но не перегружать процессор. Вы даже можете удалить кнопку btnUpdate, если хотите.

Уходя, гасите всех. Или, все же, свет?

Если вы закроете приложение Gambas и наберёте в консоли следующую команду,

ps -ef|grep tcpdump

то вероятно увидите в результате нечто вроде этого:

root 1443 1437 0 15:37 ? 00:00:00 /usr/sbin/tcpdump

Это произошло потому, что наше приложение запустило tcpdump и оставило его работать в фоновом режиме. Б ыло бы правильнее выключать его после того, как мы закончили.

Это можно сделать в процедуре Form_Close:

PUBLIC SUB Form_Close()
DIM command AS String
DIM filename AS String
DIM tmp_process_id AS String
filename = "/tmp/bainm_tcpdump_process.tmp"
command =
"ps -ef | grep /usr/sbin/tcpdump|grep -v grep" &
"| awk '{print $2}' > " & filename
SHELL command WAIT
tmp_process_id = file.Load(filename)
SHELL "sudo kill -9 " & tmp_process_id WAIT
END

В этой подпрограмме выполняются два SHELL-оператора. Первый определяет ID процесса tcpdump. Второй убивает процесс. К расота этой технологии в том, что вы можете использовать любые команды Linux. Например, вы можете создать графическую оболочку для программы top, используя таймер и запуская top -n1 > /tmp/top.tmp для выполнения одной итерации, читая затем результаты при помощи file.load.

Рассмотрев некоторые вещи, которые Linux может сделать для нас, вернёмся к встроенным возможностям Gambas.

Меню Gambas

До сих пор мы использовали кнопки для того, чтобы выполнить любые действия с нашей формой. Это работает хорошо, но приводит к загромождению экрана и вызывает проблемы корректной модификации расположения кнопок при изменении размера формы. Д ля решения этих проблем существуют меню Gambas.

Откройте форму в режиме дизайнера, щелкните на ней правой кнопкой и выберите Menu Editor (или просто наберите Ctrl+E). Теперь вы можете построить структуру меню вашего приложения, добавляя в него элементы. К ак всегда, не забывайте давать им осмысленные имена вместо Menu1, Menu2 и так далее. Д ля создания подменю «сдвигайте» нужные элементы. К огда вы закончите и закроете редактор, новое меню отобразится на форме.

Теперь, когда главное меню находится на своем месте, надо придать ему немного функциональности. Д ля начала добавим пункт для закрытия формы. Предположим, вы создали меню с названием Close и именем mnuClose. Тогда его код будет выглядеть следующим образом:

PUBLIC SUB mnuClose_Click()
ME.Close
END

Итак, мы получили чистую, красивую, профессионально выглядящую форму, которая действительно выполняет некоторые довольно сложные задачи (или как минимум управляет процессами, которые делают всё грязную работу). Вы увидели, как все Linux и Unix программисты, работавшие до нас, помогают нам хорошо жить и выглядеть. Посмотрим теперь, как разработчики Gambas могут нам помочь стать настоящими ленивыми программистами.

Компоненты Gambas

Немного раньше, в LXF71, вы видели, как полезны могут быть компоненты Gambas, и как легко с их помощью получить доступ к базе данных. Я хочу напомнить, что для использования компонентов вы должны для начала подключить их, открыв окно Project Properties (в окне проекта щелкните на слове Project, за которым идёт Properties), и перейдя на вкладку Components. Вы увидите список всех компонентов, доступных для вас. Чтобы увидеть, как полезны они могут быть, давайте напишем свой собственный web-браузер! Отметьте компонент gb.qt.kde.html. К огда вы вернётесь обратно, то в панели инструментов обнаружите новую вкладку KDE. Щ елкнув по ней, вы увидите новые объекты, которые теперь можно использовать на любой форме.

Создайте новую форму (с названием frmWebBrowser) и добавьте на нее поле ввода (txtUrl), кнопку (btnGo) и объект web-браузер (webBrowser). Вам так же понадобится создать или кнопку [Close], или пункт меню для закрытия формы. К ак только закончите, напишите следующий код:

PUBLIC SUB btnGo_Click()
IF (txtUrl.text) THEN
webBrowser.Path = "http://" & txtUrl.Text
END IF
END

Если вы запустите получившееся приложение, то увидите, что создали работающий (хотя и очень простой) интернет-браузер.

Мы можем расширить его функциональность с помощью других компонентов Gambas. Включите gb.net (компонент для работы с сетью) и добавьте текстовую метку txtIP на форму. К огда закончите, перепишите ваш код, чтобы он выглядел примерно так:

PRIVATE dns AS DnsClient
PUBLIC SUB btnGo_Click()
IF (txtUrl.text) THEN
webBrowser.Path = "http://" & txtUrl.Text
END IF
txtIp.Text=""
dns.HostName = txtUrl.text
dns.GetHostIP
txtIp.Text = dns.HostIP
END
PUBLIC SUB Form_Open()
dns = NEW DnsClient
END

Запустив приложение на этот раз, вы увидите что кроме web-сайта отображается его IP-адрес. Очень важно, что вам не надо знать, каким образом работает тот или иной компонент. достаточно уметь использовать его.

сделаем web-браузер богаче

Мы управились с созданием простого web-браузера, но цена ему - грош. Он стал чуть-чуть интереснее после добавления IP-адреса сервера, на котором находится та или иная страница. а теперь мы можем сделать простой редактор HTML. его принцип работы будет немного отличаться от работы браузера — вместо простого просмотра страницы мы скачаем её, просмотрим и отредактируем текст, а потом загрузим обратно на сервер. конечно, мы используем компоненты Gambas, чтобы они сделали за нас всю грязную работу.

Создайте новую форму (я назвал её frmHtmlEditor) и сделайте её запускаемым классом или измените ваш модуль, чтобы он открывал именно её. Не забудьте добавить кнопку или меню для закрытия формы. Поскольку мы собираемся делать три совершенно разные вещи, давайте добавим из панели инструментов область вкладок (tab strip) и назовём её tbsEditor, чтобы явно разделить три различных операции. Вы увидите, что по умолчанию присутствует только одна вкладка (Tab 0), используйте окно свойств, чтобы это исправить (измените параметр count). а теперь щелкните на каждой вкладке по отдельности, чтобы изменить их заголовки на что-то полезное (например, Viewer, Editor и Upload).

Вкладка Viewer очень похожа на web-браузер, который мы уже делали, но код слегка отличается. Создайте объекты txtUrl, btnGo и webBrowser (не забудьте подключить компонент gb.qt.kde.html). кроме того, вам понадобится компонент gb.net.curl, чтобы пользоваться протоколами HTTP и FTP. код для просмотра страницы таков:

PRIVATE http AS HttpClient
PRIVATE htmlfile AS String
PUBLIC SUB btnGo_Click()
http.URL = "http://" & txtUrl.Text
http.Get(htmlfile)
loadFile
END
PRIVATE SUB loadFile()
webBrowser.Path = "file:///" & htmlfile
END
PUBLIC SUB Form_Open()
http = NEW HttpClient
htmlfile = "/tmp/test.html"
END

Обратите внимание, мы сначала скачиваем страницу и только потом отдаём ей браузеру для отображения.

На вкладке Editor создайте многострочное поле ввода txtHtml и кнопку btnSave. Затем добавьте следующий код:

PUBLIC SUB tbsEditor_Click()
SELECT CASE tbsEditor.Text
CASE "Viewer"
loadFile
CASE "Editor"
txtHtml.Text = File.Load(htmlfile)
END SELECT
END
PUBLIC SUB btnSave_Click()
file.Save(htmlfile,txtHtml.text)
END

Нам осталось модифицировать вкладку Upload, добавив к ней три поля ввода (txtTarget, txtUsername и txtPassword) и кнопку btnUpload. Нам понадобится глобальный параметр

PRIVATE ftp AS FtpClient

и его инициализация в процедуре form_open:

ftp = NEW FtpClient

В конце напишем процедуру для загрузки файла на сервер

PUBLIC SUB btnUpload_Click()
ftp.URL = txtTarget.Text
ftp.User = txtUsername.Text
ftp.Password = txtPassword.Text
ftp.Put(htmlfile)
END

конечно, это очень простой редактор, в нём нет никаких проверок или подсветки синтаксиса. Вы также обнаружите, что это приложение может загружать на сервер только один файл (подумайте об этом на досуге). Однако оно является прекрасной демонстрацией того, как много и как быстро вы можете сделать, используя компоненты Gambas.

Персональные инструменты
купить
подписаться
Яндекс.Метрика