QWidget::setFixedSize()

2025-05-16

このメソッドを使用すると、ウィジェットの最小サイズ最大サイズの両方が指定したサイズに設定されます。これにより、そのウィジェットは、ユーザーによるリサイズやレイアウトによる調整によって、指定したサイズから拡大したり縮小したりすることができなくなります。

  • コンテンツに応じた固定サイズ
    ウィジェットのコンテンツ(例えばテキスト)に基づいて固定サイズにしたい場合は、QLayout::setSizeConstraint(QLayout::SetFixedSize) を使用するという別の方法もあります。これは、ウィジェットの内容に基づいて最適なサイズに設定し、その後そのサイズを固定します。
  • 制約の解除
    固定されたサイズ制約を解除したい場合は、setFixedSize(QWIDGETSIZE_MAX, QWIDGETSIZE_MAX) を呼び出すか、setMaximumSize()setMinimumSize() を個別に設定することで、制約を解除できます。
  • デザインの一貫性
    特定のウィジェットに常に同じサイズを保持させたい場合に便利です。例えば、ボタンやアイコンなど、視覚的に一貫性を持たせたい要素に適用されます。
  • レイアウトの制約を上書きする
    Qtのレイアウトシステムは、ウィジェットのサイズを自動的に調整しようとしますが、setFixedSize() を使用すると、そのレイアウトの制約よりも優先され、ウィジェットは指定された固定サイズを維持します。
  • サイズを固定する
    setFixedSize(const QSize &s) メソッドに QSize オブジェクトを渡すことで、ウィジェットの幅と高さをピクセル単位で指定します。例えば、widget->setFixedSize(200, 100); とすると、そのウィジェットの幅は200ピクセル、高さは100ピクセルに固定されます。


setFixedSize()を設定してもリサイズできてしまう

これは最もよくある問題です。いくつかの原因が考えられます。

原因とトラブルシューティング

  • トップレベルウィジェット(ウィンドウ)の場合

    • 原因
      QMainWindowQDialogのようなトップレベルのウィンドウにsetFixedSize()を設定した場合、オペレーティングシステムやウィンドウマネージャーがそのサイズを完全に尊重しない場合があります。特に、最大化ボタンやリサイズハンドルが表示されたままになることがあります。
    • トラブルシューティング
      • setWindowFlags()を使用する
        • setWindowFlags(Qt::MSWindowsFixedSizeDialogHint) (Windows向け) や setWindowFlags(Qt::Dialog | Qt::MSWindowsFixedSizeDialogHint) (Windows向け) を使用すると、ウィンドウに固定サイズのヒントを与え、リサイズ機能を無効にできる場合があります。ただし、これはOSやQtのバージョンによって挙動が異なることがあります。
        • setWindowFlags(Qt::WindowStaysOnTopHint | Qt::FramelessWindowHint) など、他のフラグとの組み合わせによっては予期せぬ副作用(例えば、閉じるボタンが機能しなくなるなど)が発生する可能性があります。
      • show()より前に設定する
        setWindowFlags()を呼び出す順番が重要になることがあります。通常、show()メソッドを呼び出す前に設定するのが推奨されます。
      • QSizeGripなどのウィジェットが使われていないか確認する
        ウィンドウの角にQSizeGripなどのリサイズハンドルが配置されている場合、それがリサイズを許可してしまいます。
    • 原因
      setFixedSize()は個々のウィジェットのサイズを固定しますが、そのウィジェットがレイアウト(QVBoxLayoutQHBoxLayoutQGridLayoutなど)に追加されている場合、レイアウトがウィジェットのサイズを上書きしようとすることがあります。特に、QSizePolicyExpandingなどに設定されているウィジェットは、レイアウト内でサイズを広げようとします。
    • トラブルシューティング
      • レイアウトのサイズ制約を設定する
        親ウィジェットが持っているレイアウトに対して、layout->setSizeConstraint(QLayout::SetFixedSize); を設定します。これにより、レイアウト自体がそのコンテンツの合計サイズに固定され、内部のウィジェットがリサイズされなくなります。これは、特にQMainWindowQDialogなどのトップレベルウィジェットに対して有効です。
      • setSizePolicy()を調整する
        setFixedSize()を使用するウィジェットのsizePolicyQSizePolicy::Fixedに設定することを検討します。これにより、そのウィジェットは推奨サイズ(sizeHint()またはsetFixedSize()で設定されたサイズ)を厳守するようになります。
      • setMinimumSize()とsetMaximumSize()を個別に設定する
        setFixedSize(w, h)は実質的に setMinimumSize(w, h)setMaximumSize(w, h) を呼び出すのと同じです。しかし、他のコードでこれらのメソッドが後から呼び出されて上書きされていないか確認してください。

