Программирование в Linux. Часть третья. Лицом к пользователю

В последние годы все чаще выходят новые дистрибутивы Linux, которые гордо заявляют, что потеснят Windows с домашнего компьютера. Несколько лет назад это были единичные случаи, и выглядели они просто нелепо (помнит еще кто-нибудь жутковатого бастарда Lindows 1.0?). Но когда мне в руки попал уже очередной дистрибутив, о котором я прочел, что разработан он специально для простых пользователей... Тогда-то я, как чукча из анекдота, поднял палец вверх и сказал: "Тенденция, однако!"

Сегодня на наших глазах свершается новая веха в истории Unix. По своему значению она важна, наверное, настолько же, насколько важным было создание движения OpenSource. Unix всегда была средой, дружелюбной к профессионалу, развивающей абстрактное мышление, способствующей умственному и в конечном счете культурному развитию. Пришло время, когда Unix становится дружелюбной и к простому пользователю. Популяризация Linux уже идет полным ходом и сулит немалую выгоду всему Linux-сообществу. Логичным шагом продвижения Linux в народ стал повсеместный переход от консоли и текстовых команд к графическим пользовательским интерфейсам. Графическая подсистема Linux сильно отличается от аналогичной в MS Windows. Главное отличие — в том, что она выполняется как пользовательский процесс, а в Windows она встроена в ядро (к слову: графика в Windows — самая оттестированная ее часть, и поэтому никогда не "падает"). И в Unix- и Unix-like-системах теперь не одна, а несколько альтернативных графических подсистем. Самая распространенная из них — XFree86 (а также ее клон x.org) — свободная реализация стандарта X11R6.4. Графическая подсистема Linux предоставляет самый примитивный набор операций: интерфейс взаимодействия с железом. То есть это своеобразный GDI, который позволяет получить ввод от мыши и клавиатуры, умеет рисовать графические примитивы и текст. Поэтому поверху графического сервера XFree86 всегда используются оконные менеджеры, которые и доводят до ума графическую подсистему: KDE, Gnome, Sawfish, IceWM, FluxBox, WindowsMaker и т.д. Каждый из них довольно своеобразен и в сравнении с MS Windows зачастую имеет больше возможностей. Кроме того, они сильно отличаются и друг от друга. Самая дружелюбная к пользователю, а потому и распространенная оболочка — KDE. Она разрабатывается на основе мощной технологии компонентов — KParts, чем-то напоминающей Microsoft COM, а ее графические элементы написаны с применением библиотеки Qt от норвежской компании Trolltech. Давайте рассмотрим эту библиотеку подробнее.

