QTableWidget水平滚动时如何重新定位自定义QHeaderview

问题描述 投票:0回答:1

我正在使用基于 QHeaderView 的自定义标题来创建跨多列的列标签。列标签本身就是 QLabel 对象。调整列大小时,我可以正确调整列标签的大小。但是,尚不清楚当表格水平滚动时如何重新定位标签。目前,自定义标题标签保持不变。下面是一个工作示例:

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())
pyqt5 pyside2 qtablewidget pyside6 qheaderview
1个回答
0
投票

尝试将重新定位连接到来自

horizontalScrollBar().valueChanged
QTableWidget

信号
...
class CustomHeader(QHeaderView):
    def __init__(self, orientation, top_text, parent=None):
        super().__init__(orientation, parent)   # Ensuring 'parent' is correctly set
        self.sectionResized.connect(self.handleSectionResized)
        # Connect to the parent table's horizontal scroll bar
        self.parent().horizontalScrollBar().valueChanged.connect(self.adjustPositions)
...

另一个建议是,考虑在初始化期间一次性初始化和设置标签样式,而不是在

showEvent
方法中。

...
class CustomHeader(QHeaderView):
    def __init__(self, orientation, top_text, parent=None):
        super().__init__(orientation, parent)
        self.sectionResized.connect(self.adjustPositions)
        self.parent().horizontalScrollBar().valueChanged.connect(self.adjustPositions)
        self.top_text = top_text
        self.top_labels = list()
        self.setFixedHeight(20)
        self.initLabels()

    def initLabels(self):
        for text, start_col, span in self.top_text:
            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)

    def showEvent(self, event):
        self.adjustPositions()
        super().showEvent(event)

    def adjustPositions(self):
        for i, (text, start_col, span) in enumerate(self.top_text):
            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):
        return sum(self.sectionSize(i) for i in range(index, index + span))


class MyTable(QTableWidget):
    ...
© www.soinside.com 2019 - 2024. All rights reserved.