【超解説】QSizePolicy::transpose()のしくみと使い方を徹底解説!Qt Widgetsレイアウト自在


この関数は、ウィジェットのレイアウト動作を調整する際に役立ちます。例えば、通常は幅よりも高さを優先するウィジェットを、状況に応じて幅よりも高さを優先するように変更することができます。

QSizePolicy::transpose() の使用方法

QSizePolicy policy;

// 水平方向のポリシーをFixedに、垂直方向のポリシーをExpandingに設定
policy.setHorizontalPolicy(QSizePolicy::Fixed);
policy.setVerticalPolicy(QSizePolicy::Expanding);

// 水平方向と垂直方向のポリシーを交換
policy.transpose();

// 交換後のポリシーを設定
widget->setSizePolicy(policy);

QSizePolicy::transpose() の詳細

  • この関数は、ウィジェットのレイアウトマネージャーに通知し、ウィジェットのサイズポリシーが変更されたことを知らせます。
  • この関数は、ウィジェットのサイズヒントを変更しません。
  • この関数は、void 型の値を返します。
  • この関数は、QSizePolicy オブジェクトをパラメータとして受け取りません。

QSizePolicy::transpose() の例

次の例では、ボタンのサイズポリシーを QSizePolicy::Expanding に設定し、ウィンドウ全体に広がるようにします。

QPushButton *button = new QPushButton("Expand");

QSizePolicy policy;
policy.transpose();
policy.setVerticalPolicy(QSizePolicy::Expanding);

button->setSizePolicy(policy);

この例では、ボタンの幅はウィンドウの幅に合わせ、高さが最大限に拡張されます。

  • この関数は、ウィジェットのサイズヒントを考慮しません。ウィジェットのサイズヒントを変更する必要がある場合は、setSizeHint() 関数を使用する必要があります。
  • この関数は、ウィジェットのレイアウトマネージャーが Qt::LayoutSizePolicy_Control 以外のサイズポリシー制御タイプを使用している場合にのみ機能します。


例 1: ボタンのサイズポリシーをExpandingに設定し、ウィンドウ全体に広げる

#include <QtWidgets/QApplication>
#include <QtWidgets/QPushButton>

int main(int argc, char *argv[]) {
  QApplication app(argc, argv);

  QPushButton *button = new QPushButton("Expand");

  QSizePolicy policy;
  policy.transpose();
  policy.setVerticalPolicy(QSizePolicy::Expanding);

  button->setSizePolicy(policy);

  button->show();

  return app.exec();
}

このコードを実行すると、以下のウィンドウが表示されます。

ボタンはウィンドウの幅に合わせ、高さが最大限に拡張されます。

例 2: スクロールバー付きのリストウィジェットを作成する

#include <QtWidgets/QApplication>
#include <QtWidgets/QListWidget>
#include <QtWidgets/QScrollBar>

int main(int argc, char *argv[]) {
  QApplication app(argc, argv);

  QListWidget *listWidget = new QListWidget;

  for (int i = 0; i < 100; ++i) {
    listWidget->addItem(QString("Item %1").arg(i));
  }

  QSizePolicy policy;
  policy.setHorizontalPolicy(QSizePolicy::Expanding);
  policy.setVerticalPolicy(QSizePolicy::Minimum);

  listWidget->setSizePolicy(policy);

  QScrollBar *verticalScrollBar = new QScrollBar(Qt::Orientation::Vertical);
  verticalScrollBar->setRange(0, listWidget->count() - 1);

  QHBoxLayout *layout = new QHBoxLayout;
  layout->addWidget(listWidget);
  layout->addWidget(verticalScrollBar);

  QWidget *widget = new QWidget;
  widget->setLayout(layout);

  widget->show();

  return app.exec();
}

リストウィジェットはウィンドウの幅に合わせ、高さが最小限に設定されます。垂直スクロールバーを使用して、リストウィジェット内のアイテムをスクロールすることができます。

例 3: グリッドレイアウトを使用したウィジェットの配置

