How to reposition custom QHeaderview when QTableWidget is scrolled horizontally

42 views Asked by At

I am using a custom header based on QHeaderView to create column labels that span multiple columns. The column labels are themselves QLabel objects. I can correctly resize the column labels when a column is resized. However, it is unclear how to reposition the labels when the table is horizontally scrolled. Currently the custom header labels remain stationary. Below is a working example:

import sys
from PyQt5.QtCore import *
from PyQt5.QtGui import *
from PyQt5.QtWidgets import *
COL_LEN = 4

class CustomHeader(QHeaderView):
    def __init__(self, orientation, top_text, parent=None):
        QHeaderView.__init__(self, orientation, parent=None)
        self.sectionResized.connect(self.handleSectionResized)
        self.top_text = top_text
        self.top_labels = list()
        self.setFixedHeight(20)

    def handleSectionResized(self, i):
        # print('Resizing') 
        self.adjustPositions()


    def showEvent(self, event):
        ncol = self.count()
        ntop = len(self.top_text)
        for i in range(ntop):
            text, start_col, span = self.top_text[i]
            print(self.top_text[i])
            label = QLabel(text, self) 
            label.setStyleSheet("font-weight:bold;background-color: gray;border-right: 1px solid white;")
            label.setAlignment(Qt.AlignCenter)
            self.top_labels.append(label)
            label.show()
        self.adjustPositions()
        return super().showEvent(event)

        
    def adjustPositions(self):
        ntop = len(self.top_text)
        for i in range(ntop):
            text, start_col, span = self.top_text[i]
            label = self.top_labels[i]
            span_size = self.getSpanSize(start_col, span)
            geom = QRect(
                self.sectionViewportPosition(start_col),
                0, #place at top
                span_size, 
                self.height(),
            )
            label.setGeometry(geom)

    def getSpanSize(self, index, span):
        span_size = 0
        for i in range(index, index+span):
            span_size += self.sectionSize(i)
        return span_size


class MyTable(QTableWidget):

    def __init__(self, nrow, child_list, symbol, parent=None):
        nchild = len(child_list)
        ncol = (COL_LEN+1)*nchild + 1
        super().__init__(nrow, ncol, parent=parent)
        top_labels = self.create_label_info(symbol, child_list)
        self.verticalHeader().hide()
        self.setHorizontalHeaderLabels([''] * self.columnCount()) #uncomment to see column headers moving correctly
        self.header = CustomHeader(Qt.Horizontal, top_labels, self)
        self.setHorizontalHeader(self.header)

    def create_label_info(self, symbol, child_list):
        top_labels = list()
        top_labels.append((symbol, 0,1))
        n = 2
        for e in child_list :
            top_labels.append((e, n, COL_LEN))
            n += COL_LEN + 1
        return top_labels
    

class DebugWindow(QMainWindow):

    def __init__(self):
        super(DebugWindow, self).__init__()
        self.table = MyTable(10,  ['Child 1', 'Child 2'], 'Class') 
        layout = QVBoxLayout()
        layout.addWidget(self.table)
        widget = QWidget()
        widget.setLayout(layout)
        self.setCentralWidget(widget)
        self.show()


if __name__ == '__main__':
    app = QApplication(sys.argv)
    window = DebugWindow()
    window.show()
    sys.exit(app.exec())
0

There are 0 answers