QT中如何让QVBoxLayout居中同时使ScrollArea正常工作?
QVBoxLayout居中同时QScrollArea正常工作实现方案
问题场景
刚学习QT,需要同时实现两个需求:
- QVBoxLayout保持窗口居中
- QScrollArea正常滚动
按照网上方案将ScrollArea内部改为放置widget后,滚动功能恢复,但布局不再居中;直接在ScrollArea内放布局时,布局居中但滚动失效。
原代码(对应滚动失效、布局居中)
#include "mainwindow.h" #include "ui_mainwindow.h" #include <QMainWindow> #include <QPushButton> #include <QApplication> #include <QHBoxLayout> #include <QVBoxLayout> #include <QScrollArea> #include <QObject> #include <QLabel> #include <QLineEdit> MainWindow::MainWindow(QWidget *parent) : QMainWindow(parent) , ui(new Ui::MainWindow) { ui->setupUi(this); QScrollArea *scrollArea = new QScrollArea(); QVBoxLayout *innerVerticalLayout = new QVBoxLayout; QVBoxLayout *verticalLayout = new QVBoxLayout; verticalLayout->setAlignment(Qt::AlignTop); QWidget *verticalLayoutWidgetContainer = new QWidget(); verticalLayoutWidgetContainer->setLayout(verticalLayout); verticalLayoutWidgetContainer->setFixedWidth(1000); QHBoxLayout *horizontalLayout = new QHBoxLayout; horizontalLayout->setAlignment(Qt::AlignTop); QPushButton *leftButton = new QPushButton("Left Button"); leftButton->setFixedWidth(100); QPushButton *rightButton = new QPushButton("Right Button"); rightButton->setFixedWidth(100); horizontalLayout->addWidget(leftButton, 0, Qt::AlignLeft); horizontalLayout->addWidget(rightButton, 0, Qt::AlignRight); QHBoxLayout *horizontalLayout1 = new QHBoxLayout; horizontalLayout1->setAlignment(Qt::AlignTop); QPushButton *centerButton = new QPushButton("Center Button"); centerButton->setFixedWidth(100); horizontalLayout1->addWidget(centerButton, 0, Qt::AlignHCenter); QHBoxLayout *horizontalLayout2 = new QHBoxLayout; horizontalLayout2->setAlignment(Qt::AlignTop); QPushButton *rightButton1 = new QPushButton("Right Button"); rightButton1->setFixedWidth(100); horizontalLayout2->addWidget(rightButton1, 0, Qt::AlignRight); verticalLayout->addLayout(horizontalLayout, 0); verticalLayout->addLayout(horizontalLayout1, 0); verticalLayout->addLayout(horizontalLayout2, 0); innerVerticalLayout->addWidget(verticalLayoutWidgetContainer, 0, Qt::AlignHCenter | Qt::AlignTop); scrollArea->setLayout(innerVerticalLayout); this->setCentralWidget(scrollArea); } MainWindow::~MainWindow() { delete ui; }
两种效果对比
- 效果1:直接给ScrollArea设置布局,滚动区域失效,但固定宽度的布局保持居中
- 效果2:修改为ScrollArea内放置widget(代码修改如下),滚动正常,但布局不再居中
- scrollArea->setLayout(innerVerticalLayout); + QWidget *innerVerticalLayoutWidgetContainer = new QWidget(); + innerVerticalLayoutWidgetContainer->setLayout(innerVerticalLayout); + scrollArea->setWidget(innerVerticalLayoutWidgetContainer);
解决方案
要同时实现居中与滚动,只需在效果2的代码基础上添加两个关键设置:
- 让ScrollArea允许内部widget调整大小
- 确保内部容器widget的水平大小策略自适应,从而让固定宽度的子布局保持居中
修改后的完整代码
#include "mainwindow.h" #include "ui_mainwindow.h" #include <QMainWindow> #include <QPushButton> #include <QApplication> #include <QSizePolicy> #include <QHBoxLayout> #include <QVBoxLayout> #include <QScrollArea> #include <QObject> #include <QLabel> #include <QLineEdit> MainWindow::MainWindow(QWidget *parent) : QMainWindow(parent) , ui(new Ui::MainWindow) { ui->setupUi(this); QScrollArea *scrollArea = new QScrollArea(); QVBoxLayout *innerVerticalLayout = new QVBoxLayout; QVBoxLayout *verticalLayout = new QVBoxLayout; verticalLayout->setAlignment(Qt::AlignTop); QWidget *verticalLayoutWidgetContainer = new QWidget(); verticalLayoutWidgetContainer->setLayout(verticalLayout); verticalLayoutWidgetContainer->setFixedWidth(1000); QHBoxLayout *horizontalLayout = new QHBoxLayout; horizontalLayout->setAlignment(Qt::AlignTop); QPushButton *leftButton = new QPushButton("Left Button"); leftButton->setFixedWidth(100); QPushButton *rightButton = new QPushButton("Right Button"); rightButton->setFixedWidth(100); horizontalLayout->addWidget(leftButton, 0, Qt::AlignLeft); horizontalLayout->addWidget(rightButton, 0, Qt::AlignRight); QHBoxLayout *horizontalLayout1 = new QHBoxLayout; horizontalLayout1->setAlignment(Qt::AlignTop); QPushButton *centerButton = new QPushButton("Center Button"); centerButton->setFixedWidth(100); horizontalLayout1->addWidget(centerButton, 0, Qt::AlignHCenter); QHBoxLayout *horizontalLayout2 = new QHBoxLayout; horizontalLayout2->setAlignment(Qt::AlignTop); QPushButton *rightButton1 = new QPushButton("Right Button"); rightButton1->setFixedWidth(100); horizontalLayout2->addWidget(rightButton1, 0, Qt::AlignRight); verticalLayout->addLayout(horizontalLayout, 0); verticalLayout->addLayout(horizontalLayout1, 0); verticalLayout->addLayout(horizontalLayout2, 0); innerVerticalLayout->addWidget(verticalLayoutWidgetContainer, 0, Qt::AlignHCenter | Qt::AlignTop); // 关键修改部分 QWidget *innerVerticalLayoutWidgetContainer = new QWidget(); innerVerticalLayoutWidgetContainer->setLayout(innerVerticalLayout); // 设置容器widget水平自适应,不固定宽度 innerVerticalLayoutWidgetContainer->setSizePolicy(QSizePolicy::Preferred, QSizePolicy::Preferred); // 让ScrollArea允许内部widget调整大小,保证滚动正常 scrollArea->setWidgetResizable(true); scrollArea->setWidget(innerVerticalLayoutWidgetContainer); this->setCentralWidget(scrollArea); } MainWindow::~MainWindow() { delete ui; }
核心原理
scrollArea->setWidgetResizable(true):让ScrollArea根据内部内容和自身窗口大小自动调整widget尺寸,确保滚动条在内容超出时正常显示innerVerticalLayoutWidgetContainer->setSizePolicy(QSizePolicy::Preferred, QSizePolicy::Preferred):让内部容器widget的宽度自适应ScrollArea的宽度,从而使固定宽度的verticalLayoutWidgetContainer在innerVerticalLayout的AlignHCenter设置下保持居中
内容的提问来源于stack exchange,提问作者Victor
相关产品推荐
相关产品推荐