setFixedSize()を設定すると閉じるボタンが機能しない

Stack Overflowなどで報告されている、比較的稀なケースですが、Windows環境のQt5でQMainWindowsetFixedSize()を適用すると、ウィンドウの閉じるボタンが動作しなくなり、代わりにウィンドウをドラッグする機能になるというバグが報告されています。

原因とトラブルシューティング

  • トラブルシューティング
    • Qtのバージョンを更新する
      最新のQtバージョンに更新することで、この問題が解決する可能性があります。
    • 代替手段を検討する
      • setMinimumSize()setMaximumSize()を同じ値に設定する。
      • layout()->setSizeConstraint(QLayout::SetFixedSize); を使用する。
      • setWindowFlags()を注意深く使用する(上記参照)。
  • Qtのバージョンによるバグ
    特定のQtバージョン(特にQt5の初期バージョン)とOSの組み合わせで発生する可能性があります。

setFixedSize()が適用される前にウィジェットが一度リサイズされてしまう

ウィジェットが最初に表示される際に、一瞬だけ異なるサイズで表示された後、固定サイズに調整されることがあります。

原因とトラブルシューティング

  • トラブルシューティング
    • コンストラクタで設定する
      可能な限り、ウィジェットのコンストラクタ内でsetFixedSize()を呼び出すことで、初期表示から正しいサイズになるよう試みます。
    • adjustSize()やupdateGeometry()との組み合わせ
      レイアウトの変更などがあった後、明示的にadjustSize()updateGeometry()を呼び出すことで、レイアウト計算を強制し、setFixedSize()が正しく適用されるように促すことができます。
  • 初期化のタイミング
    レイアウト計算や表示処理のタイミングによっては、setFixedSize()が完全に適用される前に、一時的にデフォルトやレイアウトが計算したサイズが適用されることがあります。

sizeHint()やminimumSizeHint()との兼ね合い

setFixedSize()sizeHint()(推奨サイズ)とminimumSizeHint()(最小推奨サイズ)を無視するわけではありませんが、最終的なサイズ決定において最も優先されます。

原因とトラブルシューティング

  • トラブルシューティング
    • setFixedSize()を使用する場合、通常はsizeHint()minimumSizeHint()を意識する必要はありません。しかし、それらが設定されていることが原因で問題が発生している場合は、一時的にそれらをコメントアウトして動作を確認してみると良いでしょう。
  • コンフリクト
    カスタムウィジェットでsizeHint()minimumSizeHint()をオーバーライドしている場合、setFixedSize()との間で意図しないコンフリクトが発生する可能性があります。
  • シンプルなコードで再現する
    複雑なアプリケーションの一部で問題が発生した場合、最小限のコードでその現象を再現する試みをします。これにより、問題の原因特定が容易になります。
  • 親ウィジェットの影響を分離する
    問題のウィジェットを、一時的にレイアウトから外し、単独でsetFixedSize()を適用して動作を確認します。これにより、問題がそのウィジェット自身にあるのか、親のレイアウトや他のウィジェットとの相互作用によるものなのかを切り分けられます。
  • Qt Designerで確認する
    Qt DesignerでGUIを設計している場合、ウィジェットのminimumSizemaximumSizesizePolicyプロパティがどのように設定されているかを確認します。
  • qDebug()でサイズを確認する
    ウィジェットのsize()minimumSize()maximumSize()sizeHint()などをqDebug()で出力し、期待通りの値が設定されているか、そして表示時のサイズがどうなっているかを確認します。


例1:単一のウィジェットのサイズを固定する

この例では、QPushButtonのサイズを固定します。

#include <QApplication>
#include <QPushButton>

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

    // QPushButtonのインスタンスを作成
    QPushButton *button = new QPushButton("固定サイズのボタン");

    // ボタンのサイズを200x50ピクセルに固定
    button->setFixedSize(200, 50);

    // ボタンを表示
    button->show();

    return app.exec();
}

解説
button->setFixedSize(200, 50); の行が、ボタンの幅を200ピクセル、高さを50ピクセルに設定し、それ以上もそれ以下もリサイズできないように固定します。

例2:トップレベルウィンドウのサイズを固定する(レイアウトを使用)

