如何在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,提问作者Азимия
相关产品推荐
相关产品推荐

