You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何实现QTableWidget表头随滚动条滚动而非固定显示?

在PySide6中实现QTableWidget表头随滚动条同步滚动

默认情况下,QTableWidget的水平和垂直表头会固定显示,不会随滚动条滚动。如果想要让表头随内容一起滚动,不再始终保持可见,可通过以下方式实现。

当前效果

当前效果示意图

期望效果

期望效果示意图

原始示例代码

import string
import random
from typing import Optional

from PySide6.QtCore import Qt
from PySide6.QtWidgets import QTableWidget, QWidget, QAbstractItemView, QHeaderView, QTableWidgetItem, QHBoxLayout, \
    QApplication


class DataTable(QTableWidget):

    def __init__(self, parent: Optional[QWidget] = None):
        super(DataTable, self).__init__(parent)

        self.setContextMenuPolicy(Qt.CustomContextMenu)
        self.setSelectionBehavior(QAbstractItemView.SelectItems)
        self.setHorizontalScrollMode(QAbstractItemView.ScrollPerPixel)

        self.horizontalHeader().setSectionResizeMode(QHeaderView.Stretch)
        self.horizontalHeader().setTextElideMode(Qt.ElideMiddle)

        for j in range(20):
            if self.columnCount() <= j:
                self.insertColumn(j)
            for i in range(20):
                if self.rowCount() <= i:
                    self.insertRow(i)
                self.setItem(i, j, QTableWidgetItem('Hello'))

        word = ''.join(random.choice(string.ascii_letters) for _ in range(6))
        self.setHorizontalHeaderLabels([str(word) for i in range(self.columnCount())])
        self.setVerticalHeaderLabels([str(word) for i in range(self.rowCount())])


if __name__ == '__main__':
    app = QApplication()

    widget = QWidget()
    widget.resize(400, 600)
    layout = QHBoxLayout(widget)
    layout.addWidget(DataTable())
    widget.show()

    app.exec()

实现方案

核心思路是将表头的父控件改为表格的视口,并同步表头与内容区域的滚动动作:

1. 修改表头父控件

在DataTable的__init__方法中,将水平和垂直表头的父对象设置为表格的视口,让表头成为视口的子控件,从而随视口滚动:

# 将水平表头父控件设为视口
self.horizontalHeader().setParent(self.viewport())
# 将垂直表头父控件设为视口
self.verticalHeader().setParent(self.viewport())

2. 同步滚动动作

重写scrollContentsBy方法,在内容滚动时同步表头的滚动偏移量:

def scrollContentsBy(self, dx: int, dy: int) -> None:
    super().scrollContentsBy(dx, dy)
    # 同步水平表头滚动
    self.horizontalHeader().scroll(dx, 0)
    # 同步垂直表头滚动
    self.verticalHeader().scroll(0, dy)

完整修改后的代码

import string
import random
from typing import Optional

from PySide6.QtCore import Qt
from PySide6.QtWidgets import QTableWidget, QWidget, QAbstractItemView, QHeaderView, QTableWidgetItem, QHBoxLayout, \
    QApplication


class DataTable(QTableWidget):

    def __init__(self, parent: Optional[QWidget] = None):
        super(DataTable, self).__init__(parent)

        self.setContextMenuPolicy(Qt.CustomContextMenu)
        self.setSelectionBehavior(QAbstractItemView.SelectItems)
        self.setHorizontalScrollMode(QAbstractItemView.ScrollPerPixel)

        self.horizontalHeader().setSectionResizeMode(QHeaderView.Stretch)
        self.horizontalHeader().setTextElideMode(Qt.ElideMiddle)

        # 修改表头父控件为视口
        self.horizontalHeader().setParent(self.viewport())
        self.verticalHeader().setParent(self.viewport())

        for j in range(20):
            if self.columnCount() <= j:
                self.insertColumn(j)
            for i in range(20):
                if self.rowCount() <= i:
                    self.insertRow(i)
                self.setItem(i, j, QTableWidgetItem('Hello'))

        word = ''.join(random.choice(string.ascii_letters) for _ in range(6))
        self.setHorizontalHeaderLabels([str(word) for i in range(self.columnCount())])
        self.setVerticalHeaderLabels([str(word) for i in range(self.rowCount())])

    def scrollContentsBy(self, dx: int, dy: int) -> None:
        super().scrollContentsBy(dx, dy)
        # 同步表头滚动偏移量
        self.horizontalHeader().scroll(dx, 0)
        self.verticalHeader().scroll(0, dy)


if __name__ == '__main__':
    app = QApplication()

    widget = QWidget()
    widget.resize(400, 600)
    layout = QHBoxLayout(widget)
    layout.addWidget(DataTable())
    widget.show()

    app.exec()

原理说明

  • QTableWidget默认将表头放在自身容器下,而非视口内,因此表头不会随视口滚动;修改父控件为视口后,表头会随视口的滚动而移动。
  • 重写scrollContentsBy方法,确保内容滚动时表头的滚动偏移量与内容完全一致,实现同步滚动效果。

内容的提问来源于stack exchange,提问作者laurapons

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.18 17:35:19