Программирование на .NET в Linux

Часть 3. Оконное приложение на GTK#

"Дружественные" GUI-интерфейсы других операционных систем имеют свои собственные проблемы. Поиски необходимых кнопок подобны игре в Adventure: интерфейсы в этих системах настолько же трудны, насколько любой интерфейс командной строки в Unix, за исключением того, что пользователь теоретически может "найти сокровища" после достаточного исследования. В Unix пользователю необходимо руководство.
Брайан Керниган


В мире Unix опытные пользователи в основном привыкли к CLI-интерфейсам (Command Line Interface). Давно известно, что интерфейс командной строки предлагает большую гибкость, но при этом возлагает большую нагрузку на память. Только это раньше все Unix-пользователи были опытными. Теперь, в основном благодаря Linux, в мир Unix приходит все больше людей, не обладающих необходимым уровнем квалификации в области информатики. А значит, наша задача как программистов — писать приложения так, чтобы их было легко изучить и просто использовать. Конечно, главную роль в "юзабильности" программы играет ее интерфейс. Проектом Mono официально поддерживается библиотека графических интерфейсов Gtk (как первой, так и второй версии). Именно с ней мы сегодня и познакомимся.

Читателю, знакомому с программированием на C# в Windows, не составит труда разобраться в использовании MonoDevelop'а. Создайте новый проект: File -> New Solution/Project -> C# -> Gtk# 2.0 Project. Среда разработки создаст заготовку оконного приложения и автоматически добавит ссылки на необходимые сборки — такие, как gtk-sharp и pango-sharp. Проект будет состоять из трех файлов: AssemblyInfo.cs, Main.cs и MyWindows.cs. Файл AssemblyInfo.cs предназначен для того же, для чего и в MS Visual Studtio 2003/2005: он содержит некоторые параметры сборки: описание, версию, имя автора и т.д. В Main.cs находится код запуска главного окна — точь-в-точь, как это делается в любом другом Gtk- или Qt-приложении. А файл MyWindows.cs содержит реализацию класса MyWindow. Аналогичный код в MS Visual Studio не делится на два файла, а содержится в одном. Обратимся к методу Main. Он состоит всего из трех строк:

public static void Main (string[] args)
{
Application.Init ();
new MyWindow ();
Application.Run ();
}
Есть три статических метода класса Gtk.Application, которые нужны каждому приложению. Первые два показаны в листинге. Метод Init()
инициализирует библиотеку Gtk#, а метод Run() запускает главный цикл обработки сообщений. Третий метод — Quit(), который завершает работу и с библиотекой Gtk#, и с приложением. Код класса MyWindow также ничем не примечателен. Единственное, на что нужно обратить внимание — обработчик события DeleteEvent.

void OnMyWindowDelete (object sender, DeleteEventArgs a)
{
Application.Quit ();
a.RetVal = true;
}

Как видно из листинга, приложение будет завершено, как только окно MyWindow будет закрыто. Теперь, следуя традиции, создадим в окне кнопку с надписью "Hello, World!" — просто чтобы посмотреть, как это работает.

private Button b;
public MyWindow () : base ("MyWindow")
{
b = new Button("Hello, World!");
b.Clicked += new EventHandler(OnButtonClick);
this.Add(b);
this.SetDefaultSize (50, 50);
this.DeleteEvent += new DeleteEventHandler (OnMyWindowDelete);
this.ShowAll ();
}
void OnButtonClick(object o, EventArgs e)
{
System.Console.WriteLine("Hello, World!");
}

Для сборки проекта в MonoDevelop нужно нажать F8, для запуска на выполнение — F5.
Хотя первый пример продемонстрировал, как можно создавать Gtk-приложения при помощи Mono, он абсолютно не показывает всех возможностей библиотеки. А посмотреть есть на что. Начнем с текстового движка Pango. Этот движок предназначен для рендеринга текста на виджетах (элементах UI) и интегрирован в библиотеку Gtk со 2-й версии. Слово "Pango" составлено из двух слов: греческого "Pan", означающего "всеобщий", и японского "Go" — "язык". По сути своей Pango — это набор библиотек, предоставляющих функциональность для правильного расположения и отрисовки локализованного текста. Т.е., если вам захочется писать слева направо или сверху вниз — пожалуйста, задайте всего один-два атрибута текста, и Pango сделает остальную работу за вас. Более того, Pango самостоятельно способен подобрать шрифт и способ оформления текста на основе используемого языка. Пример использования Pango:

Pango.Layout layout;
Gtk.DrawingArea da;
int width = 150;
int height = 50;

