You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何在QMainWindow中居中显示不拉伸的CentralWidget?

如何在不使用布局和额外Widget的情况下居中QMainWindow的CentralWidget?

我现在要把CentralWidget(棋盘组件)居中,但遇到了麻烦。这个棋盘组件不能被拉伸——一旦拉伸,棋盘格子的绘制就会出问题,最终内容会超出预期。我试过用布局,但布局要求组件填充整个空间才行。想问有没有不用创建额外填充Widget、也不用布局的方法,就能让这个组件居中显示?

原始代码

#include <QWidget>
#include <QPushButton>
#include <QHBoxLayout>
#include <QMainWindow>
#include <QPainterPath>
#include <QPainter>
#include <QScreen>
#include <cmath>

class ChessboardWidget : public QWidget{
public:
    explicit ChessboardWidget(QWidget *parent) : QWidget(parent) {
    }
    void paintEvent(QPaintEvent *event) override{
        this->setPalette(Qt::white);
        this->setAutoFillBackground(true);
        QPainter painter(this);

        bool black = true;
        int tileSize = std::ceil(this->height() / 8.0);
        for(int i = 0; i < 8; i++){
            for(int j = 0; j < 8; j++){
                int y = i * tileSize;
                int x = j * tileSize;
                painter.fillRect(x, y, tileSize, tileSize, black ? Qt::black : Qt::white);
                black = !black;
            }
            black = !black;
        }
    }

    void resizeEvent(QResizeEvent *event) override{
        resize(this->size().height(), this->size().height());

        QWidget::resizeEvent(event);
    }
private:
};

class MainWindow : public QMainWindow {
public:
    MainWindow() {
        auto *window = new QWidget();
        auto *chess = new ChessboardWidget(window);


        setCentralWidget(chess);
        setWindowTitle("Chessboard Example");
        show();
        setSizePolicy(QSizePolicy::Expanding, QSizePolicy::Expanding);
        this->setPalette(Qt::red);
        this->setAutoFillBackground(true);

    }
};


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


    MainWindow window;

    return QApplication::exec();
}

解决方案:手动计算位置并重写resizeEvent

可以通过重写MainWindow的resizeEvent方法,手动计算棋盘组件的居中位置,直接设置其几何属性,完全不需要布局或额外Widget。

修改后的完整代码

#include <QWidget>
#include <QPushButton>
#include <QHBoxLayout>
#include <QMainWindow>
#include <QPainterPath>
#include <QPainter>
#include <QScreen>
#include <cmath>

class ChessboardWidget : public QWidget{
public:
    explicit ChessboardWidget(QWidget *parent) : QWidget(parent) {
    }
    void paintEvent(QPaintEvent *event) override{
        this->setPalette(Qt::white);
        this->setAutoFillBackground(true);
        QPainter painter(this);

        bool black = true;
        int tileSize = std::ceil(this->height() / 8.0);
        for(int i = 0; i < 8; i++){
            for(int j = 0; j < 8; j++){
                int y = i * tileSize;
                int x = j * tileSize;
                painter.fillRect(x, y, tileSize, tileSize, black ? Qt::black : Qt::white);
                black = !black;
            }
            black = !black;
        }
    }

    void resizeEvent(QResizeEvent *event) override{
        resize(this->size().height(), this->size().height());
        QWidget::resizeEvent(event);
    }
private:
};

class MainWindow : public QMainWindow {
private:
    ChessboardWidget *chess; // 保存棋盘组件指针,方便后续调整位置
public:
    MainWindow() {
        chess = new ChessboardWidget(this);
        setCentralWidget(chess);
        setWindowTitle("棋盘示例");
        setSizePolicy(QSizePolicy::Expanding, QSizePolicy::Expanding);
        this->setPalette(Qt::red);
        this->setAutoFillBackground(true);
        show();
    }

    void resizeEvent(QResizeEvent *event) override {
        QMainWindow::resizeEvent(event);
        
        // 获取主窗口可用区域的宽高
        int windowWidth = this->centralWidget()->parentWidget()->width();
        int windowHeight = this->centralWidget()->parentWidget()->height();
        // 棋盘是正方形,直接取其高度作为边长
        int chessSize = chess->height();
        
        // 计算居中的坐标
        int centerX = (windowWidth - chessSize) / 2;
        int centerY = (windowHeight - chessSize) / 2;
        
        // 设置棋盘的位置和大小
        chess->setGeometry(centerX, centerY, chessSize, chessSize);
    }
};


int main(int argc, char *argv[]) {
    QApplication app(argc, argv);
    MainWindow window;
    return QApplication::exec();
}

原理说明

  • 棋盘组件自身的resizeEvent已经保证了它始终是正方形,所以我们只需要获取它的边长
  • 在MainWindow的resizeEvent中,每次窗口大小变化时,重新计算棋盘在主窗口内的居中偏移量
  • 通过setGeometry直接设置棋盘的位置,完全绕开布局系统,不需要任何额外的填充Widget

内容的提问来源于stack exchange,提问作者Азимия

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.25 21:43:14