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?

Conditional borders on QTableWidget cells?

Scheduled Pinned Locked Moved Unsolved General and Desktop
11 Posts 6 Posters 3.6k Views
  • 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 Offline
    D Offline
    donquibeats
    wrote on 11 Aug 2020, 07:34 last edited by
    #1

    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.

    J 1 Reply Last reply 11 Aug 2020, 07:45
    0
    • D donquibeats
      11 Aug 2020, 07:34

      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.

      J Offline
      J Offline
      JonB
      wrote on 11 Aug 2020, 07:45 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 11 Aug 2020, 09:52 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
        • C Online
          C Online
          Christian Ehrlicher
          Lifetime Qt Champion
          wrote on 11 Aug 2020, 15:10 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 11 Aug 2020, 15:21 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
            • C Online
              C Online
              Christian Ehrlicher
              Lifetime Qt Champion
              wrote on 11 Aug 2020, 17:57 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 11 Aug 2020, 18:29 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 12 Aug 2020, 09:05 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 17 Sept 2021, 03:00 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 17 Sept 2021, 03:11
                    1
                    • A abdv17
                      17 Sept 2021, 03:00

                      @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 17 Sept 2021, 03:11 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
                        17 Sept 2021, 03:00

                        @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 22 Jan 2023, 07:12 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