この例では、メインウィンドウ(QMainWindow)のサイズを固定します。レイアウトを使用している場合、setFixedSize()をトップレベルウィジェットに適用するだけでなく、そのレイアウトのサイズ制約も設定することが重要です。

#include <QApplication>
#include <QMainWindow>
#include <QPushButton>
#include <QVBoxLayout>
#include <QWidget>

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

    // メインウィンドウを作成
    QMainWindow *mainWindow = new QMainWindow();
    mainWindow->setWindowTitle("固定サイズのウィンドウ");

    // 中央ウィジェットとレイアウトを作成
    QWidget *centralWidget = new QWidget();
    QVBoxLayout *layout = new QVBoxLayout(centralWidget);

    // 固定サイズのボタンを追加
    QPushButton *button1 = new QPushButton("ボタン 1 (固定)");
    button1->setFixedSize(150, 40); // ボタン1のサイズを固定

    QPushButton *button2 = new QPushButton("ボタン 2 (固定)");
    button2->setFixedSize(150, 40); // ボタン2のサイズを固定

    layout->addWidget(button1);
    layout->addWidget(button2);
    layout->addStretch(); // ボタンが中央に寄るようにストレッチを追加

    // レイアウトのサイズ制約をSetFixedSizeに設定
    // これにより、レイアウトはコンテンツの推奨サイズに固定される
    layout->setSizeConstraint(QLayout::SetFixedSize);

    // 中央ウィジェットをメインウィンドウに設定
    mainWindow->setCentralWidget(centralWidget);

    // メインウィンドウのサイズも固定
    // レイアウトの制約と合わせて、ウィンドウ全体が固定サイズになる
    // QLayout::SetFixedSizeを設定することで、以下の行は省略できる場合もあるが、
    // 明示的に指定することで意図が明確になる
    mainWindow->setFixedSize(200, 200); // ウィンドウの最終的なサイズを固定

    mainWindow->show();

    return app.exec();
}

解説

  • mainWindow->setFixedSize(200, 200);: メインウィンドウ自体のサイズも固定します。レイアウトの制約と合わせることで、意図通りの固定サイズウィンドウが作成されます。この例では、レイアウトの計算結果と一致するように適当な値を設定しています。
  • layout->setSizeConstraint(QLayout::SetFixedSize);: これが非常に重要です。レイアウトが、その内部のウィジェットの推奨サイズ(この場合は固定サイズ)に基づいて自身のサイズを計算し、そのサイズを固定するように指示します。これにより、ウィンドウがリサイズされるのを防ぎます。
  • button1->setFixedSize(150, 40);: 各ボタンのサイズを固定しています。
  • QVBoxLayout *layout = new QVBoxLayout(centralWidget);: 中央ウィジェットに垂直レイアウトを設定します。

例3:特定のコンテキストでの固定サイズ(QDialogの場合)

QDialogは通常、ユーザーがリサイズできるものですが、setFixedSize()を使用することで、固定サイズのダイアログを作成できます。

#include <QApplication>
#include <QDialog>
#include <QLabel>
#include <QVBoxLayout>
#include <QPushButton>

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

    // QDialogのインスタンスを作成
    QDialog *dialog = new QDialog();
    dialog->setWindowTitle("固定サイズのダイアログ");

    QVBoxLayout *layout = new QVBoxLayout(dialog); // ダイアログに直接レイアウトを設定

    QLabel *label = new QLabel("このダイアログはリサイズできません。");
    label->setAlignment(Qt::AlignCenter); // テキストを中央寄せ

    QPushButton *closeButton = new QPushButton("閉じる");
    QObject::connect(closeButton, &QPushButton::clicked, dialog, &QDialog::accept);

    layout->addWidget(label);
    layout->addWidget(closeButton);

    // ダイアログのサイズを固定
    dialog->setFixedSize(300, 150);

    // 必要に応じて、レイアウトのサイズ制約も設定することで、
    // 内部コンテンツのサイズに合わせてダイアログのサイズが決定されるようにできる
    // ただし、この例ではdialog->setFixedSize()が優先される
    // layout->setSizeConstraint(QLayout::SetFixedSize);

    dialog->show();

    return app.exec();
}

解説
dialog->setFixedSize(300, 150); により、ダイアログウィンドウが指定されたサイズに固定され、ユーザーはこれをリサイズできなくなります。ダイアログは通常、決まった目的で使われるため、固定サイズにすることがよくあります。