#include <QtWidgets/QApplication>
#include <QtWidgets/QLabel>
#include <QtWidgets/QLineEdit>
#include <QtWidgets/QGridLayout>

int main(int argc, char *argv[]) {
  QApplication app(argc, argv);

  QLabel *label1 = new QLabel("Label 1:");
  QLabel *label2 = new QLabel("Label 2:");

  QLineEdit *lineEdit1 = new QLineEdit;
  QLineEdit *lineEdit2 = new QLineEdit;

  QGridLayout *layout = new QGridLayout;
  layout->addWidget(label1, 0, 0);
  layout->addWidget(lineEdit1, 0, 1);
  layout->addWidget(label2, 1, 0);
  layout->addWidget(lineEdit2, 1, 1);

  QSizePolicy policy;
  policy.setHorizontalPolicy(QSizePolicy::Expanding);
  policy.setVerticalPolicy(QSizePolicy::Minimum);

  lineEdit1->setSizePolicy(policy);
  lineEdit2->setSizePolicy(policy);

  QWidget *widget = new QWidget;
  widget->setLayout(layout);

  widget->show();

  return app.exec();
}

ラベルとテキスト入力フィールドは、グリッドレイアウトを使用してウィンドウ内に配置されています。テキスト入力フィールドは、グリッドレイアウトの幅に合わせ、高さが最小限に設定されます。



QSizePolicy::setFixedHeight() と QSizePolicy::setFixedWidth() を使用する

QSizePolicy policy;
policy.setFixedHeight(sizeHint().height());
policy.setFixedWidth(sizeHint().width());
widget->setSizePolicy(policy);

この方法は、ウィジェットのサイズヒントに基づいて固定された高さと幅を設定します。これは、QSizePolicy::transpose() と同じ効果を達成する簡単な方法ですが、ウィジェットがレイアウト内に収まらない場合に問題が発生する可能性があります。

QSizePolicy::ControlSizePolicy を使用する

QSizePolicy policy;
policy.setHorizontalPolicy(QSizePolicy::ControlSizePolicy);
policy.setVerticalPolicy(QSizePolicy::ControlSizePolicy);
widget->setSizePolicy(policy);

この方法は、ウィジェットのサイズをレイアウトマネージャーが完全に制御するように設定します。これは、ウィジェットが常にレイアウト内に収まるようにするのに役立ちますが、ウィジェットのサイズを制限する他のポリシーと競合する可能性があります。

カスタムレイアウトマネージャーを使用する

class MyLayout : public QLayout {
public:
  QSize sizeHint() const override {
    return QSize(widget->sizeHint().width(), widget->sizeHint().height());
  }

  void minimumSize(QSize *minimumSize) override {
    minimumSize->setWidth(widget->sizeHint().width());
    minimumSize->setHeight(widget->sizeHint().height());
  }

  void maximumSize(QSize *maximumSize) override {
    maximumSize->setWidth(QWIDGETSIZE_MAX);
    maximumSize->setHeight(QWIDGETSIZE_MAX);
  }

  void resizeLayout() override {
    widget->resize(sizeHint());
  }

private:
  QWidget *widget;
};
MyLayout *layout = new MyLayout;
layout->addWidget(widget);
widget->setLayout(layout);

この方法は、より複雑ですが、ウィジェットのサイズとレイアウトを完全に制御することができます。

  • ウィジェットのサイズとレイアウトを完全に制御する必要がある場合は、カスタムレイアウトマネージャーを使用する必要があります。
  • ウィジェットが常にレイアウト内に収まるようにする必要がある場合は、QSizePolicy::ControlSizePolicy を使用する方が簡単です。
  • ウィジェットのサイズを固定する必要がある場合は、QSizePolicy::setFixedHeight()QSizePolicy::setFixedWidth() を使用する方が簡単です。
  • sizeHint() メソッドをオーバーライドして、ウィジェットのサイズヒントをカスタムロジックに基づいて計算することもできます。
  • minimumSizeHint()maximumSizeHint() メソッドを使用して、ウィジェットの最小サイズと最大サイズをヒントすることもできます。