Содержание


Инструменты ОС Linux для разработчиков приложений для ОС Windows. Часть 8. Разработка GUI приложений

Comments

Данный цикл статей, в основном, предназначен для разработчиков драйверов (модулей ядра), обеспечивающих поддержку специфических аппаратных средств или расширяющих набор системных утилит для диагностики и управления. Поэтому, все предыдущие статьи были сфокусированы на использовании языка программирования С, так как сама система Linux (как ядро, так и большая часть GNU утилит) написаны на языке C (правда ядро содержит незначительные включения ассемблерного кода).

Однако и для прикладных программистов ОС Linux предоставляет все возможности, доступные в области разработки ПО. В данной статье мы рассмотрим некоторые инструменты ОС Linux для создания приложений с графическим интерфейсом пользователя.

Создание приложений с графическим интерфейсом пользователя

Создание приложений, взаимодействующих с пользователем посредством графического интерфейса (GUI приложения), относится к самостоятельному классу задач и даже к отдельной области программирования. В подобный список автономных классов задач из области разработки ПО можно, например, выделить:

  • программы, реализующие алгоритмы цифровой обработки сигналов (DSP);
  • приложения для обработки аудио-потоков (пакеты: sox, ogg,.speex и другие);
  • проекты IP-телефонии, реализации SIP протокола и т.д.;

К подобным независимым областям относится и разработка GUI приложений. Кроме собственной специфики в виде доступных инструментов и средств, необходимо учесть ещё одно принципиальное различие — диаметрально противоположное отношение к GUI в операционных системах семейства Windows и в UNIX (и в Linux, как его частный вид):

В ОС Windows каждое приложение относится к GUI-приложениям, так как неотъемлемым атрибутом любого приложения в Win32 API (низкого уровня) является главное окно приложения, и само приложение строится вокруг этого окна. Операционная система регистрирует классы окон и в дальнейшем соотносит с ними конкретные приложения. Обычное приложение, взаимодействующее с пользователем, просто не может существовать без окна, и с этим были связаны первоначальные проблемы с реализацией консольных (терминальных) приложений в Windows.

На платформе UNIX наблюдается противоположная картина, когда первичным является приложение, по умолчанию консольное (текстовое), и вся графическая система не является составной частью операционной системы, а представлена в виде надстройки пользовательского уровня. Чаще всего в качестве такой графической надстройки используется X11 (в реализации Xorg или X11R5), но это не обязательно, так как существуют и другие графические системы, например, Qwindow, и впоследствии Photon в операционной системе QNX, сосуществующие там одновременно с X11.

Показательно в этом смысле то, что вся оригинальная часть реализации X11, т.е. взаимодействие с аппаратурой видеоадаптеров, устройствами ввода и т.д., работает в пространстве пользователя, а не в привилегированном режиме ядра (супервизора). Отдельные реализации (видеосистемы NVIDIA или AMD Radeon) могут быть реализованы в режиме ядра (как модули), но подобные разработки не относятся к X11, и создаются в основном для решения вопросов, связанных с производительностью.

Поэтому из-за данной специфики, разработка GUI-приложений для ОС UNIX (Linux) принципиально отличается, за счёт того что:

  1. GUI-приложения функционируют через промежуточные слои (библиотеки) пользовательского уровня;
  2. Благодаря размещению графической подсистемы на пользовательском уровне, для программистов предлагается широкий спектр альтернативных инструментов (библиотек), практически равнозначных и конкурирующих друг с другом: Xlib, GTK+, Qt, wxWidgets и т.д.
  3. базовый API для работы с X11 предоставляет библиотека Xlib, а все другие фреймворки пользовательского интерфейса используют уже её функционал, как показано на рисунке 1.
  4. разработчик может выбирать уровень, на котором будет располагаться его приложение, и инструменты, которые он предполагает использовать, начиная от Xlib и выше (хотя библиотека Xlib расположена слишком "глубоко" и работа с ней требует выполнения множества рутинных операций).
Рисунок 1. Архитектура GUI-библиотек, присутствующих в ОС Linux
Архитектура GUI-библиотек, присутствующих в ОС Linux
Архитектура GUI-библиотек, присутствующих в ОС Linux

Примеры использования различных GUI-библиотек

