Skip to content
  • Categories
  • Recent
  • Tags
  • Popular
  • Users
  • Groups
  • Search
  • Get Qt Extensions
  • Unsolved
Collapse
Brand Logo
  1. Home
  2. Qt Development
  3. General and Desktop
  4. Conditional borders on QTableWidget cells?
Qt 6.11 is out! See what's new in the release blog

Conditional borders on QTableWidget cells?

Scheduled Pinned Locked Moved Unsolved General and Desktop
11 Posts 6 Posters 6.2k Views 1 Watching
  • Oldest to Newest
  • Newest to Oldest
  • Most Votes
Reply
  • Reply as topic
Log in to reply
This topic has been deleted. Only users with topic management privileges can see it.
  • D donquibeats

    What would be the 'proper' way to implement borders that would be programmatically applied to some, but not all, of the cells in a QTableWidget?

    For example I have a test table that looks like this:
    example QTableWidget with test data

    And I want to be able to put borders on certain cells, so it would look something like this (this is an Excel screenshot as an example):
    Excel screenshot showing borders on some cells

    How would I go about accomplishing this in Qt (PyQt5) please? I'm not sure where to start. I expect I'll need to use a QPainter- but where and when?

    The QTableWidget is already subclassed in my main program, and I can subclass each QTableWidgetItem if necessary, but the QTableWidgetItem doesn't seem to have a paintEvent (according to PyCharm) so I'm not sure where my code for conditional drawing of borders would be inserted?

    I can provide the code for my example above if it helps but this is more of a general "how to?" question than a problem in that code I think.

    JonBJ Offline
    JonBJ Offline
    JonB
    wrote on last edited by
    #2

    @donquibeats said in Conditional borders on QTableWidget cells?:

    I'm not sure where my code for conditional drawing of borders would be inserted

    this is more of a general "how to?" question than a problem in that code I think

    You have two possible approaches:

    • Use a QStyledItemDelegate to do the cell drawing. You attach that via QAbstractItemView::setItemDelegate(). https://doc.qt.io/qt-5/qtwidgets-itemviews-stardelegate-example.html illustrates this.

    • Try to do it somehow via stylesheet rules. However, since QTableWidgetItem is not a QWidget and so cannot be directly addressed from stylesheet, I'm not sure how to go about that. So I suggest the first alternative :)

    1 Reply Last reply
    1
    • D Offline
      D Offline
      donquibeats
      wrote on last edited by
      #3

      Thanks for the response.

      I had already looked at that page and attempted to use QStyledItemDelegate, but it hadn't worked and I'd assumed I'd been looking in the wrong direction.

      Below is my test code which, in my theory, ought to draw a thicker black line on the left side of every cell thanks to these lines:

      qr = QRect(option.rect.x(), option.rect.y(), 5, option.rect.height())
              painter.fillRect(qr, qb)
      

      I know the subclassing is being reached, at least, because when I comment out the line super().paint(painter, option, index) the cells are painted empty.

      However when I run the code, the table is displayed plain, and the fillRect() doesn't seem to have any effect. I must be doing something wrong. Any pointers would be welcome?

      import sys
      
      from PyQt5 import QtCore, QtGui
      from PyQt5.QtCore import QRect
      from PyQt5.QtGui import QBrush
      from PyQt5.QtWidgets import QApplication, QTableWidget, QTableWidgetItem, QGridLayout, QFrame, QDialog, \
          QStyledItemDelegate
      
      
      class TestDelegate(QStyledItemDelegate):
          def __init__(self):
              super().__init__()
      
          def paint(self, painter: QtGui.QPainter, option: 'QStyleOptionViewItem', index: QtCore.QModelIndex) -> None:
              self.initStyleOption(option, index)
              super().paint(painter, option, index)
              qb = QBrush()
              qr = QRect(option.rect.x(), option.rect.y(), 5, option.rect.height())
              painter.fillRect(qr, qb)
      
      
      class TableTestDialog(QDialog):
          def __init__(self, window_title):
              super().__init__()
              self.setWindowTitle(window_title)
              self.layout = QGridLayout(self)
      
              self.table = QTableWidget()
              rowCount, columnCount = 40, 40
              self.table.setItemDelegate(TestDelegate())
              self.table.setRowCount(rowCount)
              self.table.setColumnCount(columnCount)
      
              for c in range(0, columnCount):
                  self.table.setHorizontalHeaderItem(c, QTableWidgetItem("Header" + str(c) + "\nTest"))
      
              for r in range(0, rowCount):
                  for c in range(0, columnCount):
                      text = str(r) + ":" + str(c)
                      self.table.setItem(r, c, QTableWidgetItem(text))
      
              self.innerLayout = QGridLayout()
              self.innerLayoutFrame = QFrame()
              self.innerLayoutFrame.setLayout(self.innerLayout)
              self.innerLayout.addWidget(self.table)
              self.layout.addWidget(self.innerLayoutFrame, 0, 0)
      
      
      if __name__ == '__main__':
          app = QApplication(sys.argv)
          windowTitle = "Table test"
          testDialog = TableTestDialog(windowTitle)
          testDialog.show()
          sys.exit(app.exec_())
      
      
      1 Reply Last reply
      0
      • Christian EhrlicherC Offline
        Christian EhrlicherC Offline
        Christian Ehrlicher
        Lifetime Qt Champion
        wrote on last edited by
        #4

        The lines are painted independently from the cells. You have to overwrite paintEvent for this and do all the painting by yourself - maybe first call the base class and then redraw the lines

        Qt Online Installer direct download: https://download.qt.io/official_releases/online_installers/
        Visit the Qt Academy at https://academy.qt.io/catalog

        1 Reply Last reply
        1
        • D Offline
          D Offline
          donquibeats
          wrote on last edited by
          #5

          Sorry, perhaps I'm overlooking the obvious here, but "first call the base class and then redraw the lines" is exactly what I thought I was already doing in these lines:

              def paint(self, painter: QtGui.QPainter, option: 'QStyleOptionViewItem', index: QtCore.QModelIndex) -> None:
                  self.initStyleOption(option, index)
                  super().paint(painter, option, index)
                  qb = QBrush()
                  qr = QRect(option.rect.x(), option.rect.y(), 5, option.rect.height())
                  painter.fillRect(qr, qb)
          

          But that doesn't work, as above.

          So there's something I'm still not understanding about the structure I need to use...?

          1 Reply Last reply
          0
          • Christian EhrlicherC Offline
            Christian EhrlicherC Offline
            Christian Ehrlicher
            Lifetime Qt Champion
            wrote on last edited by
            #6

            I already said it's not the cell painting but the QTableView's one.

            Qt Online Installer direct download: https://download.qt.io/official_releases/online_installers/
            Visit the Qt Academy at https://academy.qt.io/catalog

            1 Reply Last reply
            0
            • eyllanescE Offline
              eyllanescE Offline
              eyllanesc
              wrote on last edited by
              #7

              Use:

              def paint(self, painter: QtGui.QPainter, option: 'QStyleOptionViewItem', index: QtCore.QModelIndex) -> None:
                  super().paint(painter, option, index)
                  
                  painter.save()
                  pen = QPen(QColor("black"))
                  qr = QRect(option.rect)
                  qr.setWidth(pen.width())
                  painter.setPen(pen)
                  painter.drawRect(qr)
                  painter.restore()
              

              If you want me to help you develop some work then you can write to my email: e.yllanescucho@gmal.com.

              1 Reply Last reply
              3
              • D Offline
                D Offline
                donquibeats
                wrote on last edited by
                #8

                Thanks @eyllanesc that's exactly what I was missing, and it works perfectly.

                I've been able to adapt this and add extra code to the subclassed QStyledItemDelegate so that I'm able to show borders on certain cells as appropriate, such as in this date table where the borders are a neat way to visually indicate weeks:

                aSnippet of calendar screenshot

                This is exactly what I was hoping to accomplish so many thanks for your help.

                1 Reply Last reply
                1
                • A Offline
                  A Offline
                  abdv17
                  wrote on last edited by abdv17
                  #9

                  @donquibeats if you don't mind can you share the extra code you added to customize the borders.
                  I'm trying to do something similar, highlight borders to range of cells/multiple rows to enclose like a rectangle/square shown in image. example_table.PNG

                  A A 2 Replies Last reply
                  1
                  • A abdv17

                    @donquibeats if you don't mind can you share the extra code you added to customize the borders.
                    I'm trying to do something similar, highlight borders to range of cells/multiple rows to enclose like a rectangle/square shown in image. example_table.PNG

                    A Offline
                    A Offline
                    abdv17
                    wrote on last edited by abdv17
                    #10

                    @eyllanesc @JonB @Christian-Ehrlicher if any suggestions from your side is also will be of great help. I'm just starting out with pyqt5

                    1 Reply Last reply
                    0
                    • A abdv17

                      @donquibeats if you don't mind can you share the extra code you added to customize the borders.
                      I'm trying to do something similar, highlight borders to range of cells/multiple rows to enclose like a rectangle/square shown in image. example_table.PNG

                      A Offline
                      A Offline
                      Alexey Serebryakov
                      wrote on last edited by
                      #11

                      @abdv17 how did you do that?

                      1 Reply Last reply
                      0

                      • Login

                      • Login or register to search.
                      • First post
                        Last post
                      0
                      • Categories
                      • Recent
                      • Tags
                      • Popular
                      • Users
                      • Groups
                      • Search
                      • Get Qt Extensions
                      • Unsolved