1. 窗体尺寸控制的核心逻辑与常见误区
很多刚接触Qt的朋友,第一次写窗口程序时都会遇到一个很别扭的现象:代码里明明写了resize(800, 600),运行出来窗口却只有一丁点大,或者拖拽边缘时窗口被压成一条线,控件全挤在一起。窗体大小设置看起来是最基础的一行代码,实际上它牵扯到布局系统、尺寸策略、屏幕适配、高DPI缩放等一整套机制。我见过不少做了两三年Qt的开发者,遇到窗口尺寸问题还是靠反复试数字来凑,这其实是因为没有把背后的规则理清楚。
这篇文章围绕“Qt中设置窗体大小”这个主题,把我在实际项目里踩过的坑和总结出来的方法完整梳理一遍。内容会覆盖固定尺寸、最小最大尺寸限制、布局联动、多屏适配、高DPI处理、子窗口与主窗口的尺寸关系等场景。不管你是刚学Qt的新手,还是想把手头项目的窗口适配做得更扎实的老手,都能从里面找到可以直接抄作业的代码和参数选择思路。
先说一个最容易被忽略的前提:窗体最终显示多大,不是由你写的某一个函数单独决定的,而是由“你设置的尺寸”和“布局系统计算出的尺寸”以及“窗口管理器的约束”三方博弈的结果。理解这句话,后面很多诡异现象就都能解释了。
1.1 为什么resize之后窗口大小不对
最常见的困惑就是调用了resize()但没生效。原因通常有三类。
第一类是布局的尺寸约束覆盖了你的设置。当窗体上挂了布局(比如QVBoxLayout),布局会根据子控件的sizeHint()和sizePolicy算出一个“推荐尺寸”。如果这个推荐尺寸比你resize的值大,窗口就会被撑大;如果布局设置了setSizeConstraint(QLayout::SetFixedSize),那窗口会被强制锁定成布局算出来的尺寸,你resize多少都没用。
第二类是调用的时机不对。在构造函数里resize通常没问题,但如果你在show()之前又调用了adjustSize()或者添加了会改变布局的控件,之前的resize就被覆盖了。更隐蔽的是在showEvent里做尺寸调整,如果没处理好递归,会出现窗口闪烁或者尺寸反复横跳。
第三类是窗口还没真正创建。某些平台上,窗口句柄要等到show()之后才存在,这时候对尺寸的某些操作会被忽略。稳妥的做法是把尺寸设置放在构造函数里,或者用QTimer::singleShot(0, ...)延迟到事件循环开始后再执行。
// 典型错误:先resize,后面又adjustSize把它覆盖了 MyWidget::MyWidget(QWidget *parent) : QWidget(parent) { resize(800, 600); // ... 添加一堆控件和布局 adjustSize(); // 这一行会把上面的resize覆盖掉 } // 正确做法:明确你的意图,要么用resize固定,要么让布局自己算 MyWidget::MyWidget(QWidget *parent) : QWidget(parent) { // 添加控件和布局 // 如果想让窗口适应内容,用adjustSize,不要先resize // 如果想固定初始尺寸,用resize,不要调adjustSize resize(800, 600); }提示:
adjustSize()和resize()是互斥的意图。前者是“让窗口适应内容”,后者是“让内容适应窗口”。同时用必然有一个被覆盖,想清楚你要哪个。
1.2 尺寸相关的几个关键概念
在动手改代码之前,有几个概念必须先分清楚,否则后面全是糊涂账。
sizeHint:控件或布局“建议”的尺寸。它是一个参考值,不是强制值。比如一个按钮的sizeHint大概是文字宽度加内边距,一个QLineEdit的sizeHint是它能舒适显示若干字符的宽度。
minimumSizeHint:控件能接受的最小尺寸。布局在压缩空间时不会小于这个值。很多控件默认的minimumSizeHint很小,所以窗口可以被拖得很小,导致内容显示不全。
sizePolicy:控件在布局中如何伸缩的策略。水平和垂直方向各有Fixed、Minimum、Maximum、Preferred、Expanding、MinimumExpanding、Ignored等取值。这个策略决定了当窗口变大变小时,控件分到多少额外空间。
minimumSize / maximumSize:硬性约束。设置了之后,窗口管理器就不会让你拖到范围之外。这是控制窗口尺寸最“强硬”的手段。
把这四个概念的关系理清:布局先收集所有子控件的sizeHint和sizePolicy,算出一个推荐尺寸;然后受minimumSize和maximumSize的钳制;最后窗口管理器在这个范围内允许用户拖拽。你调用的resize(),本质上是给这个链条一个初始值。
2. 固定尺寸、限制尺寸与自适应尺寸的实操方案
搞清楚概念之后,具体怎么设置就有章可循了。实际项目里对窗口尺寸的需求无非三种:固定死、给个范围、完全自适应。下面分别说清楚每种场景的写法和注意事项。
2.1 固定窗口尺寸的三种写法
固定尺寸最直接的方式是同时设置最小和最大尺寸相等:
// 写法一:setFixedSize,最简洁 setFixedSize(800, 600); // 写法二:分别设置最小和最大 setMinimumSize(800, 600); setMaximumSize(800, 600); // 写法三:通过布局约束锁定 layout()->setSizeConstraint(QLayout::SetFixedSize);这三种写法有细微差别。setFixedSize内部就是同时设置min和max,效果等价于写法二。写法三则是让布局来锁定,此时窗口尺寸由布局算出的sizeHint决定,你无法通过resize改变它。
什么时候用哪种?如果窗口内容尺寸是已知且固定的(比如一个工具面板),用setFixedSize最省事。如果窗口内容会动态变化但你想锁定当前尺寸,用写法三配合布局更合适。需要注意的是,setFixedSize之后窗口的最大化按钮通常会变灰,这是符合预期的行为。
注意:固定尺寸的窗口在高DPI屏幕上可能显示过小。比如你在1080P屏幕上设了800x600觉得刚好,到了4K屏上如果不做缩放处理,窗口会显得很小。关于高DPI的处理后面单独讲。
2.2 最小最大尺寸限制的合理取值
更多时候我们不需要完全固定,而是给一个合理范围。比如一个文本编辑器,最小不能小于能显示工具栏和几行文字,最大不超过屏幕工作区。
// 设置最小尺寸,保证内容不被压扁 setMinimumSize(400, 300); // 设置最大尺寸,避免窗口大到离谱 setMaximumSize(1600, 1200); // 初始尺寸取中间值 resize(900, 700);取值不是拍脑袋定的。最小尺寸应该由“内容完整显示所需的最小空间”决定。你可以先把窗口拖到很小,看哪些控件开始被截断或重叠,那个临界点往上留一点余量就是最小尺寸。最大尺寸则要考虑目标屏幕的分辨率,通常不超过屏幕工作区的宽高。
这里有个实用技巧:如果想让窗口最大不超过屏幕,可以动态获取屏幕尺寸来设置:
QScreen *screen = QGuiApplication::primaryScreen(); QRect available = screen->availableGeometry(); setMaximumSize(available.width(), available.height());用availableGeometry()而不是geometry(),因为前者排除了任务栏占用的区域,更准确。
2.3 让窗口自适应内容的正确姿势
自适应场景下,你不需要手动设尺寸,而是让布局和控件的sizeHint来决定。核心是调好每个控件的sizePolicy,然后调用adjustSize()。
// 添加控件和布局 QVBoxLayout *layout = new QVBoxLayout(this); layout->addWidget(new QLabel("用户名")); layout->addWidget(new QLineEdit); layout->addWidget(new QPushButton("确定")); // 让窗口根据内容调整到合适大小 adjustSize();但adjustSize()有个坑:它只调用一次,之后内容变化窗口不会跟着变。如果内容会动态增减,需要在内容变化后重新调用,或者依赖布局的自动更新机制。
更优雅的方式是设置布局的尺寸约束为SetMinimumSize,这样窗口最小不会小于内容所需,但用户可以自由放大:
layout->setSizeConstraint(QLayout::SetMinimumSize);这个约束的含义是:窗口的最小尺寸跟随布局的sizeHint,用户不能把窗口拖到内容显示不全的程度,但可以放大。这在很多工具类窗口里是很实用的默认行为。
3. 布局系统与窗体尺寸的联动机制
布局是Qt界面开发的核心,也是窗体尺寸问题的重灾区。很多人把布局当成“自动排列控件”的工具,忽略了它同时也在控制窗口尺寸。这一章把布局和尺寸的关系讲透。
3.1 sizeHint与sizePolicy如何影响窗口
每个控件都有sizeHint()和sizePolicy()。布局在计算时,会先问每个子控件“你想要多大”(sizeHint),再问“你能怎么伸缩”(sizePolicy),然后综合算出整个布局的推荐尺寸。
sizePolicy的取值对窗口尺寸影响很大。举个例子,两个控件放在水平布局里:
- 控件A的sizePolicy是
Fixed,sizeHint宽度100 - 控件B的sizePolicy是
Expanding,sizeHint宽度50
当窗口宽度是200时,A占100,B占100(B把多出来的50吃掉了)。当窗口宽度是300时,A还是100,B变成200。这就是Expanding的作用——它会尽可能占据额外空间。
理解这个机制后,控制窗口尺寸就有了抓手。如果你希望某个区域随窗口伸缩,给它设Expanding;如果希望它保持固定,设Fixed。窗口整体的sizeHint就是所有控件按策略组合后的结果。
// 让文本编辑区占据所有额外空间 QTextEdit *editor = new QTextEdit; editor->setSizePolicy(QSizePolicy::Expanding, QSizePolicy::Expanding); // 让按钮保持固定大小 QPushButton *btn = new QPushButton("发送"); btn->setSizePolicy(QSizePolicy::Fixed, QSizePolicy::Fixed);3.2 布局边距与间距对尺寸的隐性影响
布局的contentsMargins和spacing会直接加到窗口尺寸上,这一点经常被忽略。一个默认的布局,四周边距各9像素,控件间距6像素。如果你有5个控件垂直排列,光间距就占了24像素,加上下边距18像素,总共42像素的“额外”高度。
// 查看和调整布局边距 layout->setContentsMargins(10, 10, 10, 10); // 左、上、右、下 layout->setSpacing(8); // 控件之间的间距 // 如果想让窗口更紧凑,可以把边距和间距调小 layout->setContentsMargins(4, 4, 4, 4); layout->setSpacing(4);在做紧凑型工具窗口时,把这些值调小能明显减小窗口的推荐尺寸。反过来,如果你发现窗口比预期的大了一圈,先检查布局的边距和间距,往往就是它们在“偷偷”占空间。
实操心得:调试窗口尺寸时,可以临时给布局设置一个显眼的背景色,或者用Qt Designer的布局边界显示功能,把边距和间距可视化,一眼就能看出空间被谁占了。
3.3 嵌套布局下的尺寸传递
复杂界面通常是嵌套布局:主布局里套子布局,子布局里再套。尺寸计算是自底向上的——最内层控件的sizeHint先算出来,逐层往外传递,最后得到顶层窗口的推荐尺寸。
嵌套层数多了之后,尺寸会“膨胀”。因为每一层布局都会加上自己的边距和间距。三层嵌套,每层边距9像素,光边距就累计了27像素。所以做复杂界面时,要有意识地控制嵌套深度,能用一层布局解决的就不要套两层。
// 不推荐:过度嵌套 QVBoxLayout *outer = new QVBoxLayout(this); QHBoxLayout *row1 = new QHBoxLayout; QVBoxLayout *col1 = new QVBoxLayout; col1->addWidget(w1); col1->addWidget(w2); row1->addLayout(col1); outer->addLayout(row1); // 推荐:用QGridLayout减少嵌套 QGridLayout *grid = new QGridLayout(this); grid->addWidget(w1, 0, 0); grid->addWidget(w2, 1, 0);QGridLayout和QFormLayout能在不增加嵌套的情况下实现复杂排列,是控制窗口尺寸的好帮手。特别是QFormLayout,做设置面板时既整齐又不会让尺寸失控。
4. 多屏幕与高DPI场景下的尺寸适配
前面讲的都是单屏幕、标准DPI的情况。一旦涉及多显示器或者高分辨率屏,窗体尺寸就又是另一回事了。这一章的内容在实际项目中非常关键,但很多教程都一笔带过。
4.1 获取屏幕可用区域并居中显示
窗口居中是个常见需求,但“居中”要基于哪块屏幕、哪个区域,需要明确。多屏环境下,主屏和副屏的可用区域不同,窗口应该居中到它所在的那块屏幕。
// 获取窗口当前所在的屏幕 QScreen *screen = windowHandle()->screen(); if (!screen) { screen = QGuiApplication::primaryScreen(); } // 获取可用区域(排除任务栏) QRect available = screen->availableGeometry(); // 计算居中位置 int x = available.x() + (available.width() - width()) / 2; int y = available.y() + (available.height() - height()) / 2; move(x, y);注意availableGeometry()返回的是全局坐标,包含了屏幕在虚拟桌面中的偏移。多屏时副屏的x可能是1920或负数,直接用这个坐标move才能正确落到目标屏幕上。
如果窗口还没show,windowHandle()可能返回空,这时候用QGuiApplication::screenAt(QCursor::pos())根据鼠标位置判断屏幕更稳妥。
4.2 高DPI缩放下的尺寸陷阱
高DPI屏幕(比如4K屏)上,系统会做缩放,Qt默认会跟随系统缩放。这意味着你写的resize(800, 600),在150%缩放下,实际物理像素是1200x900,但逻辑尺寸还是800x600。这本身是好事,保证了界面元素在不同屏幕上视觉大小一致。
但陷阱在于:如果你用像素值硬编码尺寸,在高DPI下可能不合适。比如你从某个图片资源读到的尺寸是物理像素,直接拿来设窗口大小,在缩放屏幕上就会偏小。
处理方式是尽量用逻辑像素(Qt默认的坐标系统就是逻辑像素),需要物理像素时用devicePixelRatio()换算:
qreal dpr = screen->devicePixelRatio(); // 物理像素转逻辑像素 int logicalWidth = physicalWidth / dpr; resize(logicalWidth, logicalHeight);另外,如果项目需要禁用高DPI缩放(比如某些老项目的兼容需求),可以在main函数里设置属性,但这通常不推荐,因为会导致界面在高分屏上过小。
4.3 窗口跨屏拖动时的尺寸变化处理
窗口从一块屏幕拖到另一块不同缩放的屏幕时,尺寸会发生变化。Qt会自动处理大部分情况,但如果你的代码里缓存了尺寸值,就可能出现不一致。
稳妥的做法是监听屏幕变化事件,在screenChanged信号里重新计算需要的尺寸:
connect(windowHandle(), &QWindow::screenChanged, this, [this](QScreen *screen) { // 屏幕变了,根据新屏幕的可用区域重新约束尺寸 QRect available = screen->availableGeometry(); if (width() > available.width()) { resize(available.width(), height()); } if (height() > available.height()) { resize(width(), available.height()); } });这个处理能避免窗口拖到小屏上时超出屏幕边界,导致部分内容看不到。
5. 常见问题排查与实战避坑清单
理论讲完了,这一章全是实战中真金白银换来的经验。我把这些年遇到的窗口尺寸问题整理成排查清单,遇到问题按图索骥即可。
5.1 窗口尺寸不生效的排查顺序
遇到resize不生效,按这个顺序排查,基本能定位到原因:
| 排查项 | 检查方法 | 常见问题 |
|---|---|---|
| 布局约束 | 检查是否调用了setSizeConstraint(SetFixedSize) | 布局锁死了尺寸 |
| 调用时机 | 确认resize在show之前且之后没有adjustSize | 被后续调用覆盖 |
| 最小最大限制 | 打印minimumSize和maximumSize | 设置的范围与resize冲突 |
| 父窗口约束 | 检查父窗口布局是否限制了子窗口 | 子窗口被父布局压缩 |
| 屏幕限制 | 确认目标尺寸不超过屏幕可用区域 | 超出部分被裁剪 |
排查时最有效的手段是加日志,把每一步之后的size()、minimumSize()、maximumSize()都打出来,看是哪一步发生了变化。
qDebug() << "before resize:" << size(); resize(800, 600); qDebug() << "after resize:" << size(); qDebug() << "min:" << minimumSize() << "max:" << maximumSize();5.2 窗口闪烁与尺寸抖动的解决
有时候窗口显示时会闪烁,或者尺寸在几个值之间抖动。这通常是尺寸计算出现了循环依赖:A的变化触发B重算,B的重算又触发A变化。
典型场景是在resizeEvent里根据当前尺寸调整子控件,而子控件的调整又反过来影响父窗口尺寸。解决办法是加一个标志位防止重入:
void MyWidget::resizeEvent(QResizeEvent *event) { if (m_adjusting) return; m_adjusting = true; // 根据新尺寸调整子控件 // ... m_adjusting = false; QWidget::resizeEvent(event); }另一个常见原因是布局在计算时反复触发updateGeometry。如果自定义控件的sizeHint实现里有耗时操作或者返回值不稳定,就会导致抖动。确保sizeHint是纯函数,每次返回相同的值。
5.3 子窗口与主窗口的尺寸协调
子窗口(对话框、浮动面板)的尺寸和主窗口的关系需要明确。如果子窗口是主窗口的附属,通常希望它不要超出主窗口范围,或者至少不要跑到屏幕外。
// 让子窗口尺寸不超过主窗口 void ChildDialog::showEvent(QShowEvent *event) { QWidget *main = parentWidget(); if (main) { int maxW = qMin(main->width(), 800); int maxH = qMin(main->height(), 600); resize(qMin(width(), maxW), qMin(height(), maxH)); } QDialog::showEvent(event); }但要注意,子窗口如果设置了Qt::Tool或Qt::Popup标志,行为会不同。工具窗口通常不占用任务栏,尺寸约束也更宽松。根据实际需求选择合适的窗口标志。
避坑技巧:对话框用
exec()模态显示时,尺寸在showEvent里调整是有效的;但用show()非模态时,某些平台上showEvent的时机可能偏晚,建议在构造完成后、show之前就设好尺寸。
5.4 保存与恢复窗口尺寸的最佳实践
很多应用需要记住用户上次调整的窗口大小,下次启动时恢复。这个功能看似简单,但有几个细节要注意。
用QSettings保存尺寸是标准做法:
// 保存 QSettings settings("MyCompany", "MyApp"); settings.setValue("window/size", size()); settings.setValue("window/position", pos()); // 恢复 QSize savedSize = settings.value("window/size", QSize(800, 600)).toSize(); QPoint savedPos = settings.value("window/position", QPoint(-1, -1)).toPoint(); // 校验尺寸是否合理(防止上次在4K屏保存的尺寸在小屏上超出) QScreen *screen = QGuiApplication::primaryScreen(); QRect available = screen->availableGeometry(); savedSize.setWidth(qMin(savedSize.width(), available.width())); savedSize.setHeight(qMin(savedSize.height(), available.height())); resize(savedSize); // 校验位置是否在屏幕内 if (available.contains(savedPos)) { move(savedPos); } else { // 位置无效,居中显示 move(available.center() - rect().center()); }关键点是恢复时要校验。用户可能上次在扩展屏上使用,这次只插了一个屏,保存的位置就在屏幕外了。不校验的话窗口会“消失”,用户以为程序坏了。尺寸同理,要钳制到当前屏幕可用范围内。
另外,保存时机建议在closeEvent里,而不是析构函数里,因为析构时窗口可能已经不可用了。
void MainWindow::closeEvent(QCloseEvent *event) { QSettings settings("MyCompany", "MyApp"); settings.setValue("window/size", size()); settings.setValue("window/position", pos()); QMainWindow::closeEvent(event); }这套保存恢复逻辑我在多个项目里用过,配合校验之后基本没再收到“窗口不见了”的反馈。特别是多屏用户,这个校验能省掉很多支持成本。
6. 不同窗口类型下的尺寸设置差异
Qt里的窗口类型不止一种,主窗口、对话框、工具窗口、无边框窗口,它们在尺寸设置上各有各的脾气。这一章把常见窗口类型的尺寸处理要点过一遍。
6.1 QMainWindow的尺寸控制要点
QMainWindow有菜单栏、工具栏、状态栏、中央控件、停靠窗口等区域,尺寸计算比普通QWidget复杂。它的sizeHint是所有这些区域的总和。
控制QMainWindow尺寸时,中央控件是主导因素。如果中央控件设了Expanding策略,主窗口就会倾向于变大。工具栏和状态栏的高度是固定的,会加到总高度上。
QMainWindow *win = new QMainWindow; win->setCentralWidget(centralWidget); win->resize(1024, 768); // 如果希望主窗口最小尺寸由中央控件决定 win->centralWidget()->setMinimumSize(400, 300);有个细节:QMainWindow的resize在构造函数里调用时,如果还没设置中央控件,尺寸可能不准。建议先设置好所有区域,最后再resize。
6.2 对话框的尺寸自适应策略
对话框通常希望“刚好容纳内容”,不要太大也不要太小。用布局加adjustSize是标准做法,但要注意对话框的sizeConstraint。
QDialog *dlg = new QDialog; QVBoxLayout *layout = new QVBoxLayout(dlg); // ... 添加控件 layout->setSizeConstraint(QLayout::SetFixedSize); // 对话框固定为内容大小设成SetFixedSize后,对话框不能调整大小,适合那些内容固定的提示框、关于框。如果内容可能变化(比如错误信息长度不定),用SetMinimumSize更合适,允许用户拉大查看。
对于输入类对话框,通常给一个合理的初始尺寸,并允许调整:
dlg->resize(500, 400); dlg->setMinimumSize(300, 200);6.3 无边框窗口的尺寸拖拽实现
无边框窗口(Qt::FramelessWindowHint)没有系统提供的边框,用户无法直接拖拽调整大小,需要自己实现。这涉及到鼠标事件处理和边缘检测。
void FramelessWidget::mousePressEvent(QMouseEvent *event) { m_dragPos = event->globalPos(); m_oldGeometry = geometry(); // 判断鼠标是否在边缘区域 m_edge = edgeAt(event->pos()); } void FramelessWidget::mouseMoveEvent(QMouseEvent *event) { if (m_edge == NoEdge) return; QPoint delta = event->globalPos() - m_dragPos; QRect geo = m_oldGeometry; if (m_edge & LeftEdge) { geo.setLeft(geo.left() + delta.x()); } if (m_edge & RightEdge) { geo.setRight(geo.right() + delta.x()); } if (m_edge & TopEdge) { geo.setTop(geo.top() + delta.y()); } if (m_edge & BottomEdge) { geo.setBottom(geo.bottom() + delta.y()); } // 应用最小尺寸约束 if (geo.width() >= minimumWidth() && geo.height() >= minimumHeight()) { setGeometry(geo); } }边缘检测的阈值一般取5到8像素,太窄用户不好点,太宽容易误触。实现时要注意在mouseMoveEvent里根据鼠标位置切换光标形状(Qt::SizeHorCursor等),给用户反馈。
无边框窗口的尺寸拖拽是个细致活,建议把边缘检测和几何计算封装成独立函数,方便复用和调试。另外要处理鼠标离开窗口时的状态重置,否则光标可能卡在调整形状上。
7. 尺寸设置的性能考量与调试手段
最后聊聊性能和调试。窗口尺寸设置本身开销很小,但在复杂界面里,尺寸变化会触发大量重绘和重新布局,处理不当会有卡顿。
7.1 减少尺寸变化引发的重绘
每次窗口尺寸变化,Qt会重新计算布局、重绘受影响的区域。如果界面复杂,这个过程可能耗时。优化思路是减少不必要的尺寸变化和重绘。
一个实用手段是在批量修改控件时先禁用更新,改完再启用:
setUpdatesEnabled(false); // 批量修改控件属性、添加删除控件 setUpdatesEnabled(true);另一个是避免在resizeEvent里做重活。resizeEvent触发频繁,里面如果有复杂计算或IO操作,会明显拖慢窗口拖拽。把重活挪到定时器或者空闲处理里。
7.2 用调试工具观察尺寸计算过程
Qt Creator自带的对象查看器能看到运行时的控件树和尺寸信息。调试尺寸问题时,可以在这里查看每个控件的geometry、sizeHint、sizePolicy,非常直观。
另外,环境变量QT_LOGGING_RULES可以打开布局相关的日志:
QT_LOGGING_RULES="qt.layouts=true" ./myapp打开后控制台会输出布局计算的详细过程,包括每个控件的sizeHint和最终分配到的尺寸。排查“为什么这个控件这么小”之类的问题时特别有用。
如果这些还不够,可以在自定义控件的sizeHint和resizeEvent里加日志,观察调用顺序和返回值。尺寸问题的本质是“谁在什么时候决定了什么值”,把调用链打出来,问题就无处遁形了。
7.3 尺寸相关代码的组织建议
最后给一个代码组织上的建议。窗口尺寸的设置逻辑最好集中管理,不要散落在各个地方。我通常会在窗口类里写一个setupGeometry()函数,把所有尺寸相关的设置放进去:
void MainWindow::setupGeometry() { // 初始尺寸 resize(1024, 768); // 最小尺寸 setMinimumSize(640, 480); // 最大尺寸不超过屏幕 QScreen *screen = QGuiApplication::primaryScreen(); QRect available = screen->availableGeometry(); setMaximumSize(available.size()); // 居中 move(available.center() - rect().center()); }在构造函数末尾调用一次,需要恢复用户设置时再单独处理。这样尺寸逻辑清晰可查,后续维护或者换人接手都不会抓瞎。尺寸问题最怕的就是设置散落各处,A处设了又被B处覆盖,排查起来像破案。集中管理能从源头上避免这类问题。
这套方法我在多个桌面项目里实践下来,窗口尺寸相关的bug率明显下降。尤其是配合前面说的保存恢复校验,用户端的体验会稳定很多。