Рейтинг@Mail.ru
[Войти] [Зарегистрироваться]

Наши друзья и партнеры

UnixForum
Беспроводные выключатели nooLite купить дешевый 
компьютер родом из Dhgate.com

Lines Club

Ищем достойных соперников.

Библиотека сайта или "Мой Linux Documentation Project"

Создание графических приложений

Цилюрик О.И.

Настоящая статья является дополнением к книге «Инструменты Linux для Windows-программистов». Это не описание как делать GUI приложения в Linux, это описание того, как ПРИСТУПИТЬ к созданию графических приложений в Linux, и, хотелось бы надеяться что это прозвучит - чем принципиально программирование графики в Linux отличается от того же занятия в Windows. Главным требованием здесь была простота. Сделав простейший шаблон GUI прложения, дальше двигаться уже гораздо проще. Кроме того, все эти простейшие приёмы программирования показаны сравнительно: на основе основных графических технологий (библиотек), используемых в UNIX.

Все примеры к тексту вы можете скачать в виде общего архива.


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

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

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

  • В Windows каждое приложение является принципиально GUI, неотъемлемым атрибутом любого приложения в Win32 API (низкого уровня) является главное окно приложения, уже само приложение «вяжется» вокруг его главного окна. Операционная система регистрирует классы окон и уже далее к ним соотносит конкретные приложения. Не может существовать приложения (взаимодействующего с пользователем, не системные службы) без окна, с этим были связаны и первоначальные сложности Windows в реализации консольных (терминальных) приложений.
  • в UNIX картина принципиально обратная: первичным является приложение, которое, по умолчанию, является консольным, текстовым, вся графическая система не является составной частью операционной системы, а является надстройкой пользовательского уровня. Чаще всего такой графической надстройкой является X11 (в реализации Xorg или X11R5), но и это не обязательно: практиковались и другие графические системы, хороший пример тому графические системы Qwindow, а затем Photon в операционной системе QNX, сосуществующие там одновременно с X11.
  • Показательно в этом смысле то, что вся оригинальная часть реализации X11 работает в пространстве пользователя, не в привилегированном режиме ядра (супервизора): работа с аппаратурой видеоадаптеров, устройствами ввода и другое. Отдельные реализации (видеосистемы NVIDIA или ATI Radeon) могут быть реализованы в режиме ядра (модули), но это а) сторонние относительно X11 разработки, и б) решение вопросов только производительности.

Из-за обозначенной специфики, разработка GUI приложений в UNIX (Linux) принципиально отличается:

  • вся работа GUI приложений ведётся через промежуточные слои (библиотеки) пользовательского уровня;
  • из-за того, что это ординарный пользовательский уровень, для разработчика предлагается широкий спектр альтернативных инструментов (библиотек), практически равнозначных, и конкурирующих друг с другом: Xlib, GTK+, Qt, wxWorks и многие другие.
  • базовый API работы с X11 предоставляет Xlib, все другие используют уже её функционал, как это показано на рисунке.

  • разработчик имеет возможность широкого выбора тех уровня и инструментов, которые он предполагает использовать, начиная от Xlib и выше (хотя уровень Xlib и слишком низок и работа с ним громоздкая).

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

Средства Xlib (архив Xlib.tgz):

Xlib.c :

#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; 

   if( ( d = XOpenDisplay( getenv("DISPLAY" ) ) ) == NULL ) {  // Соединиться с X сервером, 
      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


Средства GTK+ (архив GTK+.tgz):

gtk.c :

# 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


Средства Qt (архив Qt.tgz):

Средства 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


Средства wxWidgets (архив wxWidgets.tgz):

simple.cc :

#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; 
}

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

Сборка приложения:

$ g++ simple.cc `wx-config —cxxflags` `wx-config --libs` -o simple

...

Выполнение приложения:

$ ./simple


Средства GLUT (архив glut.tgz):

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

glut.c :

#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


То, что показано выше, это фактически не приложения, а скелеты приложений, но они позволяют: а) сравнить подобие всех GUI технологий в X11, и б) быть отправной точкой для сборки более содержательных GUI приложений. Показано только несколько GUI технологий, применяемых в X11 (большинство из них являются кросс-платформенными, и применимы в большинстве существующих операционных систем). Каждая из этих технологий, а названы только немногие из значительно большего числа, присутствующих в UNIX, могут быть полной альтернативой любой другой из этого же ряда, они взаимно заменимы, и даже взаимно дополняемые.

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


Эта статья еще не оценивалась
Вы сможете оценить статью и оставить комментарий, если войдете или зарегистрируетесь.
Только зарегистрированные пользователи могут оценивать и комментировать статьи.

Комментарии отсутствуют