Issue
I have a QTableView, which I feed with data from ODBC/SQL, where I sort the values firstly in "Team" and in "Person":
Team | Person | RO |
---|---|---|
A | PA | 11111 |
A | PB | 11112 |
A | PC | 11113 |
B | PD | 11114 |
B | PE | 11115 |
C | PF | 11116 |
In the QTableView I know, that I can set the gridline via
tableWidget.setShowGrid(False)
tableWidget.setStyleSheet('QTableView::item {border-right: 1px solid #d6d9dc;}')
But I want to make a thick line between different "Teams", so between Person PC/PD and PE/PF should be a thick horizontal seperator on the full row.
How to do that? - I searched the web and dont find anything...
I thought I cloud do it with
QtCore.QAbstractTableModel
but I dont find a Role to give another borderline.
Thanks
Solution
A possible solution could be to override the paint event of the table and draw the "thicker" lines based on the data. For optimization reasons, the rows of those lines can be "cached", so that the only computation needed for painting is to get the coordinates for the lines.
The code below will give the following result:
class TableSplitLines(QTableWidget):
linesDirty = False
penWidth = 3
referenceColumn = 0
def __init__(self, *args, **kwargs):
super().__init__(*args, **kwargs)
self.splitLines = []
self.itemChanged.connect(self.markDirty)
def markDirty(self):
if not self.linesDirty:
self.linesDirty = True
self.update()
def updateLines(self):
'''
Create a list of rows that correspond to the last rows that have common
and contiguous values for the choosen column
'''
self.splitLines.clear()
last = None
for row in range(self.rowCount()):
first = self.item(row, self.referenceColumn)
if first is None:
value = None
else:
value = first.text()
if row == 0:
last = value
elif value != last:
self.splitLines.append(row)
last = value
self.linesDirty = False
def paintEvent(self, event):
if self.linesDirty:
self.updateLines()
if self.splitLines:
# get the right edge of the last visible column
hHeader = self.horizontalHeader()
lastSection = -1
for i in range(self.columnCount()):
logical = hHeader.logicalIndex(i)
if not hHeader.isSectionHidden(logical):
lastSection = logical
right = min(self.viewport().width(),
hHeader.sectionPosition(lastSection)
+ hHeader.sectionSize(lastSection)
- hHeader.offset()
)
extent = self.penWidth // 2 + 1
top = event.rect().y() - extent
bottom = event.rect().bottom() + extent
# get the grid color from the current style
opt = QStyleOption()
opt.initFrom(self)
gridColor = QColor.fromRgb(
self.style().styleHint(
QStyle.SH_Table_GridLineColor, opt, self
) & 0xffffff)
qp = QPainter(self.viewport())
qp.setPen(QPen(gridColor, self.penWidth, cap=Qt.FlatCap))
# draw lines as long as they're included in the event rect
vHeader = self.verticalHeader()
offset = vHeader.offset() + 1
for row in self.splitLines:
y = vHeader.sectionPosition(row) - offset
if y < top:
continue
elif y > bottom:
break
qp.drawLine(0, y, right, y)
# call the base implementation
super().paintEvent(event)
Note: the 0xffffffff
mask is caused by the fact that the value returned by styleHint()
is an unsigned int, but due to the dynamic typing of Python it can be interpreted as a signed (so, possibly negative).
Answered By - musicamante
0 comments:
Post a Comment
Note: Only a member of this blog may post a comment.