Wiki

Создание кроссплатформенных OpenGL приложений с использованием библиотеки Qt

Статья посвящена работе с библиотекой для создания кроссплатформенных GUI приложений - Qt и методам работы с её классами, составляющим удобную оболочку для OpenGL Известно, что если консольная программа, написанная на ANSI/ISO Standard C++, после перекомпиляции исходного текста будет корректно работать под любой операционной системой, то Windows-приложения с графическим интерфейсом пользователя (GUI), как правило, плохо переносятся. Это связано с привязкой подобных программ к такому инструменту программирования, как использование Windows API (Application Programming Interface). Применение нативных (характерных для данной ОС API) приводит к необходимости заново перепроектировать пользовательский интерфейс в случае переноса приложения на другую систему (Linux, MacOS и т.п.). В то же время имеется большое количество кроссплатформенных библиотек, позволяющих создавать графический интерфейс пользователя на основе собственных API-функций, что делает возможным написание исходного текста приложений, одинаково выглядящих в любой операционной системе. Одним из наиболее удобных инструментов разработки GUI является Qt, поддерживающий большое количество ОС, в том числе такие распространённые как Windows (линейки 9x/Me и NT/2000/XP), Linux, FreeBSD, HP-UX, MacOS, Solaris и многие другие. Qt является самостоятельным инструментом разработки, содержащим средства быстрого проектирования графического интерфейса (Qt Designer), перевода программ на различные языки (Qt Linguist), создания файлов сборки (qmake) и др., однако может выступать и как библиотека в интегрированных средах разработки (например, MS Visual Studio для Windows или KDevelop для Linux). Qt имеет богатую библиотеку собственных удобных в применении классов, значительно облегчающих разработку приложений. В частности, Qt предоставляет разнообразные средства работы с графикой, включая OpenGL. Последняя графическая библиотека, являясь стандартом de-facto при создании дву- и трёхмерных изображений, обладает двумя существенными недостатками: во-первых, она не является объектно-ориентированной и не имеет собственных классов, а во-вторых, требует при переносе разработанных с её помощью программ на другую платформу внесения ряда изменений в исходный код для привязки контекста воспроизведения (rendering context) к оконной системе платформы (Win32, X11, MacOSX). Qt устраняет эти недостатки, предоставляя удобные базовые классы для создания пользовательских виджетов (компонент), работающих с OpenGL, не требующих внесения каких-либо изменений в их исходный код при переносе на другую платформу, что делает библиотеку OpenGL в Qt-представлении абсолютно платформонезависимой. В данной статье мы рассмотрим возможность создания простейшего OpenGL-приложения для Windows и Linux, базирующегося на Qt-классах. Эта программа будет рисовать прямоугольник, окрашенный в различные цвета, подвергающиеся сглаживанию. Для начала нам нужно установить Qt. В большинстве Linux-дистрибутивов Qt уже установлен (на основе его классов разработан такой популярный оконный менеджер, как KDE). Убедится в его наличии можно, введя в консоли команду qmake -v. Для Windows существует как коммерческая версия библиотеки, так и бесплатная для разработки некоммерческих приложений и обучения. Скачать её можно здесь (23,4 Мб): http://slv.nov.net/usr/qt-win-noncommercial-msvc-3.2.1.exe Установка под Windows осуществляется обычно, однако, учитывая, что нам придётся работать с командной строкой, рекомендую осуществить установку в папку Qt, заранее созданную в корневом диске. После этого в папке Qt (пользователи Linux – в домашнем каталоге) создайте папку Projects, а в ней – папку Colours для хранения файлов проекта. Для создания исходных текстов программы можете использовать любой привычный редактор кода (например, KWrite в Linux или UltraEdit в Windows), однако имейте в виду, что для корректного отображения надписей на русском языке в вашей программе её исходный код должен быть сохранён в кодировке Utf-8. Наша программа будет состоять из невидимого объекта класса Qt - QApplication, - отвечающего за обработку сигналов (сообщений) пользователя и системы и главного окна приложения, отвечающего за вывод графической информации, класс которого мы назовём TMainForm и унаследуем от класса QMainWindow. Это окно будет содержать 3 компонента (виджета) – наш (пользовательский) виджет, собственно работающий с OpenGL, класса TOGLWidget, наследующего классу QGLWidget, и две кнопки класса QPushButton. Тем самым, нам нужно создать три файла исходного кода: MainForm.h и MainForm.cpp, содержащие объявление и реализацию наших классов TMainForm и TOGLWidget, а также файл main.cpp, содержащий главную функцию (main) приложения. Последняя реализуется весьма просто: создаётся объект класса QApplication
   int main(int argc, char* argv[])
   {
      QApplication MyProgramme(argc, argv);
 
   }
после чего создаём главное окно и устанавливаем его в качестве главного окна (виджета) приложения:
   TMainForm MainWindow;
   MyProgramme.setMainWidget(&MainWindow);
После этого показываем главное окно приложения (максимизированным) и возвращаем код выполнения программы:
   MainWindow.showMaximized();
   return MyProgramme.exec();
Теперь приступим к проектированию собственно главного окна (TMainForm) на основе собственного виджета TOGLWidget (файл MainForm.h). Как уже упоминалось, он будет унаследован от класса QGLWidget. Кроме того, нам потребуется переопределить три функции-члена последнего:
   class TOGLWidget : public QGLWidget
   {
      Q_OBJECT
   public:
      TOGLWidget(QWidget* pParent=0, const char* psName=0);
 
   protected:
      virtual void initializeGL();
      virtual void resizeGL(int iWidth, int iHeight);
 
      virtual void paintGL();
 
   };
