带有 QTableWidget 的 Qt ItemDelegate displayText():如何访问 table 索引?

Qt ItemDelegate displayText() with a QTableWidget: How can I access the table index?

我根据组合框的设置(在 QTableWidget 之外)以各种数字格式在 QTableWidget 中显示数据。这通过重新定义 ItemDelegate 的 displayText() 方法很好地工作。

我还想根据其索引设置/修改显示文本的样式,但是,只有文本和区域设置作为参数传递给 displayText()

作为解决方法,我还重新定义了 paint() 方法,因为这里也传递了索引。这对我来说似乎很笨拙,当我开始设计文本样式时,我也处于困境 - 纯 Cargo Cult 编程 ...

那么,我找错人了吗?有没有更简单的格式化方法,例如只有元素 (0,1)(见下面的代码),可能在 displayText()?

以下代码只是一个最小的工作示例,完整代码在

https://github.com/chipmuenk/pyFDA/blob/coeff_table/pyfda/input_widgets/filter_coeffs.py

# -*- 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:>{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_())

编辑:=========================================== ======================

@m7913d 的建议对我有用,我覆盖了 initStyleOption() 方法而不是 paint() 方法,这对我来说看起来更简洁。这是更新后的代码(所以我已经部分回答了我自己的问题):

# -*- 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:>{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_())

替换覆盖的绘制例程,更加简洁。

您可以尝试覆盖 QStyledItemDelegate::initStyleOption and set the text yourself as this is now done by qt:

option->text = displayText(value, option->locale);