need to add subscript to horizontal header of QTableWidget with QLabel where html will be the text of the QLabel.
You have to create QLabels whose parent is the QHeaderView and update what is displayed and its geometry when necessary:
from PyQt5 import QtCore, QtGui, QtWidgets
class HeaderProxyStyle(QtWidgets.QProxyStyle):
def drawControl(self, element, option, painter, widget=None):
if element == QtWidgets.QStyle.CE_Header:
option.text = ""
super(HeaderProxyStyle, self).drawControl(
element, option, painter, widget
)
class LabelHeaderView(QtWidgets.QHeaderView):
def __init__(self, parent):
super(LabelHeaderView, self).__init__(QtCore.Qt.Horizontal, parent)
self.m_labels = []
self.sectionResized.connect(self.adjustPositions)
self.sectionCountChanged.connect(self.onSectionCountChanged)
self.parent().horizontalScrollBar().valueChanged.connect(
self.adjustPositions
)
proxy_style = HeaderProxyStyle(self.style())
self.setStyle(proxy_style)
@QtCore.pyqtSlot()
def onSectionCountChanged(self):
while self.m_labels:
label = self.m_labels.pop()
label.deleteLater()
for i in range(self.count()):
label = QtWidgets.QLabel(self, alignment=QtCore.Qt.AlignCenter)
self.m_labels.append(label)
self.update_data()
self.adjustPositions()
def setModel(self, model):
super(LabelHeaderView, self).setModel(model)
if self.model() is not None:
self.model().headerDataChanged.connect(self.update_data)
def update_data(self):
option = QtWidgets.QStyleOptionHeader()
self.initStyleOption(option)
for i, label in enumerate(self.m_labels):
text = self.model().headerData(
i, self.orientation(), QtCore.Qt.DisplayRole
)
label.setText(str(text))
pal = label.palette()
bc = self.model().headerData(
i, self.orientation(), QtCore.Qt.BackgroundRole
)
if bc is None:
bc = option.palette.brush(QtGui.QPalette.Window)
pal.setBrush(QtGui.QPalette.Window, bc)
fc = self.model().headerData(
i, self.orientation(), QtCore.Qt.ForegroundRole
)
if fc is None:
fc = option.palette.brush(QtGui.QPalette.ButtonText)
pal.setBrush(QtGui.QPalette.ButtonText, fc)
label.setPalette(pal)
textAlignment = self.model().headerData(
i, self.orientation(), QtCore.Qt.TextAlignmentRole
)
if textAlignment is None:
textAlignment = self.defaultAlignment()
label.setAlignment(textAlignment)
def updateGeometries(self):
super(LabelHeaderView, self).updateGeometries()
self.adjustPositions()
@QtCore.pyqtSlot()
def adjustPositions(self):
for index, label in enumerate(self.m_labels):
geom = QtCore.QRect(
self.sectionViewportPosition(index),
0,
self.sectionSize(index),
self.height(),
)
geom.adjust(2, 0, -2, 0)
label.setGeometry(geom)
if __name__ == "__main__":
import sys
app = QtWidgets.QApplication(sys.argv)
w = QtWidgets.QTableWidget(10, 10)
header = LabelHeaderView(w)
w.setHorizontalHeader(header)
header_labels = []
for i in range(w.columnCount()):
header_label = "<sub>%s</sub><b>Header</b><sup>%s</sup>" % (i, i)
header_labels.append(header_label)
w.setHorizontalHeaderLabels(header_labels)
w.resize(320, 240)
w.show()
sys.exit(app.exec_())