title: Qt ItemDelegate displayText() with a QTableWidget: How can I access the table index?
body: <p>I display data in a QTableWidget in various number formats, depending on the setting of a combobox (outside QTableWidget). This works nicely by redefining the <code>displayText()</code> method of an ItemDelegate.</p>
  
  <p>I would also like to style / modify the displayed text depending on its index, however, only the text and the locale are passed as arguments to <code>displayText()</code>.</p>
  
  <p>As a workaround I also redefined the <code>paint()</code> method because here the index is passed as well. This seems very clumsy to me and I'm also at the end of the rope when I start styling the text - pure Cargo Cult programming ...</p>
  
  <p>So, am I barking up the wrong tree? Is there a simpler way to format e.g. only the element (0,1) (see code below), maybe within <code>displayText()</code>?</p>
  
  <p>The following code is just a minimum working example, full code under</p>
  
  <p><a href="https://github.com/chipmuenk/pyFDA/blob/coeff_table/pyfda/input_widgets/filter_coeffs.py" rel="nofollow noreferrer">https://github.com/chipmuenk/pyFDA/blob/coeff_table/pyfda/input_widgets/filter_coeffs.py</a></p>
  
  <pre><code># -*- coding: utf-8 -*-
  from __future__ import print_function, division, unicode_literals, absolute_import
  #from PyQt4.QtGui import  ...
  from PyQt5.QtWidgets import (QWidget, QApplication, QTableWidget, 
                               QTableWidgetItem, QVBoxLayout, QStyledItemDelegate)
  from PyQt5.QtWidgets import QStyle  
  from PyQt5.QtGui import QFont
  #from PyQt4.QtGui import QStyle, QFont
  import numpy as np
  
  class ItemDelegate(QStyledItemDelegate):
      """
      The following methods are subclassed to replace display and editor of the
      QTableWidget.
      """
      def __init__(self, parent):
          """
          Pass instance `parent` of parent class (TestTable)
          """
          super(ItemDelegate, self).__init__(parent)
          self.parent = parent # instance of the parent (not the base) class
  
      def paint(self, painter, option, index):
          """
          painter:  instance of QPainter
          option: instance of QStyleOptionViewItem(V4?)
          index:   instance of QModelIndex
          """
          style_option = option
          # read text to be shown:
          if index.row() == 0 and index.column() == 1: # always display "1!" at index (0,1)
              style_option.text = "1!" 
              style_option.font.setBold(True)
              # now paint the cell
              self.parent.style().drawControl(QStyle.CE_ItemViewItem, style_option, painter)
          else:
              super(ItemDelegate, self).paint(painter, option, index) # default painter
  
      def displayText(self, text, locale):
          """
          Display `text` in the selected with the selected number
          of digits
  
          text:   string / QVariant from QTableWidget to be rendered
          locale: locale for the text
          """ 
          data = text # .toString() # Python 2: need to convert to "normal" string
          return "{0:&gt;{1}}".format(data, 4)
  
  
  class TestTable(QWidget):
      """ Create widget for viewing / editing / entering data """
      def __init__(self, parent):
          super(TestTable, self).__init__(parent)
  
          self.bfont = QFont()
          self.bfont.setBold(True)
  
          self.tblCoeff = QTableWidget(self)
          self.tblCoeff.setItemDelegate(ItemDelegate(self))
  
          layVMain = QVBoxLayout()
          layVMain.addWidget(self.tblCoeff)
          self.setLayout(layVMain)
  
          self.ba = np.random.randn(3,4) # test data
          self._refresh_table()
  
      def _refresh_table(self):
          """ (Re-)Create the displayed table from self.ba """
          num_cols = 3
          num_rows = 4
  
          self.tblCoeff.setRowCount(num_rows)
          self.tblCoeff.setColumnCount(num_cols)
  
          for col in range(num_cols):
              for row in range(num_rows):
                  # set table item from self.ba 
                  item = self.tblCoeff.item(row, col)
                  if item: # does item exist?
                      item.setText(str(self.ba[col][row]))
                  else: # no, construct it:
                      self.tblCoeff.setItem(row,col,QTableWidgetItem(
                            str(self.ba[col][row])))
  
          self.tblCoeff.resizeColumnsToContents()
          self.tblCoeff.resizeRowsToContents()
  
  #------------------------------------------------------------------------------
  
  if __name__ == '__main__':
      import sys
      app = QApplication(sys.argv)
      mainw = TestTable(None)
  
      app.setActiveWindow(mainw)
      mainw.show()
  
      sys.exit(app.exec_())
  </code></pre>
  
  <p>EDIT: =================================================================</p>
  
  <p>@m7913d's suggestion works for me, I'm overriding the initStyleOption()  method instead of the paint() method which looks more concise to me. This is the updated code (so I've partially answered my own question):</p>
  
  <pre><code># -*- coding: utf-8 -*-
  from __future__ import print_function, division, unicode_literals, absolute_import
  #from PyQt4.QtGui import  ...
  from PyQt5.QtWidgets import (QWidget, QApplication, QTableWidget, 
                               QTableWidgetItem, QVBoxLayout, QStyledItemDelegate)
  from PyQt5.QtWidgets import QStyle  
  from PyQt5.QtGui import QFont
  #from PyQt4.QtGui import QStyle, QFont
  import numpy as np
  
  class ItemDelegate(QStyledItemDelegate):
      """
      The following methods are subclassed to replace display and editor of the
      QTableWidget.
      """
      def __init__(self, parent):
          """
          Pass instance `parent` of parent class (TestTable)
          """
          super(ItemDelegate, self).__init__(parent)
          self.parent = parent # instance of the parent (not the base) class
  
      def initStyleOption(self, option, index):
          """
          Initialize `option` with the values using the `index` index. When the 
          item (0,1) is processed, it is styled especially. All other items are 
          passed to the original `initStyleOption()` which then calls `displayText()`.
          """
          if index.row() == 0 and index.column() == 1: # a[0]: always 1
              option.text = "1!" # QString object
              option.font.setBold(True) 
              option.displayAlignment = Qt.AlignRight
              #option.backgroundBrush ...
          else:
              # continue with the original `initStyleOption()`
              super(ItemDelegate, self).initStyleOption(option, index)     
  
      def displayText(self, text, locale):
          """
          Display `text` in the selected with the selected number
          of digits
  
          text:   string / QVariant from QTableWidget to be rendered
          locale: locale for the text
          """ 
          data = text # .toString() # Python 2: need to convert to "normal" string
          return "{0:&gt;{1}}".format(data, 4)
  
  
  class TestTable(QWidget):
      """ Create widget for viewing / editing / entering data """
      def __init__(self, parent):
          super(TestTable, self).__init__(parent)
  
          self.bfont = QFont()
          self.bfont.setBold(True)
  
          self.tblCoeff = QTableWidget(self)
          self.tblCoeff.setItemDelegate(ItemDelegate(self))
  
          layVMain = QVBoxLayout()
          layVMain.addWidget(self.tblCoeff)
          self.setLayout(layVMain)
  
          self.ba = np.random.randn(3,4) # test data
          self._refresh_table()
  
      def _refresh_table(self):
          """ (Re-)Create the displayed table from self.ba """
          num_cols = 3
          num_rows = 4
  
          self.tblCoeff.setRowCount(num_rows)
          self.tblCoeff.setColumnCount(num_cols)
  
          for col in range(num_cols):
              for row in range(num_rows):
                  # set table item from self.ba 
                  item = self.tblCoeff.item(row, col)
                  if item: # does item exist?
                      item.setText(str(self.ba[col][row]))
                  else: # no, construct it:
                      self.tblCoeff.setItem(row,col,QTableWidgetItem(
                            str(self.ba[col][row])))
  
          self.tblCoeff.resizeColumnsToContents()
          self.tblCoeff.resizeRowsToContents()
  
  #------------------------------------------------------------------------------
  
  if __name__ == '__main__':
      import sys
      app = QApplication(sys.argv)
      mainw = TestTable(None)
  
      app.setActiveWindow(mainw)
      mainw.show()
  
      sys.exit(app.exec_())
  </code></pre>
  
  <p>replaces the overridden paint routine and is more concise.</p>