Поскольку статья рассчитана на программистов, мигрирующих с Windows в Linux, то в рассказе о Qt стоит упомянуть библиотеки компонентов MFC и Windows Forms как самые распространенные в Windows. Сравнивая Qt и MFC, трудно удержаться от злорадства: MFC сплошь и рядом кажется пережитком прошлого, жалким наследием Windows 3.11, от которого Microsoft решила наконец избавиться. MFC устроена в основном как обертка для Windows API и имеет мало общего с объектноориентированным дизайном. В различных местах программы на MFC для вызова метода объекта нужно снабдить его доброй дюжиной параметров, из которых нужен всего один, или же приходится вызывать функции с устаревшими параметрами. Структура классов MFC продумана крайне неряшливо. Например, при создании диалогов нужно ожидать возврата OnInitDialog(), объектов-видов — OnInitialUpdate(); при создании графических объектов, кроме конструктора, зачем-то нужен еще и метод Create(). По количеству функционала классы MFC уступают даже Borland OWL и от версии к версии практически не претерпевали ни важных изменений, ни существенных дополнений. Напротив, Qt полностью объектно ориентирована и очень хорошо продумана. Классы Qt имеют согласованное наименование, наследование и организацию. Архитектура библиотеки построена на шаблонах проектирования и реализована на языке C++. Там, где возможностей языка было недостаточно, Trolltech внесла небольшие дополнительные конструкции, которые перед компиляцией обрабатываются препроцессором moc. Если сравнивать Qt и Windows Forms .NET, то здесь выделить лидера сложнее. По дизайну Windows Forms не менее хороша, чем Qt, и активно использует новые веяния объектноориентированного подхода — свойства, делегаты и метаобъектную систему. Единственным минусом Windows Forms является то, что она работает только на платформе .NET, а в .Mono реализована не полностью. Что касается Qt, она также включает в себя перечисленные механизмы, зато работает как под традиционными платформами (Unix, Win32, Mac OS), так и под .NET. По количеству функционала, на мой взгляд, они примерно одинаковы. Наиболее распространенная сегодня версия библиотеки — Qt3. На ее основе построен оконный менеджер KDE3 и огромное количество софта (проверьте сами: сайт Однако месяц назад уже вышла новая версия QT — 4.0.0, и, значит, хочешь — не хочешь, а придется начинать осваивать новинку. Сейчас я покажу, как сделать kickstart в изучении Qt 4.0, а затем расскажу о ее основных отличиях от предыдущей эпохальной версии — 3.2.

Во-первых, Qt4 нужно скачать, т.к. в дистрибутивах он еще не появился. Сделать это можно на сайте Trolltech: сайт Там в секции Download найдете файл qt-x11-opensource-desktop-4.0.0.tar.bz2 (весит он 15 Мб). Затем его нужно распаковать и установить:

$tar -xf qt-x11-opensource-desktop-4.0.0.tar.bz2
$cd qt-x11-opensource-desktop-4.0.0/
$./configure
$make
$su -c "make install"

Запустив команду make, оставляем компьютер наедине с самим собой и уходим молиться, чтобы во время компиляции неожиданно не обнаружились какие- нибудь недостатки системы. Молиться придется долго — больше часа, а если у вас не слишком мощный компьютер, то с легкостью успеете выучить наизусть весь Катехизис. По умолчанию каталог, в который Qt4 себя установит, — /usr/local/Trolltech/Qt-4.0.0, поэтому, чтобы можно было пользоваться именно этой, 4-й, версией Qt при сборке программ, нужно, чтобы в переменных окружения был прописан путь к этому каталогу. Я прописал его в файле /home/dim/.profile вот таким образом:

export PATH=$PATH:/usr/local/Trolltech/Qt-4.0.0:
/usr/local/Trolltech/Qt-4.0.0/bin:/usr/local/Trolltech/Qt-4.0.0/include:/usr/local/Trolltech/Qt- 4.0.0/lib

Не забудьте залогиниться в систему заново, чтобы настройки вступили в силу. Если вы все сделали правильно, Qt4 готова к работе. Давайте проверим это: в ответ на команду "qmake -v" должно появиться сообщение, что используется именно 4-я версия Qt. Прежде чем приступить к работе, давайте посмотрим, на что способна Qt4, и запустим демонстрацию возможностей:

$qtdemo

Даже сама оболочка для демонстрации достойна всяческих похвал, но это еще цветочки. Выберите хотя бы меню Demonstrations -> Vector Deformation -> Launch и посмотрите, как там все художественно оформлено: элементы управления полупрозрачные и очень красиво подсвечиваются; форма элементов какая угодно, только не перпендикулярно-параллельная; по полю рисования "плавает" стеклянный шарик, демонстрирующий еще целый набор спецэффектов нового графического движка Qt4 — Arthur. Специально не привожу для примера скриншот, потому что это нужно увидеть собственными глазами, и только в действии. Правда, все эти элементы управления разработаны специально для демонстрации, а обычный стиль компонентов Qt4 куда более привычен. Теперь самое время и самим попробовать создать что-нибудь при помощи Qt4. Давайте запустим программу designer, поставляющуюся вместе с Qt4, которая поможет нам создавать пользовательский интерфейс в режиме WYSIWIG.

Выберите File -> New Form и создайте новую форму. Как только форма появится, дальнейшая разработка интерфейса станет привычной и не потребует дополнительных объяснений. Вволю поизгалявшись над несчастным окошком, тут же захочется скомпилировать приложение и посмотреть, как оно работает. Вот это уже совсем не так просто. Если дизайнер для Qt3 еще поддерживал редактирование кода и позволял создать полноценный проект только собственными средствами, то в Qt4 такой возможности уже нет. Поэтому для начала запаситесь каким-нибудь текстовым редактором и валерьянкой: все будем делать самостоятельно. Сначала нужно создать файл проекта — назовем его "src.pro". Сохраняем созданную в дизайнере форму с именем "testform.ui" в каталог проекта и одновременно добавляем в src.pro строчку: "FORMS = testform.ui". Если вы посмотрите, что за файл создал дизайнер, то сразу поймете: самое интересное еще впереди, ибо testform.ui — это только описание будущей формы в формате xml. Класс формы по этому описанию будет создан только во время сборки проекта и на этапе кодирования еще недоступен. Заголовочный файл, в котором будет находиться описание класса — "ui_testform.h". Откройте еще раз testform.ui и найдите строчку (она будет в самом начале файла) "<widget class="QDialog" name="Dialog" >". Как видите, здесь задается имя будущего класса, его можно изменить даже из дизайнера. Так вот, класс будет называться Ui_Dialog. Если у вас уже есть опыт написания графических пользовательских интерфейсов, то следующий шаг, который вы по привычке захотите сделать — создать класс, наследующий от Ui_Dialog. В Qt4 другой подход: создать нужно класс, наследующий от обычного QDialog, а Ui_Dialog — класс вообще невизуальный, его задача — только настроить интерфейс. Вот пример файла myform.h:

#include "ui_testform.h"
class MyForm: public QDialog
{
public:
MyForm()
{
ui.setupUi(this);
}
private:
Ui_Dialog ui;
};

В файл src.pro, соответственно, нужно добавить строчку "HEADERS = myform.h". Осталось последнее — написать функцию main и запустить из нее нашу форму. Вот пример файла main.cpp:

#include "myform.h"
#include <QApplication>
int main(int argc,char **argv)
{
QApplication app(argc,argv);
MyForm *form = new MyForm();
form->show();
return app.exec();
}
В файл src.pro добавляем строчку "SOURCES = main.cpp".

Все, проект готов к сборке. Для этого запускаем команду "qmake src.pro", затем — "make" и любуемся обилием созданных во время сборки файлов. Наш запускаемый бинарник будет называться "src". Вместе с Qt4 поставляется очень толковая справочная система наподобие MSDN, вызвать ее можно клавишей F1 из дизайнера. Только что мы создали очень простую программу на Qt4, но, если возникнет желание разобраться в библиотеке поглубже, то лучшего хелпа не найти.

А теперь об изменениях в Qt4 по сравнению с Qt3.2. Написать об этом и не употребить ни одного матерного слова — задача практически невыполнимая. Изменений много, и они глобальны. Если у вас уже есть проект, написанный на Qt3.х, который нужно перенести на Qt4 — мои соболезнования! Trolltech настолько не позаботилась об обратной совместимости, что изменила не только некоторые имена классов и методов, но даже их общую семантику. Настоящей насмешкой звучит название утилиты "qt3to4", предназначенной для автоматизации портирования. Все, что сделает эта утилита — просто переименует некоторые классы — вот и все. В документации на qt3to4 сказано примерно так: "Запустите qt3to4, затем — make, после чего исправьте все ошибки, выявленные во время сборки". Некоторые классы настолько видоизменились, что для упрощения портирования в Qt4 просто оставили их Qt3'шные версии — они имеют приставку "Q3". Кроме множества внешних изменений, которые вы мгновенно заметите, как только начнете использовать Qt4, есть множество изменений внутренних. Они сотрясли самые основы библиотеки Qt. Во-первых, это, конечно, введение технологии The Interview Framework. Работает она как "Документ-представление" в MFC, но со своими особенностями. Паттерн проектирования, на котором основана эта технология, в документации по Qt4 назвали не "Document-view", а "Model-view" чтобы подчеркнуть, что данные, отображаемые в представлении, недоступны напрямую. Объект "Модель" просто предоставляет к ним интерфейс и контролирует все объекты представления. А для обработки и отображения этих данных используются делегаты — специальные классы, позволяющие вынести функциональность по обработке данных за границы объекта модели. Таким образом, некоторые виджеты разработаны в двух версиях и называются, например, так: QTreeView (используется в паттерне модель-вид) и QTreeWidget (классический вариант). Во-вторых, сильно изменился класс QMainWindow. Нового в него практически ничего не добавили, зато вынесли всю функциональность по контролю за дочерними виджетами в другие классы. Пример:

Qt 3:
QPopupMenu *fileMenu = new QPopupMenu(this);
openAction->addTo(fileMenu);
menuBar()->insertItem(tr("&File"), fileMenu);
Qt 4:
QMenu *fileMenu = menuBar()->addMenu(tr("&File"));
fileMenu->addAction(openAction);

В-третьих, новый, сильно улучшенный графический движок Arthur. По возможностям он не уступает GDI+ из .NET и содержит множество улучшений по сравнению с Qt3. Лично для себя я отметил одно из таких улучшений: поддержка двойной буферизации по умолчанию. Пример:

Qt3:
QPixmap buffer(size());
QPainter painter(&buffer);
// Рисование
painter.end();
bitBlt(this, 0, 0, &buffer);
Qt4:
QPainter painter(this);
// Рисование
painter.end();

В-четвертых, новая библиотека контейнеров Tulip. Изменение: теперь контейнеры, как и в STL, основаны на "значениях", а не на ссылках, и добавлены новые итераторы по образцу Java. В-пятых, новый текстовый движок Scribe. Он заменяет старый RichText-engine и добавляет новую функциональность для обработки простого текста и текста в формате rtf. Кроме того, глобальной переработке и улучшению подверглись еще многие и многие модули (SQL-движок, подсистемы сети, ресурсов и т.д.). В общем, похоже, что Qt4 действительно гораздо лучше Qt3 и со временем сживет со свету свою предшественницу. А значит — ждем KDE4;-). Что касается новейших средств Linux для программистов, то мой рассказ еще не закончен. На очереди обзор реализации .NET под Linux — .Mono.

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


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

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