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

如何为QTableWidget的列设置多级表头?

How to Add Multi-Level Headers to QTableWidget

If you need a two-level header structure for your QTableWidget (with "Failed" and "Undefined" as top-level headers covering your existing four columns), here's a straightforward way to implement it:

Approach Overview

Since Qt's default QHeaderView doesn't natively support spanning sections for multi-level headers, we'll create a custom header bar widget that sits above the table, then hide the original horizontal header. This keeps things simple and avoids complex subclassing.

Step-by-Step Implementation (PyQt5/PySide2)

1. Set Up the Basic QTableWidget

First, create your table with the 4 columns and original headers:

from PyQt5.QtWidgets import (QApplication, QTableWidget, QTableWidgetItem,
                             QWidget, QHBoxLayout, QLabel, QVBoxLayout, QSizePolicy, QHeaderView)
import sys

app = QApplication(sys.argv)

# Create main window widget
main_widget = QWidget()
main_layout = QVBoxLayout(main_widget)

# Create table with 4 columns
table = QTableWidget()
table.setColumnCount(4)
original_headers = ["Failed DIPS", "Failed Outputs", "Extra DIPS", "Extra Outputs"]
table.setHorizontalHeaderLabels(original_headers)

# Optional: Add some sample data
table.setRowCount(3)
for row in range(3):
    for col in range(4):
        table.setItem(row, col, QTableWidgetItem(f"Row {row}, Col {col}"))

2. Create the Top-Level Header Bar

Next, build a horizontal layout to hold the two top-level headers, each spanning two columns:

# Create top header widget
top_header_widget = QWidget()
top_header_layout = QHBoxLayout(top_header_widget)
top_header_layout.setContentsMargins(0,0,0,0)
top_header_layout.setSpacing(0)

# Style the header labels to match Qt's default header look
header_style = """
    QLabel {
        background-color: #f0f0f0;
        border: 1px solid #cccccc;
        padding: 4px;
        font-weight: bold;
        text-align: center;
    }
"""

# Add "Failed" header (covers columns 0 and 1)
failed_header = QLabel("Failed")
failed_header.setStyleSheet(header_style)
# Make it stretch to fit two columns' width
failed_header.setSizePolicy(QSizePolicy.Expanding, QSizePolicy.Fixed)
top_header_layout.addWidget(failed_header)

# Add "Undefined" header (covers columns 2 and 3)
undefined_header = QLabel("Undefined")
undefined_header.setStyleSheet(header_style)
undefined_header.setSizePolicy(QSizePolicy.Expanding, QSizePolicy.Fixed)
top_header_layout.addWidget(undefined_header)

3. Combine Everything and Hide Original Header

Add the top header and table to the main layout, then hide the original horizontal header:

# Add top header and table to main layout
main_layout.addWidget(top_header_widget)
main_layout.addWidget(table)

# Hide the original horizontal header (since we have our custom top header)
table.horizontalHeader().setVisible(False)

# Adjust table column widths to match top header sections
table.horizontalHeader().setSectionResizeMode(QHeaderView.Stretch)

main_widget.show()
sys.exit(app.exec_())

Alternative: Subclass QHeaderView (for Tighter Integration)

If you want the multi-level headers to be part of the table's native header (instead of a separate widget), you can subclass QHeaderView to draw the top-level sections. Here's a quick snippet:

from PyQt5.QtGui import QPainter, QPen
from PyQt5.QtCore import Qt

class MultiLevelHeader(QHeaderView):
    def __init__(self, parent=None):
        super().__init__(Qt.Horizontal, parent)
        self.top_level_headers = [("Failed", 0,1), ("Undefined",2,3)]

    def paintSection(self, painter, rect, logicalIndex):
        # Draw original section first
        super().paintSection(painter, rect, logicalIndex)
        
        # Draw top-level headers if we're in the first section of a group
        for header_text, start_col, end_col in self.top_level_headers:
            if logicalIndex == start_col:
                # Calculate the total width of the group
                group_width = 0
                for col in range(start_col, end_col+1):
                    group_width += self.sectionSize(col)
                # Draw the top header
                painter.save()
                painter.setPen(QPen(Qt.gray))
                painter.setBrush(Qt.lightGray)
                painter.drawRect(rect.x(), 0, group_width, 20)
                painter.setPen(QPen(Qt.black))
                painter.drawText(rect.x(), 0, group_width, 20, Qt.AlignCenter, header_text)
                painter.restore()

# Usage:
table.horizontalHeader().setVisible(True)
table.setHorizontalHeader(MultiLevelHeader(table))
# Adjust header height to fit both levels
table.horizontalHeader().setMinimumHeight(40)

Key Notes

  • The widget-based approach is simpler and works well for most cases, especially if you don't need interactive top-level headers.
  • The subclassed QHeaderView approach integrates more tightly with the table, allowing for features like sorting while keeping the multi-level headers visible.
  • Tweak the styles and sizes to match your application's design system.

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.22 08:04:04