我正在使用基于 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())
尝试将重新定位连接到来自
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):
...