Qt QTableView调整高度适配内容时如何消除底部多余空白
问题:消除QTableView最后一行下方的空白区域

当前该表格水平尺寸策略为Expanding,垂直尺寸策略为Minimum,其余表格的双向尺寸策略均设为Expanding。
我参考了相关方案实现了如下方法,但调整效果并不完美:
void verticalResizeTableViewToContents(QTableView* tableView) { tableView->resizeRowsToContents(); // does it work ? tableView->setSizeAdjustPolicy(QAbstractScrollArea::AdjustToContents); int rowTotalHeight = 0; // Rows height int count = tableView->verticalHeader()->count(); for (int i = 0; i < count; ++i) { // 2018-03 edit: only account for row if it is visible if (!tableView->verticalHeader()->isSectionHidden(i)) { rowTotalHeight += tableView->verticalHeader()->sectionSize(i); } } // Check for scrollbar visibility if (!tableView->horizontalScrollBar()->isHidden()) { rowTotalHeight += tableView->horizontalScrollBar()->height(); } // Check for header visibility if (!tableView->horizontalHeader()->isHidden()) { rowTotalHeight += tableView->horizontalHeader()->height(); } tableView->setMaximumHeight(rowTotalHeight); }
我使用如下代码配置其中一个表格:
m_Internals->Ui.Measures->setModel(mm->getPh66MeasuresModel()); m_Internals->Ui.Measures->horizontalHeader()->setSectionsMovable(true); m_Internals->Ui.Measures->horizontalHeader()->setHighlightSections(false); m_Internals->Ui.Measures->horizontalHeader()->setSectionResizeMode(QHeaderView::Interactive); m_Internals->Ui.Measures->horizontalHeader()->setStretchLastSection(true); m_Internals->Ui.Measures->verticalHeader()->hide(); m_Internals->Ui.Measures->setSelectionBehavior(QAbstractItemView::SelectRows); verticalResizeTableViewToContents(m_Internals->Ui.Measures);
我采用Qt ModelView模式来填充和更新表格数据。
更新
经测试,使用Qt官方安装器安装的版本(5.12.11)时不存在该问题,但使用vcpkg提供的旧版Qt库时该问题可复现,两个版本的运行效果如下:
- vcpkg提供的Qt版本运行截图:

- Qt官方提供的5.12.11版本运行截图:

请问该问题的诱因是什么,如何适配不同Qt版本解决该问题?
问题诱因
该问题是旧版Qt的QTableView边距计算逻辑缺陷导致的:部分旧版本Qt的QAbstractScrollArea会默认预留滚动区域的上下边距,你现有的计算逻辑漏加了QTableView视口(viewport)的上下content margin值,不同Qt版本对默认margin的赋值规则不同,就出现了版本间表现不一致的问题。vcpkg提供的旧版Qt没有合并Qt官方在5.12分支后期提交的QTableView边距计算修复补丁,所以会多出来一截空白。
适配方案
修改verticalResizeTableViewToContents函数,补全边距计算逻辑,即可兼容新旧版本:
void verticalResizeTableViewToContents(QTableView* tableView) { tableView->resizeRowsToContents(); tableView->setSizeAdjustPolicy(QAbstractScrollArea::AdjustToContents); int rowTotalHeight = 0; int count = tableView->verticalHeader()->count(); for (int i = 0; i < count; ++i) { if (!tableView->verticalHeader()->isSectionHidden(i)) { rowTotalHeight += tableView->verticalHeader()->sectionSize(i); } } // 强制设置视口边距为0,消除版本差异导致的默认边距 tableView->setViewportMargins(0, 0, 0, 0); if (!tableView->horizontalScrollBar()->isHidden()) { rowTotalHeight += tableView->horizontalScrollBar()->height(); } if (!tableView->horizontalHeader()->isHidden()) { rowTotalHeight += tableView->horizontalHeader()->height(); } // 增加2px容错值,避免不同Qt版本的边框计算误差 tableView->setMaximumHeight(rowTotalHeight + 2); // 同步更新最小高度,匹配你设置的Minimum尺寸策略 tableView->setMinimumHeight(rowTotalHeight + 2); }
另外需要在表格数据更新(model的dataChanged、rowsInserted、rowsRemoved信号触发)时重新调用一次该函数,保证尺寸动态适配内容变化。如果想要进一步规避样式影响,可以为该QTableView添加如下样式表:
QTableView { padding: 0px; }
内容的提问来源于stack exchange,提问作者Aminos
相关产品推荐
相关产品推荐

