このページでは

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

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

「基本的なグラフィックスレイアウト」の例では、QGraphicsView に含まれるレイアウトクラス(QGraphicsLinearLayout およびQGraphicsGridLayout )の使用方法を示しています。さらに、独自のカスタムレイアウトアイテムを作成する方法についても説明しています。

「基本レイアウト」の例のスクリーンショット

ウィンドウクラスの定義

Window クラスは、QGraphicsWidget のサブクラスです。このクラスには、QGraphicsWidget parent をパラメータとするコンストラクタがあります。

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

};

Windowクラスの実装

Window のコンストラクタは、縦向き(vertical)のQGraphicsLinearLayout オブジェクト(windowLayout 、QGraphicsLinearLayout )をインスタンス化します。次に、親がwindowLayout である別の オブジェクト(linear )をインスタンス化します。続いて、LayoutItem オブジェクト(item )を作成し、addItem()関数を使用してlinear に追加します。また、item にstretchFactor を指定します。

    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);

次に、linear をwindowLayout に追加し、2つのQGraphicsLinearLayout オブジェクトをネストさせます。QGraphicsLinearLayout の他に、QGraphicsGridLayout オブジェクトであるgrid も使用します。これは、一部のセルが他の行にまたがる4×3のグリッドです。

以下のコードスニペットに示すように、7つのLayoutItem オブジェクトを作成し、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()では、アイテムを配置するセルを指定するために、引数として行番号と列番号が必要です。また、rowSpan およびcolumnSpan の引数が省略された場合、デフォルト値は1になります。

なお、構築する各LayoutItem に対して親を指定する必要はありません。これらすべてのアイテムはwindowLayout に追加されるためです。レイアウトにアイテムを追加すると、そのアイテムは自動的に、レイアウトがインストールされているウィジェットを親として再設定されます。

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

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

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 = 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() 関数の目的は、背景の矩形を描画し、その後にピクマップを囲む矩形を描画することです。

    // 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());
}

アイテムのサイズがピクマップより小さくなるのを防ぐため、m_pix より大きいサイズヒントを返すようにする必要があります。また、後で描画する境界線のために、周囲に余白を追加します。 あるいは、アイテムがピクマップより小さくならないように、ピクマップをスケーリングすることも可能です。推奨サイズは最小サイズヒントと同じにし、最大サイズは大きな値に設定します

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

© 2026 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.