フローレイアウトの例
ウィンドウサイズに応じてウィジェットを配置する方法を示しています。
フローレイアウトは、さまざまなウィンドウサイズに対応するレイアウトを実装しています。ウィジェットの配置は、アプリケーションウィンドウの幅に応じて変化します。

FlowLayout クラスは主に `QLayout ` および `QWidgetItem` を使用しますが、Window クラスは `QWidget ` および `QLabel` を使用します。
詳細については、「レイアウト管理」のページをご覧ください。
例の動作確認
サンプルを実行するには、以下の手順に従ってください。
- Qt Creator
Welcome モードを開き、Examples からサンプルを選択します。詳細については、Qt Creator の「チュートリアル:ビルドと実行」を参照してください。
- Qt Extension for Visual Studio Code
Command Palette から `Qt: Open Qt examples ` コマンドを実行し、リストからサンプルを選択してください。詳細については、Qt Extension for Visual Studio Code の「チュートリアル:ビルドと実行」を参照してください。
FlowLayout クラスの定義
FlowLayout クラスはQLayout を継承しています。これは、子ウィジェットを水平方向および垂直方向に配置するカスタムレイアウトクラスです。
class FlowLayout : public QLayout
{
public:
explicit FlowLayout(QWidget *parent, int margin = -1, int hSpacing = -1, int vSpacing = -1);
explicit FlowLayout(int margin = -1, int hSpacing = -1, int vSpacing = -1);
~FlowLayout();
void addItem(QLayoutItem *item) override;
int horizontalSpacing() const;
int verticalSpacing() const;
Qt::Orientations expandingDirections() const override;
bool hasHeightForWidth() const override;
int heightForWidth(int) const override;
int count() const override;
QLayoutItem *itemAt(int index) const override;
QSize minimumSize() const override;
void setGeometry(const QRect &rect) override;
QSize sizeHint() const override;
QLayoutItem *takeAt(int index) override;
private:
int doLayout(const QRect &rect, bool testOnly) const;
int smartSpacing(QStyle::PixelMetric pm) const;
QList<QLayoutItem *> itemList;
int m_hSpace;
int m_vSpace;
};QLayout から継承した関数を再実装します。これらの関数は、レイアウトに項目を追加し、その向きや形状を処理します。
また、2つのプライベートメソッド、doLayout() とsmartSpacing() を宣言します。doLayout() はレイアウト項目を配置し、smartSpacing() 関数は項目間の間隔を計算します。
FlowLayout クラスの実装
まず、コンストラクタから見ていきましょう:
FlowLayout::FlowLayout(QWidget *parent, int margin, int hSpacing, int vSpacing)
: QLayout(parent), m_hSpace(hSpacing), m_vSpace(vSpacing)
{
setContentsMargins(margin, margin, margin, margin);
}
FlowLayout::FlowLayout(int margin, int hSpacing, int vSpacing)
: m_hSpace(hSpacing), m_vSpace(vSpacing)
{
setContentsMargins(margin, margin, margin, margin);
}コンストラクタ内では、setContentsMargins() を呼び出して、左、上、右、下のマージンを設定します。デフォルトでは、QLayout は現在のスタイルから提供された値を使用します(QStyle::PixelMetric を参照)。
FlowLayout::~FlowLayout()
{
QLayoutItem *item;
while ((item = takeAt(0)))
delete item;
}この例では、純粋仮想関数であるaddItem() を再実装しています。addItem() を使用する場合、レイアウト項目の所有権はレイアウトに移管されるため、それらを削除するのはレイアウトの責任となります。
void FlowLayout::addItem(QLayoutItem *item)
{
itemList.append(item);
}addItem() は、レイアウトにアイテムを追加するために実装されます。
int FlowLayout::horizontalSpacing() const
{
if (m_hSpace >= 0) {
return m_hSpace;
} else {
return smartSpacing(QStyle::PM_LayoutHorizontalSpacing);
}
}
int FlowLayout::verticalSpacing() const
{
if (m_vSpace >= 0) {
return m_vSpace;
} else {
return smartSpacing(QStyle::PM_LayoutVerticalSpacing);
}
}horizontalSpacing() およびverticalSpacing() を実装し、レイアウト内のウィジェット間の間隔を取得します。値が 0 以下の場合は、この値が使用されます。そうでない場合は、smartSpacing() が呼び出され、間隔が計算されます。
int FlowLayout::count() const
{
return itemList.size();
}
QLayoutItem *FlowLayout::itemAt(int index) const
{
return itemList.value(index);
}
QLayoutItem *FlowLayout::takeAt(int index)
{
if (index >= 0 && index < itemList.size())
return itemList.takeAt(index);
return nullptr;
}次に、count() を実装して、レイアウト内のアイテム数を返します。アイテムのリストを操作するには、itemAt() と takeAt() を使用して、リストからアイテムを削除・取得します。アイテムが削除されると、残りのアイテムの番号が再割り当てされます。これら3つの関数はすべて、QLayout からの純粋仮想関数です。
Qt::Orientations FlowLayout::expandingDirections() const
{
return { };
}expandingDirections() レイアウトがsizeHint() よりも多くのスペースを利用できるQt::Orientationを返します。
bool FlowLayout::hasHeightForWidth() const
{
return true;
}
int FlowLayout::heightForWidth(int width) const
{
int height = doLayout(QRect(0, 0, width, 0), true);
return height;
}高さが幅に依存するウィジェットに対応するため、heightForWidth() を実装します。関数hasHeightForWidth() はこの依存関係を判定するために使用され、heightForWidth() は幅をdoLayout() に渡し、 はその幅をレイアウト矩形(つまり、アイテムが配置される範囲)の引数として使用します。この矩形には、レイアウトの margin() は含まれません。
void FlowLayout::setGeometry(const QRect &rect)
{
QLayout::setGeometry(rect);
doLayout(rect, false);
}
QSize FlowLayout::sizeHint() const
{
return minimumSize();
}
QSize FlowLayout::minimumSize() const
{
QSize size;
for (const QLayoutItem *item : std::as_const(itemList))
size = size.expandedTo(item->minimumSize());
const QMargins margins = contentsMargins();
size += QSize(margins.left() + margins.right(), margins.top() + margins.bottom());
return size;
}setGeometry() は通常、実際のレイアウト、すなわちレイアウト項目のジオメトリを計算するために使用されます。この例では、doLayout() を呼び出し、レイアウト矩形を渡しています。
sizeHint() はレイアウトの推奨サイズを返し、minimumSize() はレイアウトの最小サイズを返します。
int FlowLayout::doLayout(const QRect &rect, bool testOnly) const
{
int left, top, right, bottom;
getContentsMargins(&left, &top, &right, &bottom);
QRect effectiveRect = rect.adjusted(+left, +top, -right, -bottom);
int x = effectiveRect.x();
int y = effectiveRect.y();
int lineHeight = 0;doLayout() horizontalSpacing() または がデフォルト値を返さない場合、この関数がレイアウトを処理します。 を使用して、レイアウト項目が利用できる領域を計算します。verticalSpacing() getContentsMargins()
for (QLayoutItem *item : std::as_const(itemList)) {
const QWidget *wid = item->widget();
int spaceX = horizontalSpacing();
if (spaceX == -1)
spaceX = wid->style()->layoutSpacing(
QSizePolicy::PushButton, QSizePolicy::PushButton, Qt::Horizontal);
int spaceY = verticalSpacing();
if (spaceY == -1)
spaceY = wid->style()->layoutSpacing(
QSizePolicy::PushButton, QSizePolicy::PushButton, Qt::Vertical);その後、現在のスタイルに基づいて、レイアウト内の各ウィジェットに適切な間隔を設定します。
int nextX = x + item->sizeHint().width() + spaceX;
if (nextX - spaceX > effectiveRect.right() && lineHeight > 0) {
x = effectiveRect.x();
y = y + lineHeight + spaceY;
nextX = x + item->sizeHint().width() + spaceX;
lineHeight = 0;
}
if (!testOnly)
item->setGeometry(QRect(QPoint(x, y), item->sizeHint()));
x = nextX;
lineHeight = qMax(lineHeight, item->sizeHint().height());
}
return y + lineHeight - rect.y() + bottom;
}その後、各アイテムの幅と行高さを初期の x 座標および y 座標に加算することで、レイアウト内の各アイテムの位置を計算します。これにより、次のアイテムが現在の行に収まるか、それとも次の行に移動する必要があるかを判断できます。また、ウィジェットの高さに基づいて、現在の行の高さも算出します。
int FlowLayout::smartSpacing(QStyle::PixelMetric pm) const
{
QObject *parent = this->parent();
if (!parent) {
return -1;
} else if (parent->isWidgetType()) {
QWidget *pw = static_cast<QWidget *>(parent);
return pw->style()->pixelMetric(pm, nullptr, pw);
} else {
return static_cast<QLayout *>(parent)->spacing();
}
}smartSpacing() は、トップレベルレイアウトまたはサブレイアウトのデフォルトの余白を取得するように設計されています。親がQWidget である場合のトップレベルレイアウトのデフォルトの余白は、スタイルを照会することで決定されます。親がQLayout である場合のサブレイアウトのデフォルトの余白は、親レイアウトの余白を照会することで決定されます。
© 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.