基本的なグラフィックレイアウトの例

基本的なグラフィックス・レイアウトの作成方法を示します。

基本的なグラフィック・レイアウトの例では、QGraphicsView のレイアウト・クラスの使い方を示しています :QGraphicsLinearLayoutQGraphicsGridLayout 。 それに加えて、独自のカスタム・レイアウト・アイテムの書き方も示しています。

Screenshot of the Basic Layouts Example

ウィンドウ・クラスの定義

Window クラスはQGraphicsWidget のサブクラスです。QGraphicsWidget parent をパラメータとするコンストラクタを持ちます。

class Window : public QGraphicsWidget
{
    Q_OBJECT
public:
    Window(QGraphicsWidget *parent = nullptr);

};

ウィンドウ・クラスの実装

Window のコンストラクタは、縦向きのQGraphicsLinearLayout オブジェクトwindowLayout をインスタンス化します。windowLayout を親とする別のQGraphicsLinearLayout オブジェクトlinear をインスタンス化します。次に、LayoutItem オブジェクトitem を作成し、addItem() 関数でlinear に追加します。また、itemstretchFactor を追加します。

    QGraphicsLinearLayout *windowLayout = new QGraphicsLinearLayout(Qt::Vertical);
    QGraphicsLinearLayout *linear = new QGraphicsLinearLayout(windowLayout);
    LayoutItem *item = new LayoutItem;
    linear->addItem(item);
    linear->setStretchFactor(item, 1);

このプロセスを繰り返す:

  • 新しいLayoutItem を作成する、
  • linear を追加します。
  • ストレッチ・ファクターを提供する。
    item = new LayoutItem;
    linear->addItem(item);
    linear->setStretchFactor(item, 3);
    windowLayout->addItem(linear);

次に、linearwindowLayout に追加し、2つのQGraphicsLinearLayout オブジェクトを入れ子にします。QGraphicsLinearLayout とは別に、QGraphicsGridLayout オブジェクト、grid も使います。これは4x3のグリッドで、いくつかのセルは他の行にまたがっています。

以下のコード・スニペットに示すように、LayoutItem オブジェクトを7つ作成し、addItem() 関数を使用してgrid に配置します:

    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行にまたがる。次の2つの項目は2列目に配置され、2行にわたります。各項目のmaximumHeight() とminimumHeight() は、縦に展開しないように等しくなるように設定されています。その結果、これらの項目はセルに垂直に収まらない。そこで、Qt::AlignVCenter を使って、セルの中央に縦に並ぶように指定する。

最後に、grid 自身がwindowLayout に追加される。QGridLayout::addItem() と異なり、QGraphicsGridLayout::addItem() は引数に行と列を必要とし、どのセルに項目を配置するかを指定する。また、rowSpancolumnSpan の引数が省略された場合、デフォルトで1になります。

これらのアイテムはすべてwindowLayout に追加されるため、作成するLayoutItem それぞれに親を指定しないことに注意してください。アイテムをレイアウトに追加すると、レイアウトがインストールされているウィジェットに自動的にリペアレントされます。

    setLayout(windowLayout);
    setWindowTitle(tr("Basic Graphics Layouts Example"));

grid を設定し、windowLayout に追加したので、QGraphicsWidget::setLayout() を使用してwindowLayout をウィンドウ・オブジェクトにインストールし、ウィンドウ・タイトルを設定します。

LayoutItemクラスの定義

LayoutItem クラスはQGraphicsLayoutItemQGraphicsItem のサブクラスです。 コンストラクタ、デストラクタ、および必要な再実装があります。QGraphicsLayoutItem を継承しているので、 {QGraphicsLayoutItem::setGeometry()}{setGeometry()} と {QGraphicsLayoutItem::sizeHint()}{sizeHint()} を再実装しなければなりません。さらに、QGraphicsItem を継承しているので、{QGraphicsItem::boundingRect()}{boundingRect()}と{QGraphicsItem::paint()}{paint()}を再実装しなければなりません。

class LayoutItem : public QGraphicsLayoutItem, public QGraphicsItem
{
public:
    LayoutItem(QGraphicsItem *parent = nullptr);

    // Inherited from QGraphicsLayoutItem
    void setGeometry(const QRectF &geom) override;
    QSizeF sizeHint(Qt::SizeHint which, const QSizeF &constraint = QSizeF()) const override;

    // Inherited from QGraphicsItem
    QRectF boundingRect() const override;
    void paint(QPainter *painter, const QStyleOptionGraphicsItem *option, QWidget *widget = nullptr) override;

private:
    QPixmap m_pix;
};

また、LayoutItem クラスはQPixmap のプライベート・インスタンスm_pix を持っています。

LayoutItem クラスの実装

LayoutItem のコンストラクタでは、m_pix がインスタンス化され、block.png 画像がロードされます。

LayoutItem::LayoutItem(QGraphicsItem *parent)
    : QGraphicsLayoutItem(), QGraphicsItem(parent),
      m_pix(QPixmap(QLatin1String(":/images/block.png")))
{
    setGraphicsItem(this);
}

Q_UNUSED ()マクロを使用することで、コンパイラが未使用のパラメータに関する警告を出さないようにしています。

void LayoutItem::paint(QPainter *painter, const QStyleOptionGraphicsItem *option,
                       QWidget *widget)
{
    Q_UNUSED(widget);
    Q_UNUSED(option);

    QRectF frame(QPointF(0, 0), geometry().size());
    const QSize pmSize = m_pix.size();
    QGradientStops stops;

paint() 関数の背後にある考え方は、背景の矩形をペイントし、その後、pixmap の周囲に矩形をペイントすることです。

    // paint a background rect (with gradient)
    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);

    // paint a rect around the pixmap (with gradient)
    QPointF pixpos = frame.center() - (QPointF(pmSize.width(), pmSize.height()) / 2);
    QRectF innerFrame(pixpos, pmSize);
    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());
}

アイテムのサイズをpixmapより小さくしたくないので、m_pix より大きいサイズヒントを返すようにします。また、アイテムがpixmapより小さくならないように、pixmapを拡大縮小することもできます。好ましいサイズは最小サイズのヒントと同じですが、最大サイズは大きな値に設定します。

QSizeF LayoutItem::sizeHint(Qt::SizeHint which, const QSizeF &constraint) const
{
    switch (which) {
    case Qt::MinimumSize:
    case Qt::PreferredSize:
        // Do not allow a size smaller than the pixmap with two frames around it.
        return m_pix.size() + QSize(12, 12);
    case Qt::MaximumSize:
        return QSizeF(1000,1000);
    default:
        break;
    }
    return constraint;
}

プロジェクト例 @ code.qt.io

© 2025 The Qt Company Ltd. Documentation contributions included herein are the copyrights of their respective owners. The documentation provided herein is licensed under the terms of the GNU Free Documentation License version 1.3 as published by the Free Software Foundation. Qt and respective logos are trademarks of The Qt Company Ltd. in Finland and/or other countries worldwide. All other trademarks are property of their respective owners.