В силу сказанного, все GUI-приложения для ОС Linux, независимо от инструментов, использовавшихся для их создания, имеют абсолютно одинаковую структуру. Далее мы сравним код нескольких простейших GUI приложений, разработанных с помощью различных инструментов. Основной целью подобной демонстрации будет знакомство с принципами использования различных библиотек и команд для компиляции и сборки GUI-приложений, чтобы предоставить читателю возможность в дальнейшем создавать собственные GUI приложения. Полный код примеров, представленных в данной статье, можно найти в архивах, представленных в разделе "Материалы" для скачивания" (для каждой библиотеки используется собственный каталог в примерах).

Листинг 1. Создание GUI-приложения средствами Xlib (каталог Xlib):
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <errno.h>
#include <X11/Xlib.h>

extern int errno;

int main( void ) {
   Display *d;
   Window w;
   XEvent e;
   char *msg = "Hello, World!";
   int s;
   // подключиться к X серверу
   if( ( d = XOpenDisplay( getenv( "DISPLAY" ) ) ) == NULL ) {
      printf( "Can't connect X server: %s\n", strerror( errno ) );
      exit( 1 );
   }
   // создать окно
   s = DefaultScreen( d );
   w = XCreateSimpleWindow( d, RootWindow( d, s ), 10, 10, 200, 200, 1,
                            BlackPixel( d, s ), WhitePixel( d, s ) );
   // выбрать события, на которые будет реагировать окно
   XSelectInput( d, w, ExposureMask | KeyPressMask );
   // вывести окно на экран
   XMapWindow( d, w );
   // бесконечный цикл для обработки событий
   while( 1 ) {
      XNextEvent( d, &e );
      if( e.type == Expose ) { // перерисовть окно
         XFillRectangle( d, w, DefaultGC( d, s ), 20, 20, 10, 10 );
         XDrawString( d, w, DefaultGC( d, s ), 50, 50, msg, strlen( msg ) );
      }
      if( e.type == KeyPress ) // при нажатии кнопки – выйти из приложения
         break;
   }
   XCloseDisplay( d ); // закрыть соединение с X сервером
   return 0;
}

Соберём и запустим приложение, как показано ниже:

$ gcc Xlib.c -o Xlib -lX11
$ ./Xlib
Рисунок 2. Простейшее Xlib-приложение.
Простейшее Xlib-приложение.
Листинг 2 Создание GUI-приложения средствами GTK+ (каталог GTK+):
# include <gtk/gtk.h> /* подключаем библиотеку GTK+ */

int main( int argc, char *argv[] ) {
   // объявляем виджеты:
   GtkWidget *label;  // метка
   GtkWidget *window; // главное окно
   gtk_init( &argc, &argv );                        // инициализируем GTK+
   window = gtk_window_new( GTK_WINDOW_TOPLEVEL );  // создаем главное окно
   gtk_window_set_title( GTK_WINDOW( window ),      // устанавливаем заголовок окна
                         "Здравствуй, мир!");
   label = gtk_label_new( "Здравствуй, мир!" );         // создаем метку с текстом
...// помещаем метку в главное окно
   gtk_container_add( GTK_CONTAINER( window ), label );
   // показываем окно вместе с виджетами
   gtk_widget_show_all( window );
   // соединяем сигнал завершения с выходом
   g_signal_connect( G_OBJECT( window ), "destroy",
                     G_CALLBACK( gtk_main_quit ), NULL );
   gtk_main();   // приложение переходит в цикл ожидания
   return 0;
}

Как и в прошлый раз соберём и запустим приложение:

$ gcc gtk.c -o gtk `pkg-config --cflags --libs gtk+-2.0`
$ ./gtk
Рисунок 3. Простейшее GTK+приложение
Простейшее GTK+приложение

Библиотека Qt предполагает написание приложений на языке С++ и имеет богатый набор инструментов, например, для построения сценария сборки приложения. Сначала мы создадим в рабочем каталоге (изначально пустом) файл исходного кода приложения, как показано в листинге 3. Полный код примера можно найти в архиве, каталог Qt в разделе "Материалы для скачивания".

Листинг 3. Пример Qt-приложения (файл index.cc)
#include <qapplication.h>
#include <qdialog.h>

int main( int argc, char** argv ) {
   QApplication app( argc, argv );
   QDialog  startDialog;
   startDialog.setMinimumWidth( 200 );
   startDialog.show();
   return app.exec();
}

А теперь для сборки нашего проекта выполним следующие команды:

$ ls
index.cc
$ qmake -project
$ ls
index.cc  Qt.pro
$ qmake
$ ls
index.cc  Makefile  Qt.pro