setFixedSize(w, h)は、内部的にはsetMinimumSize(w, h)setMaximumSize(w, h)を同時に呼び出しているのと等価です。このことを理解するための例です。

#include <QApplication>
#include <QWidget>
#include <QLabel>
#include <QVBoxLayout>

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

    QWidget *window = new QWidget();
    window->setWindowTitle("Min/Maxで固定");

    QVBoxLayout *layout = new QVBoxLayout(window);
    QLabel *label = new QLabel("このウィンドウは幅250、高さ100に固定されます。");
    label->setAlignment(Qt::AlignCenter);
    layout->addWidget(label);

    // setFixedSize(250, 100) と同じ効果
    window->setMinimumSize(250, 100);
    window->setMaximumSize(250, 100);

    window->show();

    return app.exec();
}

解説
このコードは、setFixedSize(250, 100); を呼び出すのと全く同じ効果をもたらします。もし、一時的に固定を解除したい場合など、柔軟性を持たせたい場合に、これらのメソッドを個別に操作することもできます。例えば、setMaximumSize(QWIDGETSIZE_MAX, QWIDGETSIZE_MAX); とすることで、最大サイズ制約を解除し、リサイズ可能にすることができます。



setMinimumSize() と setMaximumSize() の組み合わせ

setFixedSize(width, height) は、内部的には setMinimumSize(width, height)setMaximumSize(width, height) を同時に呼び出すのと等価です。

用途

  • 将来的に片方のサイズ制約だけを変更する可能性がある場合(例:最小サイズは固定しつつ、最大サイズは無制限にするなど)。
  • setFixedSize() と全く同じ効果を得たいが、コードの可読性を高めたい場合。

コード例

```cpp #include <QApplication> #include <QPushButton>

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

QPushButton *button = new QPushButton("Min/Maxで固定されたボタン");
button->setMinimumSize(180, 45); // 最小サイズを設定
button->setMaximumSize(180, 45); // 最大サイズを設定 (最小と同じ値で固定)
button->show();

return app.exec();

}


### 2\. `QSizePolicy` を使用する

`QSizePolicy` は、ウィジェットがレイアウト内でどのように振る舞うかを定義する非常に強力なメカニズムです。`QSizePolicy::Fixed` を使用することで、ウィジェットのサイズを`sizeHint()`(推奨サイズ)に基づいて固定できます。

**`QSizePolicy::Fixed` の特徴:**

  * **`sizeHint()` に基づく:** ウィジェットの推奨サイズ (`sizeHint()`) が最終的な固定サイズとなります。カスタムウィジェットを作成している場合、`sizeHint()` を適切にオーバーライドすることで、そのウィジェットが自然に固定サイズとして扱われるようになります。
  * **レイアウトとの連携:** レイアウトは `QSizePolicy` を考慮してウィジェットを配置します。`Fixed`ポリシーのウィジェットは、推奨サイズから拡大・縮小されません。

**用途:**

  * カスタムウィジェットのデフォルトのサイズポリシーとして、そのウィジェットが常に同じサイズであることを意図する場合。
  * レイアウト内の特定のウィジェットが、その内容に基づいて固定サイズであるべき場合。
  * `setFixedSize()` よりも「レイアウトのヒント」としての意味合いが強い。

**コード例:**

```cpp
#include <QApplication>
#include <QPushButton>
#include <QHBoxLayout>
#include <QWidget>
#include <QLabel>

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

    QWidget *window = new QWidget();
    QHBoxLayout *layout = new QHBoxLayout(window);

    QLabel *label = new QLabel("固定サイズのラベル:");
    QPushButton *button = new QPushButton("固定");

    // ラベルのサイズポリシーをFixedに設定
    // QLabelのsizeHint()に基づいてサイズが決定される
    label->setSizePolicy(QSizePolicy::Fixed, QSizePolicy::Fixed);

    // ボタンのサイズポリシーをFixedに設定
    button->setSizePolicy(QSizePolicy::Fixed, QSizePolicy::Fixed);

    // これらのウィジェットは、それぞれのsizeHint() (またはsetFixedSize()で明示的に設定されたサイズ) に基づいて
    // 固定サイズとしてレイアウトに配置される
    layout->addWidget(label);
    layout->addWidget(button);

    // レイアウト全体のサイズ制約も考慮する(任意だが、ウィンドウ全体を固定したい場合に有効)
    layout->setSizeConstraint(QLayout::SetFixedSize);

    window->setWindowTitle("QSizePolicy::Fixed の例");
    window->show();

    return app.exec();
}
  • QSizePolicy::Ignored: sizeHint()を無視し、可能な限り多くのスペースを取ろうとする。
  • QSizePolicy::MinimumExpanding: sizeHint()が最小サイズだが、利用可能な余分なスペースをできるだけ活用しようとする。
  • QSizePolicy::Expanding: sizeHint()は妥当なサイズだが、利用可能な余分なスペースをできるだけ活用しようとする。
  • QSizePolicy::Preferred (デフォルト): sizeHint()が最適サイズであり、ある程度の拡大・縮小が可能。
  • QSizePolicy::Maximum: sizeHint()が最大サイズであり、そこから縮小は可能だが拡大はできない。
  • QSizePolicy::Minimum: sizeHint()が最小サイズであり、そこから拡大は可能だが縮小はできない。
  • QSizePolicy::Fixed: sizeHint()が唯一の許容サイズであり、ウィジェットは拡大も縮小もしない。

