pbreach pbreach - 2 months ago 43x
Python Question

Add border under column headers in QTableWidget

I have a table widget with two column header in a dialog that looks like this:

enter image description here

There is a separation between the column headers named "Index" and "Label", but there is no separating border between these header and the row below them. How can this be added?

Say the table is instantiated as:

table = QTableWidget(6, 2, self)

I know that I can get the first horizontal header as a QTableWidgetItem by doing
headerItem = table.horizontalHeaderItem(0)
modify some properties and set it back, but I'm unsure of what properties to set or if there is a more straightforward approach.


If I extract the header and set the style, shadow, and line width properties of its underlying frame via:

header = table.horizontalHeader()
header.setFrameStyle(QFrame.Box | QFrame.Plain)

I end up with something that looks like this:

enter image description here

This way a border does show up around the header. This could be done for each header item separately, but there are a couple of concerns:

  1. The border extends past the width of the cells below

  2. I'd still have to match the color of the frame to the existing lines for this to look somewhat decent.

  3. It appears that the vertical line that separates "Index" and "Label" is shifted in relation to the line separating the cells below (unless my eyes are playing tricks on me).

Is there a more 'built in' way to do this?


I had the same problem. The first thing to note is that this only happens on Windows 10. On other OS, there is nothing to repair, it just works. On Windows 10 however, the painting primitives are not painting the bottom border (which is the default Windows 10 table header style - as can be seen in windows file explorer). This is unfortunate but can be solved with the following style sheet:

            "border-top:0px solid #D8D8D8;"
            "border-left:0px solid #D8D8D8;"
            "border-right:1px solid #D8D8D8;"
            "border-bottom: 1px solid #D8D8D8;"
            "border-top:0px solid #D8D8D8;"
            "border-left:0px solid #D8D8D8;"
            "border-right:1px solid #D8D8D8;"
            "border-bottom: 1px solid #D8D8D8;"

Sorry to bother you with C++ code but It should be easy enough to translate into valid pyqt code.

Note1: The background-color and padding are unfortunate but they are necessary to make our custom rendering looks like the default one.

Note2: The color of the border is the color of the grid on my system. I did not use the color of the default header.

Note3: The QTableCornerButton::section part is necessary to add the missing border below the top left corner. If the vertical header is not visible, the missing line is invisible too.

Hope this helps.