带有 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);
我根据组合框的设置(在 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);