レイアウトのサイズ制約 (QLayout::setSizeConstraint())

この方法は、特にトップレベルのウィンドウ(QMainWindowQDialogなど)や、コンテンツ全体が固定サイズであるべきコンテナウィジェットに非常に有効です。

QLayout::SetFixedSize の特徴

  • ウィンドウをリサイズしても、その内容のサイズは変わらず、ウィンドウ全体がコンテンツに合わせて固定されます。
  • これにより、個々のウィジェットにsetFixedSize()を呼び出す手間を省き、レイアウトがコンテンツの変化に応じて自動的にサイズを調整し、その後そのサイズを固定します。
  • レイアウトに、その中に含まれる全ウィジェットのsizeHint()の合計に基づいて自身のサイズを計算し、そのサイズを固定するように指示します。

用途

  • レイアウト内のコンテンツが動的に変化し、その都度ウィンドウサイズを固定したい場合。
  • ダイアログウィンドウなど、内容に基づいてサイズが自動的に決まり、かつリサイズさせたくない場合に最適。

コード例

#include <QApplication>
#include <QDialog>
#include <QLabel>
#include <QPushButton>
#include <QVBoxLayout>

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

    QDialog *dialog = new QDialog();
    dialog->setWindowTitle("レイアウトで固定されたダイアログ");

    QVBoxLayout *layout = new QVBoxLayout(dialog); // ダイアログに直接レイアウトを設定

    QLabel *label = new QLabel("このダイアログは内容に合わせてサイズが固定されます。");
    label->setAlignment(Qt::AlignCenter);

    QPushButton *okButton = new QPushButton("OK");
    QObject::connect(okButton, &QPushButton::clicked, dialog, &QDialog::accept);

    layout->addWidget(label);
    layout->addWidget(okButton);

    // ★重要: レイアウトのサイズ制約をFixedに設定
    layout->setSizeConstraint(QLayout::SetFixedSize);

    // ダイアログ自体にsetFixedSize()を明示的に呼び出す必要はない
    // layout->setFixedSize() は存在しない

    dialog->show();

    return app.exec();
}

解説
layout->setSizeConstraint(QLayout::SetFixedSize); がキーです。これにより、ダイアログのサイズは、内部のラベルとボタンの推奨サイズ(sizeHint())に基づいて自動的に計算され、そのサイズに固定されます。ユーザーはダイアログをリサイズできなくなります。

setFixedSize()は幅と高さの両方を固定しますが、setFixedWidth()setFixedHeight()を使用すると、片方の次元のみを固定し、もう片方は柔軟に保つことができます。

用途

  • あるいは、ツールバーのように高さは固定だが、幅はウィンドウ全体に広げたい場合。
  • 例えば、横幅は固定したいが、高さはコンテンツの量に応じて可変にしたい場合。
#include <QApplication>
#include <QWidget>
#include <QLabel>
#include <QVBoxLayout>

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

    QWidget *window = new QWidget();
    window->setWindowTitle("幅のみ固定のウィンドウ");

    QVBoxLayout *layout = new QVBoxLayout(window);
    QLabel *label1 = new QLabel("このラベルは幅が固定されていますが、テキスト量に応じて高さは変わります。");
    label1->setWordWrap(true); // テキストを折り返す設定
    
    // ラベルの幅を固定
    label1->setFixedWidth(200); 

    QLabel *label2 = new QLabel("これは別のラベルです。");
    
    layout->addWidget(label1);
    layout->addWidget(label2);
    layout->addStretch(); // 上にコンテンツを寄せる

    window->show();

    return app.exec();
}