Пример "Basic Graphics Layouts"Файлы:
Изображения: Пример "Basic Graphics Layouts" демонстрирует как использовать классы компоновки в QGraphicsView: QGraphicsLinearLayout и QGraphicsGridLayout. В дополнение, покажем, как писать ваш собственный пользовательский элемент компоновки. Определение класса WindowКласс Window является подклассом QGraphicsWidget. У него есть конструктор с QGraphicsWidget parent в качестве параметра. class Window : public QGraphicsWidget { Q_OBJECT public: Window(QGraphicsWidget *parent = 0); }; Реализация класса WindowКонструктор Window создает объект QGraphicsLinearLayout, windowLayout, с вертикальной ориентацией. Мы создаем другой объект QGraphicsLinearLayout, linear, чьим родителем является windowLayout. Затем, мы создаем объект LayoutItem item и добавляем его в linear с помощью функции addItem(). Мы также обеспечиваем item с stretchFactor. QGraphicsLinearLayout *windowLayout = new QGraphicsLinearLayout(Qt::Vertical); QGraphicsLinearLayout *linear = new QGraphicsLinearLayout(windowLayout); LayoutItem *item = new LayoutItem; linear->addItem(item); linear->setStretchFactor(item, 1); Мы повторяем процесс:
item = new LayoutItem; linear->addItem(item); linear->setStretchFactor(item, 3); windowLayout->addItem(linear); Затем мы добавляем linear в windowLayout, размещая два объекта QGraphicsLinearLayout. Кроме QGraphicsLinearLayout мы также используем объект QGraphicsGridLayout grid, являющимся сеткой 4x3 с некоторыми ячейками распространяющимся на другие строки. Мы создаем семь объектов LayoutItem и размещаем их в grid с помощью функции addItem() как показано в примере кода ниже: QGraphicsGridLayout *grid = new QGraphicsGridLayout(windowLayout); item = new LayoutItem; grid->addItem(item, 0, 0, 4, 1); item = new LayoutItem; item->setMaximumHeight(item->minimumHeight()); grid->addItem(item, 0, 1, 2, 1, Qt::AlignVCenter); item = new LayoutItem; item->setMaximumHeight(item->minimumHeight()); grid->addItem(item, 2, 1, 2, 1, Qt::AlignVCenter); item = new LayoutItem; grid->addItem(item, 0, 2); item = new LayoutItem; grid->addItem(item, 1, 2); item = new LayoutItem; grid->addItem(item, 2, 2); item = new LayoutItem; grid->addItem(item, 3, 2); windowLayout->addItem(grid); Первый элемент который мы добавляем в grid размещается в левой верхней ячейке, распространенной на 4 строки. Следующие два элемента расположены во втором столбце и распространяются на две строки. Значения maximumHeight() и minimumHeight() каждого элемента установленны одинаковыми чтобы они не расширялись вертикально. В результате эти элементы не поместятся в своих ячейках вертикально. Поэтому мы указываем что они должны быть выровнены по вертикали в центре ячейки используя Qt::AlignVCenter. Наконец сам grid добавляется в windowLayout. В отличае от QGridLayout::addItem(), QGraphicsGridLayout::addItem() требует строку и столбец в качестве аргумента, указывающих в какую ячейку элемент должен быть размещен. Также если аргументы rowSpan и columnSpan опущены, то по умолчанию они будут равны 1. Заметьте, что мы не указываем родителя для каждого LayoutItem который мы создаем так как все эти элементы будут добавлены в windowLayout. Когда мы добавляем элемент в компоновку, он автоматически сменит родителя на виджет в который установлена данная компоновка. setLayout(windowLayout);
setWindowTitle(tr("Basic Graphics Layouts Example"));
Теперь, настроив grid и добавив ее в windowLayout, мы устанавливаем windowLayout в объект окна используя функцию QGraphicsWidget::setLayout() и мы устанавливаем заголовок окна. Определение класса LayoutItemКласс LayoutItem является подклассом QGraphicsLayoutItem и QGraphicsItem. Он имеет конструктор, деструктор и некоторые необходимые переопределения. Так как он унаследован от QGraphicsLayoutItem, он должен переопределить {QGraphicsLayoutItem::setGeometry()}{setGeometry()} и {QGraphicsLayoutItem::sizeHint()}{sizeHint()}. Кроме того чтобы он унаследовал от QGraphicsItem, поэтому он должен переопределить {QGraphicsItem::boundingRect()}{boundingRect()} и {QGraphicsItem::paint()}{paint()}. class LayoutItem : public QGraphicsLayoutItem, public QGraphicsItem { public: LayoutItem(QGraphicsItem *parent = 0); ~LayoutItem(); // Унаследовано от QGraphicsLayoutItem void setGeometry(const QRectF &geom); QSizeF sizeHint(Qt::SizeHint which, const QSizeF &constraint = QSizeF()) const; // Унаследовано от QGraphicsItem QRectF boundingRect() const; void paint(QPainter *painter, const QStyleOptionGraphicsItem *option, QWidget *widget = 0); private: QPixmap *m_pix; }; Класс LayoutItem также имеет частный экземпляр QPixmap, m_pix. Реализация класса LayoutItemВ конструкторе LayoutItem'а, экземпляр класса m_pix создает и в него загружается изображение block.png. LayoutItem::LayoutItem(QGraphicsItem *parent/* = 0*/) : QGraphicsLayoutItem(), QGraphicsItem(parent) { m_pix = new QPixmap(QLatin1String(":/images/block.png")); setGraphicsItem(this); } Мы используем макрос Q_UNUSED() чтобы не допустить генерацию предупреждений компилятором относительно неиспользуемых параметров. void LayoutItem::paint(QPainter *painter, const QStyleOptionGraphicsItem *option, QWidget *widget /*= 0*/) { Q_UNUSED(widget); Q_UNUSED(option); QRectF frame(QPointF(0,0), geometry().size()); qreal w = m_pix->width(); qreal h = m_pix->height(); QGradientStops stops; Смысл функции paint() в отрисовке прямоугольника заднего фона, а затем отрисовка прямоугольника вокруг изображения. // отрисовываем фоновый прямоугольник (с градиентом) QLinearGradient gradient(frame.topLeft(), frame.topLeft() + QPointF(200,200)); stops << QGradientStop(0.0, QColor(60, 60, 60)); stops << QGradientStop(frame.height()/2/frame.height(), QColor(102, 176, 54)); //stops << QGradientStop(((frame.height() + h)/2 )/frame.height(), QColor(157, 195, 55)); stops << QGradientStop(1.0, QColor(215, 215, 215)); gradient.setStops(stops); painter->setBrush(QBrush(gradient)); painter->drawRoundedRect(frame, 10.0, 10.0); // отрисовываем прямоугольник вокруг pixmap (с градиентом) QPointF pixpos = frame.center() - (QPointF(w, h)/2); QRectF innerFrame(pixpos, QSizeF(w, h)); innerFrame.adjust(-4, -4, +4, +4); gradient.setStart(innerFrame.topLeft()); gradient.setFinalStop(innerFrame.bottomRight()); stops.clear(); stops << QGradientStop(0.0, QColor(215, 255, 200)); stops << QGradientStop(0.5, QColor(102, 176, 54)); stops << QGradientStop(1.0, QColor(0, 0, 0)); gradient.setStops(stops); painter->setBrush(QBrush(gradient)); painter->drawRoundedRect(innerFrame, 10.0, 10.0); painter->drawPixmap(pixpos, *m_pix); } Переопределение boundingRect() установит верхний левый угол в (0,0), а его размер будет размером элементов компоновки geometry(). Это область, внутри которой мы рисуем. QRectF LayoutItem::boundingRect() const { return QRectF(QPointF(0,0), geometry().size()); } Переопределение setGeometry() просто вызывает реализацию его базового класса. Однако, так как это изменит boundingRect, мы также должны вызвать prepareGeometryChange(). В заключение, мы перемещаем элемент соответственно в geom.topLeft(). void LayoutItem::setGeometry(const QRectF &geom) { prepareGeometryChange(); QGraphicsLayoutItem::setGeometry(geom); setPos(geom.topLeft()); } Поскольку мы не хотим размер элемента меньше чем растровое изображение, мы должны убедиться что мы возвращаем подсказку размера, которая меньше чем m_pix. Мы также добавили некоторое дополнительное пространство вокруг для границы, которые мы отрисуем позднее. Также вы можете масштабировать изображение, чтобы элемент не стал меньше него. Предпочитаемый размер равен минимальной подсказке размера не смотря на то, что мы установили максимом большое значение. QSizeF LayoutItem::sizeHint(Qt::SizeHint which, const QSizeF &constraint) const { switch (which) { case Qt::MinimumSize: case Qt::PreferredSize: // Не позволять размеру быть меньше чем pixmap с двумя фреймами вокруг него. return m_pix->size() + QSize(12, 12); case Qt::MaximumSize: return QSizeF(1000,1000); default: break; } return constraint; } |
Попытка перевода Qt документации. Если есть желание присоединиться, или если есть замечания или пожелания, то заходите на форум: Перевод Qt документации на русский язык... Люди внесшие вклад в перевод: Команда переводчиков |