Оглавление
Переход на графическое представлениеГрафическое представление обеспечивает поверхность для управления и взаимодействия с большим количеством созданных пользователем двумерных графических элементов, а также виджет для их визуализации с поддержкой масштабирования и вращения. Графическое представление было введено в Qt 4.2 и заменило своего предшественника, класс QCanvas. Для получения дополнительной информации о графическом представлении смотрите Каркас графического представления. Этот документ проводит по всем необходимым шагам, класс за классом, функцию за функцией переводя приложение с QCanvas на графическое представление. Qt 4.2 предоставляет два полных примера приложений Q3Canvas переведённых на графическое представление:
ВведениеВ основном, Классы графического представления из Qt 4 и классы канвы из Qt 3 предоставляют похожую функциональность используя одинаковый дизайн. Вместо "канва", мы используем термин "сцена". Другими словами, имена классов и функций почти такие же как в Qt 3. Простейшими классами для перехода будут QCanvas и QCanvasView. Опыт показывает что больше всего времени тратится на перевод классов элементов, в зависимости от сложности классов QCanvasItem которые вы использовали раньше. Это руководство по переводу будет подразумевать что вы уже перевели ваше приложение на Qt 4, использовав Q3Canvas. Если вы ещё не сделали это, в качестве первого шага запустите инструмент qt3to4 для вашего проекта. Этот инструмент автоматизирует наиболее трудоёмкую часть усилий по переходу. Обычно требуются некоторые дополнительные шаги, прежде чем ваше приложение скомпилируется и запустится. Вы можете прочитать больше о процессе портирования в Переход на Qt 4. Переход от Q3CanvasQGraphicsScene является ближайшем эквивалентом для Q3Canvas. Есть некоторые заметные различия в новом API: Где классы Q3Canvas используют целочисленную точность, QGraphicsScene полностью основан на координатах с плавающей точкой, с графическими примитивами такими как QPointF вместо QPoint, QRectF вместо QRect и QPolygonF и QPainterPath. Область канвы определяется прямоугольником сцены, позволяя отрицательные координаты, в отличие от Q3Canvas, которая определяет только размер (QSize), и у которой верхний левый угол всегда (0, 0). К тому же, больше нет явной поддержки плиток канвы; смотрите Перевод сцен с плитками для дополнительной информации. Кусочная индексная система была заменена неявно поддерживаемым внутренним BSP-деревом. Таблица перехода
Перевод сцен с плиткамиQGraphicsScene не предоставляет API для плиток. Тем не менее, вы можете получить похожее поведение отрисовывая растровые изображения в переопределённой функции QGraphicsScene::drawBackground(). Поддержка плиток Q3Canvas основана на предоставлении одного растрового изображения, содержащего плитки фиксированной ширины и высоты, и затем доступа к ним (чтение и замена пластин) по индексу. Плитки в растровом изображении упорядочены слева на право, сверху вниз.
С графическим представлением это растровое изображение может храниться как член подкласса QGraphicsScene. Три главные функции, которые составляют открытый API плиток, могут быть определены как новые члены этого класса. Вот один пример как реализовать поддержку плиток: class TileScene : public QGraphicsScene { public: ... void setTiles(const QPixmap &pixmap, int h, int v, int tileHeight, int tileWidth); void setTile(int x, int y, int tilenum); private: QRect tileRect(int x, int y) const; QRect tileRect(int tileNum) const; QVector<QVector<int> > tiles; QPixmap tilePixmap; int tileW, tileH; int hTiles, vTiles; }; В зависимости от того как ваша сцена использует пластины, вы можете упростить этот подход. В данном примере мы попробуем воспроизвести поведение функций Q3Canvas. Мы начинаем с создания подкласса QGraphicsScene ("TileScene"). В этом классе мы декларируем две функции для работы с плитками из Q3Canvas, а затем мы добавляем две вспомогательные функции, которые возвращают прямоугольник для определённой плитки в нашем растровом изображении плиток. Мы будем использовать двухмерный вектор целых чисел чтобы отслеживать какие плитки должны быть использованы на какой части сцены. void TileScene::setTiles(const QPixmap &pixmap, int h, int v, int tileHeight, int tileWidth) { tilePixmap = pixmap; tileW = tileWidth; tileH = tileHeight; hTiles = h; vTiles = v; tiles.resize(v); for (int y = 0; y < v; ++y) tiles[y].resize(h); } В setTiles() мы сохраняем растровое изображение и свойства плитки как члены класса. Затем мы изменяем размер вектора плиток чтобы он совпадал с шириной и высотой нашей сетки пластин. void TileScene::setTile(int x, int y, int tilenum) { tiles[y][x] = tilenum; update(tileRect(x, y)); } Функция setTile() обновляет индекс плиток и затем обновляет соответствующий прямоугольник на сцене, вызывая tileRect(). QRect TileScene::tileRect(int x, int y) const { return QRect(x * tileW, y * tileH, tileW, tileH); } Первая функция tileRect() возвращает QRect для плитки на позиции (x, y). QRect TileScene::tileRect(int tileNum) const { int numHTiles = tilePixmap.width() / tileW; int numVTiles = tilePixmap.height() / tileH; return tileRect(tileNum % numHTiles, tileNum / numHTiles); } Вторая функция tileRect() возвращает QRect для номера плитки. С этими функциями мы можем реализовать функцию drawBackground(). void drawBackground(QPainter *painter, const QRectF &exposed) { for (int y = 0; y < vTiles; ++y) { for (int x = 0; x < hTiles; ++x) { QRect destRect = tileRect(x, y); if (exposed.intersects(destRect)) { painter->drawPixmap(destRect, tilePixmap, tileRect(tiles[y][x])); } } } } В drawBackground(), мы перерисовываем все плитки, прямоугольники которых пересекаются с отображаемой области фона. Переход от Q3CanvasViewБлижайший эквивалент для Q3CanvasView в графическом представлении называется QGraphicsView. В большинстве случаев это простейший класс для перевода. В дополнение ко всей предоставляемой функциональности Q3CanvasView, QGraphicsView включает некоторые новые полезные особенности. Вы можете прочитать об этом больше в документации по QGraphicsView. Таблица переходаДругие различияQGraphicsView может кэшировать видимое содержимое сцены, аналогично тому как Q3Canvas::setDoubleBuffering() может кэшировать все содержимое сцены. Вы можете вызвать QGraphicsView::setCacheMode() для настройки кэширования и QGraphicsView::resetCachedContent() аннулирует кэш. Для улучшенной поддержки навигации вы можете установить якорь изменения размера или преобразования с помощью QGraphicsView::resizeAnchor и QGraphicsView::transformationAnchor. Это позволит вам легко поворачивать и масштабировать вид зафиксировав центр или мастабировать относительно позиции под курсором мыши. Также, если вы установите QGraphicsView::dragMode для вида, QGraphicsView предоставит выделение резиновой нитью или навигацию "нажми-и-тяни" с использованием курсоров OpenHandCursor и ClosedHandCursor. Переход от Q3CanvasItemБлижайшим эквивалентом для Q3CanvasItem в графическом представлении называется QGraphicsItem. Наследование от этого класса является обычной практикой, поэтому перевод Q3CanvasItem часто требует больше работы чем Q3Canvas и Q3CanvasView. Q3CanvasItem стал проще для использования, проще для наследования и более мощным с QGraphicsItem. Ключевым отличаем от Q3CanvasItem заключается в продвижении событий и группах элементов, но вы также найдёте несколько новых удобных особенностей, таких как поддержка всплывающих подсказок, курсоров, трансформации элементов и перетаскивания. Вы можете прочитать всё о QGraphicsItem в его собственной документации. Эта секция начинается с таблицы, которая показывает как перевести каждую функцию с Q3CanvasItem на QGraphicsItem. Сразу после этого, каждый стандартный подкласс Q3CanvasItem имеет собственную секцию. Обратите внимание на то, что некоторые виртуальные функции, которые передавались в QGraphicsItem, перестали быть виртуальными. Пример - Q3CanvasItem::moveBy(), которая часто использовалась для отслеживания перемещения элементов. В этом случае виртуальная функция QGraphicsItem::itemChange() перенимается как замена. Q3CanvasPolygonalItemБлижайший эквивалент для Q3CanvasPolygonalItem в графическом представлении называется QAbstractGraphicsShapeItem. В отличае от Q3CanvasPolygonalItem, он не определяет точки области (Q3CanvasPolygonalItem::areaPoints()); вместо этого геометрия каждого элемента хранится в качестве члена подклассов. Функция Q3CanvasPolygonalItem::drawShape() больше не доступна; вместо неё вы можете установить перо и карандаш из QGraphicsItem::paint().
Q3CanvasEllipseБлижайший эквивалент для Q3CanvasEllipse в графическом представлении называется QGraphicsEllipseItem. Наиболее заметное отличие от QGraphicsEllipseItem в том, что эллипс больше не отрисовывается с центром в его позиции; вместо этого он рисуется ограниченным QRectF также как QPainter::drawEllipse(). Для совместимости вы можете сдвинуть эллипс вверх и влево чтобы сохранить эллипс отцентрированным. Пример: // Прежде Q3CanvasEllipse ellipse(10, 10); // После QGraphicsEllipseItem ellipse(-5, -5, 10, 10); Замечание: QGraphicsEllipseItem использует QAbstractGraphicsShapeItem::pen() для внешних линий там, где Q3CanvasEllipse не использует Q3CanvasPolygonalItem::pen(). Q3CanvasLineБлижайший эквивалент для Q3CanvasLine в графическом представлении называется QGraphicsLineItem. Q3CanvasPolygonБлижайший эквивалент для Q3CanvasPolygon в графическом представлении называется QGraphicsPolygonItem. Q3CanvasSplineБлижайший эквивалент для Q3CanvasSpline в графическом представлении называется QGraphicsPathItem. Этот элемент может быть использован для описания любого типа пути, поддерживаемого QPainter. Q3CanvasSpline берёт свои контрольные точки в качестве Q3PointArray, но QPainterPath оперирует последовательностью вызовов QPainterPath::moveTo() и QPainterPath::cubicTo(). Вот как вы можете преобразовать кривую Безье Q3PointArray в QPainterPath: static QPainterPath fromControlPoints(const Q3PointArray &pa) { QPainterPath path; path.moveTo(pa[0]); for (int i = 1; i < pa.size(); i += 3) path.cubicTo(pa[i], pa[(i + 1) % pa.size()], pa[(i + 2) % pa.size()]); return path; } Замечание: QGraphicsPathItem использует QAbstractGraphicsShapeItem::pen() для внешних линий там, где Q3CanvasSpline не использует Q3CanvasPolygonalItem::pen().
Q3CanvasRectangleБлижайший эквивалент для Q3CanvasRectangle в графическом представлении называется QGraphicsRectItem. Q3CanvasSpriteQ3CanvasSprite это класс элемента, которые в наибольшей степени отличается от своего предшественника Q3Canvas. Ближайшим подобием Q3CanvasSprite в графическом представлении является QGraphicsPixmapItem. Q3CanvasSprite поддерживает анимированные растровые изображения; тем не менее QGraphicsPixmapItem является элементом с простым однокадровым растровым изображением. Если всё что вам нужно это растровое изображение, то переход является простым. Если вам требуется поддержка анимации, то потребуется дополнительная работа; в данном случае нет прямого подхода для перехода. Для примера Пример "Ported Asteroids" используется подкласс QGraphicsPixmapItem для замещения Q3CanvasSprite, храня список изображений и счётчик кадров. Анимация происходит в QGraphicsItem::advance(). Q3CanvasPixmap, Q3CanvasPixmapArrayЭти классы были убраны из API. Вы можете использовать QPixmap вместо Q3CanvasPixmap и QList вместо Q3CanvasPixmapArray. Q3CanvasPixmapArray обеспечивает удобство для загрузки последовательности изображений или масок с использованием пути с подстановочными знаками (смотрите Q3CanvasPixmapArray::readPixmaps() и Q3CanvasPixmapArray::readCollisionMasks()). Чтобы добиться похожей функциональности с использованием графического представления, вы можете загружать изображения с использованием QDir: wildcardPath.replace("%1", "*"); QFileInfo fi(wildcardPath); QList<QPixmap> frames; foreach (QString entry, QDir(fi.path(), fi.fileName()).entryList()) frames << QPixmap(fi.path() + "/" + entry); Q3CanvasTextВ графическом представлении Q3CanvasText был разделён на два кла: QGraphicsSimpleTextItem и QGraphicsTextItem. Для перехода вполне подходит QGraphicsSimpleTextItem. QGraphicsTextItem предоставляет дополнительные особенности структурирования документа, похожие на возможности QTextEdit, и также позволяет взаимодействие (т.е., редактирование и выделение). Q3CanvasItemListВместо этого используйте QList. Другие ресурсыСтатья Porting to Qt 4.2's Graphics View в ежеквартальнике Qt Quarterly 21 описывает процесс перевода примера канвы с Qt 3 на Qt 4. Результатом является пример Ported Canvas. |
Попытка перевода Qt документации. Если есть желание присоединиться, или если есть замечания или пожелания, то заходите на форум: Перевод Qt документации на русский язык... Люди внесшие вклад в перевод: Команда переводчиков |