public MyWindow () : base ("MyWindow")
{
this.SetDefaultSize (width, height);
this.DeleteEvent += new DeleteEventHandler (OnMyWindowDelete);
da = new Gtk.DrawingArea();
da.ExposeEvent += Expose_Event;
layout = new Pango.Layout(this.PangoContext);
layout.FontDescription = Pango.FontDescription.FromString("Ahafoni CLM Bold 100");

layout.SetMarkup("<span underline=\"single\" size='12000' foreground='#00FF00' background='#FFFFFF' >Hello, World!</span>");

this.Add(da);
this.ShowAll ();
}
void Expose_Event(object obj, ExposeEventArgs args){
da.GdkWindow.DrawLayout (da.Style.TextGC (StateType.Normal), 5, 5, layout);
}

Класс Gtk.DrawingArea предназначен для отрисовки графических примитивов. В нем и будет выводиться текст, отрендеренный в экземпляре класса Pango.Layout. К слову, Pango.Layout — класс, предназначенный для форматирования целого абзаца текста за раз. После этих пояснений остальной код становится достаточно понятным. Метод void Expose_Event() вызывается при перерисовке контекста устройства — в нем отрисовывается абзац текста из Pango.Layout. Свойство Pango.Layout. FontDescription содержит краткое название шрифта. Самый важный для нас метод Pango.Layout'а — SetMarkup(). Он устанавливает текст и его атрибуты при помощи специального формата разметки, основанного на Xml. Корневой тег документа, размеченного для Pango, называется <markup>. Впрочем, его можно опустить. Наиболее общий тег, позволяющий устанавливать атрибуты текста — <span>.

Он содержит ряд параметров — таких, как цвет символов или фона, размер и прочее. Основные атрибуты тега <span> я привел в конце статьи, т.к. их описания нет в MonoDoc. Есть также дополнительные теги — так называемые convenience tags, призванные упростить разметку документа. Они берут на себя задачу какого-нибудь отдельного атрибута тега <span>. Например, тег <b> сделает шрифт "жирным". В приведенном выше примере класс Pango.Layout используется для рисования в Gtk.DrawingArea. Но выводить текст при помощи Pango можно на любом виджете Gtk. Алгоритм следующий: нужно создать Pango.Layout при помощи свойства виджета Gtk.Widget.PangoContext, установить размеченный текст методом SetMarkup(), затем в обработчике события ExposeEvent окна отрисовать соответствующий Pango. Пример:

Button b;
Pango.Layout l;
...
b = new Button();
l = new Pango.Layout(b.PangoContext);
l.SetMarkup("<u>Hello, World!</u>");
...
void OnExposed (object o, ExposeEventArgs args)
{
this.GdkWindow.DrawLayout (this.Style.TextGC (StateType.Normal), 1, 1, l);
}
Еще более простой способ применить Pango — использовать класс Gtk.Label, который применяется для отрисовки надписей на других виджетах — таких, как кнопки и элементы меню. Строку с разметкой можно сразу передавать конструктору Gtk.Label и установить его свойство UseMarkup в true — вот и все!
Button b;
Label lb;
lb = new Label("<span weight=\"bold\">123</span>");
lb.UseMarkup = true;
b = new Button(lb);

Приложение 1. Основные атрибуты тега <span>

font_desc — строка описания шрифта — например, "Sans Italic 12". Прочие атрибуты затирают этот параметр, так что, если указать size='10000', то размер шрифта будет уже не 12, а 10.
size — размер шрифта — указывается в 1024-х долях пункта. Возможно использование предопределенных размеров — таких, как 'small', 'medium', 'large' и пр.
style — стиль. Принимает одно из трех значений: normal', 'oblique', 'italic'.
weight — "вес" шрифта. Возможные значения: 'ultralight', 'light', 'normal', 'bold', 'ultrabold', 'heavy'. Значение weight можно указать также и в численном виде.
stretch — величина расстояния между символами. Возможные значения: 'ultracondensed', 'extracondensed', 'condensed', 'semicondensed', 'normal', 'semiexpanded', 'expanded', 'extraexpanded', 'ultraexpanded'.
foreground — цвет шрифта.
backround — цвет фона.
underline — подчеркивание текста. Возможные значения:'single', 'double', 'low', 'none'.
strikethrough — зачеркивание текста. Принимает только 'true' или 'false'.
lang — код языка.

Приложение 2. Convenience tags

b — жирный шрифт.
big — увеличивает шрифт. Эквивалентен атрибуту <span size="larger">.
i — курсив.
s — зачеркивание.
small-- уменьшает шрифт. Эквивалентен атрибуту <span size="smaller">.
tt — моноширинный шрифт.
u — подчеркивание.

Дмитрий Бушенко, nop@list.ru


Компьютерная газета. Статья была опубликована в номере 05 за 2006 год в рубрике программирование

©1997-2024 Компьютерная газета