Таким способом, из имеющихся файлов с исходным кодом был сгенерирован файл проекта и, затем, сценарий сборки (Makefile). Остаётся выполнить сборку проекта и изучить опции, которые использовались для компиляции и сборки:

$ make
g++ -c -pipe -Wall -W -O2 -g -pipe -Wall -Wp,-D_FORTIFY_SOURCE=2 –fexceptions \
    -fstack-protector --param=ssp-buffer-size=4 -m32 -march=i686 \ 
 -   mtune=atom -fasynchronous-unwind-tables
g++  -o Qt index.o    -L/usr/lib/qt-3.3/lib -lqt-mt -lXext -lX11 -lm
$ ls
index.cc  index.o  Makefile  Qt  Qt.pro
$ ./Qt
Рисунок 4. Пример Qt-приложения
Пример Qt-приложения
Листинг 4. Создание GUI-приложения средствами библиотеки wxWidgets (каталог wxWidgets)
#include <wx/wx.h>
class Simple : public wxFrame {
public:
      Simple( const wxString& title );
};

Simple::Simple( const wxString& title ) :
   wxFrame( NULL, wxID_ANY, title, wxDefaultPosition, wxSize( 250, 150 ) ) {
   Centre();
}

class MyApp : public wxApp {
public:
      virtual bool OnInit();
};

bool MyApp::OnInit() {
   Simple *simple = new Simple( wxT( "Simple" ) );
   simple->Show(true);   // старт цикда обработки событий
  return true;
}

// этот макрос реализует функцию main() в приложениях wxWidgets,
// скрывая подробности главного цикла обработки событий.
IMPLEMENT_APP( MyApp )

Как обычно соберём и запустим приложение:

$ g++ simple.cc `wx-config —cxxflags` `wx-config --libs` -o simple
$ ./simple
Рисунок 5. Пример wx-Widgets приложения
Рисунок 5. Пример wx-Widgets приложения

Библиотека GLUT OpenGL Utility Toolkit, как следует из названия, использует в приложения средства технологии OpenGL, которая требует определённой поддержки со стороны видеооборудования.

Листинг 6. Пример GLUT-приложения (каталог glut)
#include <GL/gl.h>

void Draw( void ) {
   glClear( GL_COLOR_BUFFER_BIT );
   glColor3f( 0.0f, 0.0f, 1.0f );
   glLineWidth( 1 );
   glBegin( GL_LINES );
   glVertex2f( 0, 0.5f );
   glVertex2f( 0, -0.5f );
   glEnd();
   glFlush();
}

int main( int argc, char *argv[] ) {
   glutInit( &argc, argv );
   glutInitWindowSize( 400, 300 );
   glutInitWindowPosition( 100, 100 );
   glutCreateWindow( "GL Demo" );
   glutDisplayFunc( Draw );
   glClearColor( 0, 0, 0, 0 );
   glutMainLoop();
   return 0;
}

Соберём и запустим приложение:

$ gcc glut.c -o glut -lX11 –lglut
$ ./glut
Рисунок 6. Пример GLUT-приложения
Пример GLUT-приложения
Пример GLUT-приложения

Заключение

Хотя все представленные примеры и содержат только базовую функциональность, но они позволяют сравнить поведение различных GUI-библиотек в X11 и могут послужить отправной точкой для разработки более функциональных GUI-приложений. Мы рассмотрели только несколько GUI-технологий, доступных в X11, хотя большинство из них являются кросс-платформенными и могут применяться и в других операционных системах. Все перечисленные технологии и другие, существующие в эко-системе Unix/Linux, взаимно заменимы и даже взаимно дополняемые.

В данной статье мы рассмотрели примеры простых GUI-приложений, но сложные визуальные интерфейсы для таких приложений обычно создаются не путём непосредственного кодирования, а за счёт использования интегрированных сред разработки (IDE) и их "мастеров" (визардов) для визуальной разработки пользовательского интерфейса.


Ресурсы для скачивания


Похожие темы


Комментарии

Войдите или зарегистрируйтесь для того чтобы оставлять комментарии или подписаться на них.

static.content.url=http://www.ibm.com/developerworks/js/artrating/
SITE_ID=40
Zone=Linux, Open source
ArticleID=968493
ArticleTitle=Инструменты ОС Linux для разработчиков приложений для ОС Windows. Часть 8. Разработка GUI приложений
publish-date=04152014