Основой главного окна нашего приложения послужит менеджер вертикальной компоновки, располагающий дочерние виджеты сверху вниз, класса QVBox:
   class TMainForm : public QMainWindow
   {
      Q_OBJECT
   public:
      TMainForm(QWidget* pParent=0, const char* psName="MainForm", WFlags Flags=0); // Конструктор класса.
      QVBox* pCentralWidget; // Центральный виджет окна.
   }; 
Введём в класс TMainForm ещё три члена (виджета) – объект нашего класса TOGLWidget, кнопка, разворачивающие окно во весь экран, и кнопка, завершающая работу программы:
   TOGLWidget* pPaintArea;
   QPushButton* pWindowButton;
   QPushButton* pCloseButton;
Кроме того, объявим обработчики событий (в Qt они называются слоты – SLOTS), отвечающие за отображение надписей на виджетах окна (функция LanguageChange()) и обработку щелчка по кнопке pWindowButton (функция OnWindow()). Для кнопки pCloseButton объявление слота не нужно, т.к. для закрытия окна приложения существует стандартный обработчик – close(). Реализацию объявленных классов опишем в файле MainForm.c. Конструктор класса TOGLWidget не имеет реализации, он просто передаёт указатель виджета-предка (QWidget* pParent) наследуемому классу. Инициализация OpenGL (функция-член класса TOGLWidget initializeGL()) осуществляется заданием цвета очистки буфера изображения:
   void TOGLWidget::initializeGL()
   {
      qglClearColor(black); // Чёрный цвет.
   }
При пустом методе класса TOGLWidget paintGL() это приводит к закрашиванию фона окна в чёрный цвет. Однако в нашем случае мы очищаем буфер изображения и буфер глубины методом glClear(). После этого происходит вызов обычных OpenGL-функций, формирующих собственно изображение (заключены между glBegin() и glEnd()). Теперь можно приступить к реализации класса главного окна приложения. Центральным виджетом окна и родительским классом по отношению к классам всех остальных виджетов будет менеджер вертикальной компоновки:
   pCentralWidget=new QVBox(this, "CentralWidget");
   setCentralWidget(pCentralWidget); // Устанавливается как центральный виджет.
   pPaintArea=new TOGLWidget(pCentralWidget, "PaintArea"); 
 
   // Наш OGL виджет.
   pWindowButton=new QPushButton(pCentralWidget, "WindowButton");
   pCloseButton=new QPushButton(pCentralWidget, "CloseButton");
В методе класса TMainForm LanguageChange() опишем надписи, которые будут отображаться на виджетах главного окна. При этом функция trUtf8() при выполнении приложения будет переводить надписи из кодировки Utf8 в текущую кодировку конкретной операционной системы:
   void TMainForm::LanguageChange()
   {
      setCaption(trUtf8("Цвета")); // Устанавливает заголовок окна.
      pWindowButton->setText(trUtf8("Окно")); // Надпись на 1-й кнопке.
      QToolTip::add(pWindowButton, trUtf8("Отобразить в окне"));
 
      // Подсказка 1-й кнопки.
      pCloseButton->setText(trUtf8("Закрыть")); // Надпись на 2-й кнопке.
      QToolTip::add(pCloseButton, trUtf8("Завершить работу программы"));
 
      // Подсказка 2-й кнопки.
   }
В завершение следует установить связь между событием, возникающим при пользовательском щелчке по кнопке (сигнал – SIGNAL) и соответствующим обработчиком этого события (слот – SLOT). Как уже упоминалось, для кнопки pCloseButton и сигнал, и слот являются стандартными:
   connect(pCloseButton, SIGNAL(clicked()), this, SLOT(close()));
Для кнопки pWindowButton после установления соединения между стандартным сигналом clicked() и нашим слотом OnWindow()
   connect(pWindowButton, SIGNAL(clicked()), this, SLOT(OnWindow()));
релизацию обработчика нужно описать вручную:
   void TMainForm::OnWindow()
   {
      if(TMainForm::isFullScreen()) // Если приложение развёрнуто во весь экран...
      {
         showMaximized(); // ...свернуть в окно.
      }
      else if(TMainForm::isMaximized()) // И наоборот. 
      {
         showFullScreen();
      }
   }
На этом создание нашего OGL-приложения завершено. Приступим к его компиляции. В Linux перейдём в созданный нами каталог проекта: cd /home/your_folder/Projects/Colours, после чего последовательно введём команды:
   qmake -project 
 
   qmake Colours.pro
 
   make
В Windows в командной строке (для WinXP) введём команды:
   cd /d C:QtProjectsColours
 
   qmake -project
 
   qmake Colours.pro
 
   nmake
Nmake – утилита, входящая в состав Visual C++, поэтому на Вашем компьютере должна быть установлена либо 6-я версия этого компилятора, либо Visual Studio.Net. Если же Вы хотите иметь возможность использовать менеджер классов, отладчик и другие инструменты IDE, то команду nmake можно заменить следующей:
   qmake -tp vc Colours.pro
Эта команда создаст файл проекта Visual Studio, в связи с чем Вы сможете оперировать Вашими классами и классами Qt так, как будто они являются классами VC++. Посмотрите откомпилированные приложения в работе и убедитесь, что они одинаково выглядят в Windows и Linux. Полные исходные коды программы, а также откомпилированные программы для Linux и Windows Вы можете скачать здесь: http://crossplatform.ru/uploads/articles/sources/Colours.zip Источник: http://prog-begin.net.ru/