KnigaRead.com/
KnigaRead.com » Компьютеры и Интернет » Программирование » Жасмин Бланшет - QT 4: программирование GUI на С++

Жасмин Бланшет - QT 4: программирование GUI на С++

На нашем сайте KnigaRead.com Вы можете абсолютно бесплатно читать книгу онлайн Жасмин Бланшет, "QT 4: программирование GUI на С++" бесплатно, без регистрации.
Перейти на страницу:

12 }

Мы хотим обеспечить по мере возможности достаточность указанного размера для размещения заданного текста. По этой причине используем метрики шрифта и, если текст оказывается слишком большим, входим в цикл, где уменьшаем размер, пока он не окажется подходящим или не достигнет 9 точек, что соответствует нашему минимальному размеру.

13 QPixmap pixmap(size);

14 QPainter painter(&pixmap);

15 painter.setFont(myFont);

16 painter.setPen(pen);

17 painter.setBrush(brush);

18 painter.setRenderHint(QPainter::Antialiasing, true);

19 painter.setRenderHint(QPainter::TextAntialiasing, true);

20 painter.setRenderHint(QPainter::SmoothPixmapTransform, true);

21 painter.eraseRect(pixmap.rect());

Мы создаем пиксельную карту требуемого размера и рисовальщик для рисования на пиксельной карте. Также устанавливаем некоторые особенности воспроизведения, чтобы обеспечить максимальное сглаживание при выводе текста. Вызов функции eraseRect() очищает пиксельную карту, заполняя ее цветом фона.

22 if (effect == "Plain") {

23 painter.setPen(Qt::NoPen);

24 } else if (effect == "Outline") {

25 QPen pen(Qt::black);

26 pen.setWidthF(2.5);

27 painter.setPen(pen);

28 } else if (effect == "Shadow") {

29 QPainterPath path;

30 painter.setBrush(Qt::darkGray);

31 path.addText(((size.width() - metrics.width(text)) / 2) + 3,

32 (size.height() - metrics.descent()) + 3, myFont, text);

33 painter.drawPath(path);

34 painter.setBrush(brush);

35 }

Для эффекта «Plain» (простой) не требуется никакой рамки. Для эффекта «Outline» (рамка) игнорируем исходное перо и создаем наше собственное перо шириной в 2.5 пикселя. Для эффекта «Shadow» (тень) сначала рисуется тень, чтобы можно было выводить текст поверх нее.

36 QPainterPath path;

37 path.addText((size.width() - metrics.width(text)) / 2,

38 size.height() - metrics.descent(), myFont, text);

39 painter.drawPath(path);

40 return pixmap;

41 }

Теперь у нас имеются перо и кисти, соответствующим образом установленные для каждого текстового эффекта, а для эффекта «Shadow» нарисована тень. После этого мы готовы воспроизвести текст. Текст центрируется по горизонтали и выводится достаточно далеко от нижнего края пиксельной карты, чтобы оставить достаточно места для размещения нижних выносных элементов.

Q_EXPORT_PLUGIN2(basiceffectsplugin, BasicEffectsPlugin)

В конце файла .cpp используем макрос Q_EXPORT_PLUGIN2(), чтобы этот подключаемый элемент был доступен для Qt.

Файл .pro аналогичен файлу, который мы использовали ранее в данной главе для подключаемого модуля курсоров Windows:

TEMPLATE = lib

CONFIG += plugin

HEADERS = ../textart/textartinterface.h

basiceffectsplugin.h

SOURCES = basiceffectsplugin.cpp

DESTDIR =../textart/plugins

Если данная глава повысила ваш интерес к подключаемым к приложению модулям, вы можете изучить имеющийся в Qt более сложный пример Plug & Paint (подключи и рисуй). Приложение поддерживает три различных интерфейса и включает в себя полезное диалоговое окно Plugin Information (информация о подключаемых модулях), которое содержит списки подключаемых модулей и интерфейсов, доступных в приложении.

Глава 20. Возможности, зависимые от платформы

В данной главе мы рассмотрим некоторые доступные программистам Qt возможности, которые зависят от платформы. Мы начнем с рассмотрения способов доступа к таким «родным» программным интерфейсам, как Win32 API в системе Windows, Carbon в системе Mac OS X и Xlib в системе X11. Затем мы перейдем к изучению расширения ActiveQt, демонстрируя способы применения элементов управления ActiveX в приложениях Qt, работающих в системе Windows, а также способы создания приложений, выполняющих функции серверов ActiveX. В последнем разделе мы рассмотрим способы взаимодействия приложений Qt с менеджером сеансов системы X11.

Кроме представленных здесь возможностей компания «Trolltech» предлагает несколько зависимых от платформы решений в рамках проекта Qt Solutions, в частности миграционные фреймворки Qt/Motif и Qt/MFC, позволяющие упростить перевод в Qt приложений Motif/Xt и MFC. Подобное расширение для приложений Tcl/Tk обеспечивается фирмой «Froglogic», а компанией «Klaralvdalens Datakonsult» разработан конвертор ресурсов Windows компании Microsoft. Дополнительную информацию вы найдете на следующих веб-страницах:

• http://www.trolltech.com/products/solutions/catalog/

• http://www.froglogic.com/tq/

• http://www.kdab.net/knut/

Для встроенных приложений компания «Trolltech» обеспечивает Qtopia — рабочую среду для разработки таких приложений. Она рассматривается в главе 21.

Применение «родных» программных интерфейсов

Всесторонний программный интерфейс Qt удовлетворяет большинству требований на всех платформах, но при некоторых обстоятельствах нам может потребоваться базовый, платформозависимый программный интерфейс. В данном разделе мы продемонстрируем способы применения «родных» программных интерфейсов различных платформ, поддерживаемых Qt, для решения конкретных задач.

Для каждой платформы класс QWidget поддерживает функцию winId(), которая возвращает идентификатор или описатель окна. QWidget также обеспечивает статическую функцию find(), которая возвращает QWidget с идентификатором конкретного окна. Мы можем передавать этот идентификатор функциям «родного» программного интерфейса для достижения эффектов, зависимых от платформы. Например, в следующем программном коде используется функция winId() для отображения слева заголовка панели инструментов, используя «родные» функции Mac OS X:

#ifdef Q_WS_MAC

ChangeWindowAttributes(HIViewGetWindow(HIViewRef(toolWin.winId())),

kWindowSideTitlebarAttribute, kWindowNoAttributes);

#endif

Рис. 20.1. Окно панели инструментов Mac OS X с отображением заголовка сбоку.

Ниже показано, как в системе X11 мы можем модифицировать свойство окна:

#ifdef Q_WS_X11

Atom atom = XInternAtom(QX11Info::display(), "MY_PROPERTY", False);

long data = 1;

XChangeProperty(QX11Info::display(), window->winId(), atom, atom,

32, PropModeReplace, reinterpret_cast<uchar *>(&data), 1);

#endif

Использование директив #ifdef и #endif вокруг зависимого от платформы программного кода гарантирует компиляцию приложения на других платформах.

Приведенный ниже пример показывает, как в приложениях, предназначенных только для Windows, можно использовать вызовы GDI для рисования на виджете Qt:

01 void GdiControl::paintEvent(QPaintEvent * /* event */)

02 {

03 RECT rect;

04 GetClientRect(winId(), &rect);

05 HDC hdc = GetDC(winId());

06 FillRect(hdc, &rect, HBRUSH(COLOR_WINDOW + 1));

07 SetTextAlign(hdc, TA_CENTER | TA_BASELINE);

08 TextOutW(hdc, width() / 2, height() / 2,

09 text.utf16(), text.size());

10 ReleaseDC(winId(), hdc);

11 }

Чтобы это сработало, мы должны также переопределить функцию QPaintDevice::paintEngine() для возврата нулевого указателя и установить атрибут Qt::WA_PaintOnScreen в конструкторе виджета.

Следующий пример показывает, как можно сочетать QPainter и GDI в обработчике события рисования, используя функции getDC() и releaseDC() класса QPaintEngine:

01 void MyWidget::paintEvent(QPaintEvent * /* event */)

02 {

03 QPainter painter(this);

04 painter.fillRect(rect().adjusted(20, 20, -20, -20), Qt::red);

05 #ifdef Q_WS_WIN

06 HDC hdc = painter.paintEngine()->getDC();

07 Rectangle(hdc, 40, 40, width() - 40, height() - 40);

08 painter.paintEngine()->releaseDC();

09 #endif

10 }

Подобное совмещение вызовов QPainter и GDI иногда может дать странный результат, особенно когда вызовы QPainter выполняются после вызовов GDI, потому что QPainter делает некоторые предположения о состоянии базового уровня рисования.

Qt определяет один из следующих четырех символов оконной системы: Q_WS_WIN, Q_WS_X11, Q_WS_MAC и Q_WS_QWS (Qtopia). Мы должны обеспечить включение хотя бы одного заголовка Qt перед их использованием в приложениях. Qt также обеспечивает препроцессорные символы для идентификации операционной системы:

• Q_OS_AIX

• Q_OS_BSD4

• Q_OS_BSDI

• Q_OS_CYGWIN

• Q_OS_DGUX

• Q_OS_DYNIX

• Q_OS_FREEBSD

• Q_OS_HPUX

• Q_OS_HURD

• Q_OS_IRIX

• Q_OS_LINUX

• Q_OS_LYNX

• Q_OS_MAC

• Q_OS_NETBSD

• Q_OS_OPENBSD

• Q_OS_OS2EMX

• Q_OS_OSF

• Q_OS_QNX6

• Q_OS_QNX

• Q_OS_RELIANT

• Q_OS_SCO

Перейти на страницу:
Прокомментировать
Подтвердите что вы не робот:*