QTableWidget初始化需先调用setRowCount()和setColumnCount()设定行列数,否则为0×0;列标题用setHorizontalHeaderLabels()设置,内容通过setItem(row,col,new QTableWidgetItem("text"))写入,禁用列宽调整用setSectionResizeMode(QHeaderView::Fixed),点击信号优先连cellClicked()以捕获所有格子点击,大数据量时应改用QTableView+QAbstractTableModel。

QTableWidget 初始化和基础设置
直接 new 一个 QTableWidget 后,必须显式设置行列数,否则它默认是 0 行 0 列——界面看起来是空的,但不是“没画出来”,而是真没数据也没格子。
- 用
setRowCount()和setColumnCount()先定尺寸,别依赖后续插入自动扩容(它不会) - 列标题用
setHorizontalHeaderLabels(),传QStringList,顺序对应列索引;不设的话表头显示数字(0, 1, 2…),但单元格仍可写 - 如果想禁用用户调整列宽,对水平表头调用
setSectionResizeMode(QHeaderView::Fixed),否则拖动后columnWidth()可能和初始值不一致
往单元格里塞内容:setText 还是 setItem?
setText() 不是 QTableWidget 的方法,这是常见误写。真正写文本必须用 setItem(),且必须传 QTableWidgetItem* 对象。
- 直接写:
table->setItem(row, col, new QTableWidgetItem("hello")) - 不能只写字符串,也不能用
setText("xxx")—— 那是QTableWidgetItem的方法,不是表格控件的 - 如果只是临时显示、不需要响应点击/选中/编辑,可以用
setCellWidget()塞QLabel或QPushButton,但注意:这类 widget 不参与表格的排序、选中逻辑
选中行为和信号怎么连才不丢事件
itemClicked() 和 cellClicked() 看起来差不多,但触发条件不同:前者只在单元格有 QTableWidgetItem 时触发;后者只要点到格子就发,哪怕该格子是空的或塞了 widget。
- 要捕获所有点击,优先连
cellClicked(int row, int column) - 如果连了
itemSelectionChanged(),注意它会在多选、Ctrl+点击、Shift+点击等任意选区变化时触发,不是单次点击——容易重复处理 - 获取当前选中项用
currentItem(),但它可能返回nullptr(比如点了空格子又没 item),务必判空
性能差?大表格卡顿的几个硬伤点
超过 500 行 × 20 列还用 QTableWidget,基本等于自己埋雷。它的每个 QTableWidgetItem 都是独立对象,内存和绘制开销线性增长。
- 避免在循环里反复调用
setItem():先构造好所有QTableWidgetItem指针数组,再批量塞入,比边建边塞快 3–5 倍 - 关掉重绘优化:
setUpdatesEnabled(false)开始前,填完再开回来;否则每设一个 item 都触发一次局部刷新 - 真要撑万级数据,换
QTableView+ 自定义QAbstractTableModel,QTableWidget的封装便利性这时全变成负担
表格控件看着简单,但行列表头状态、item 生命周期、选中模型三者耦合得很紧,稍不注意就会出现点击无响应、内容不刷新、内存泄漏(忘了 delete item)之类的问题。尤其当你要支持右键菜单、跨行合并、实时过滤时,底层逻辑比表面看到的复杂得多。











