我有一个由
QTableView
和QAbstractTableModel
实现的QStyledItemDelegate
。对于模型数据,它有 4 个维度,'姓名'、'年龄'、'性别'、'电话号码'。但在 tableview 中我想将它们显示在 3 列中,名称和年龄在一列中,另外两个放在它们自己的列中。
import sys
from PySide2.QtWidgets import QApplication,QTableView, QStyledItemDelegate,QStyleOptionViewItem,QStyle, QPushButton,QWidget,QVBoxLayout
from PySide2.QtCore import Qt, QAbstractTableModel, QModelIndex
from PySide2.QtGui import QColor, QTextDocument, QPainter,QFont,QAbstractTextDocumentLayout, QPalette,QTextCursor,QTextCharFormat, QTextBlockFormat,QFontMetrics
class MyTableModel(QAbstractTableModel):
def __init__(self, mydata):
super().__init__()
self._tabledata = mydata
def rowCount(self, parent: QModelIndex = ...) -> int:
return len(self._tabledata)
def columnCount(self, parent: QModelIndex = ...) -> int:
return len(self._tabledata[0] if self._tabledata else [])
def data(self, index: QModelIndex, role: int = ...):
if not index.isValid():
return None
if index.row() >= self.rowCount():
return None
if role == Qt.DisplayRole or role == Qt.EditRole:
return self._tabledata[index.row()][index.column()]
else:
return None
def insertNewRow(self):
self.beginInsertRows(QModelIndex(), 0, 0)
self._tabledata.append(['test','20','female', 234])
self.endInsertRows()
class TableDelegate(QStyledItemDelegate):
def paint(self, painter, option, index):
if index.column() in [0, 3, 2]:
painter.save()
painter.setRenderHint(QPainter.Antialiasing, True)
widget = option.widget
style = widget.style()
style.drawControl(style.CE_ItemViewItem, option, painter, widget)
painter.restore()
if index.column() == 0:
self.doc = QTextDocument(self)
colWid = option.rect.width()
painter.save()
painter.setPen(QColor(244,243,243,255))
painter.drawLine(option.rect.bottomLeft(), option.rect.bottomRight())
options = QStyleOptionViewItem(option)
self.initStyleOption(options, index)
self.doc.setPlainText('')
cursor = QTextCursor(self.doc)
fmt = QTextCharFormat()
fmt.setFontFamily('Aria')
fmt.setFontWeight(QFont.Bold)
fmt.setFontPointSize(10)
serifFont = QFont("Aria", 10, QFont.Bold)
fm = QFontMetrics(serifFont)
cursor.setCharFormat(fmt)
cursor.beginEditBlock()
cursor.insertText(fm.elidedText(options.text, Qt.ElideRight, colWid -10))
fmt.setBackground(Qt.red)
cursor.endEditBlock()
tbm = QTextBlockFormat()
tbm.setTopMargin(10)
cursor.insertBlock(tbm)
cursor.beginEditBlock()
fmt.setBackground(Qt.transparent)
fmt.setFontWeight(QFont.Normal)
fmt.setFontPointSize(8)
fmt.setForeground(QColor(123,123,123,255))
cursor.setCharFormat(fmt)
serifFont = QFont("Aria", 8, QFont.Normal)
fm = QFontMetrics(serifFont)
elidedstr = fm.elidedText(index.model().data(index.siblingAtColumn(1), Qt.DisplayRole), Qt.ElideRight, colWid -10)
cursor.insertText(elidedstr)
fmt.setBackground(Qt.red)
cursor.endEditBlock()
ctx = QAbstractTextDocumentLayout.PaintContext()
if option.state & QStyle.State_Selected:
ctx.palette.setColor(QPalette.Text, option.palette.color(
QPalette.Active, QPalette.HighlightedText))
else:
ctx.palette.setColor(QPalette.Text, option.palette.color(
QPalette.Active, QPalette.Text))
textRect = option.widget.style().subElementRect(QStyle.SE_ItemViewItemText, options)
textRect.adjust(5, 0, 0, 0)
textRect.setTop(textRect.top())
painter.translate(textRect.topLeft())
self.doc.documentLayout().draw(painter, ctx)
painter.restore()
else:
QStyledItemDelegate.paint(self, painter, option, index)
class MyTableView(QTableView):
def __init__(self):
super().__init__()
self.verticalHeader().setDefaultSectionSize(40)
self.horizontalHeader().setVisible(False)
self.verticalHeader().setVisible(False)
self.setFixedWidth(300)
if __name__ == '__main__':
app = QApplication(sys.argv)
myWindow = QWidget()
lyt = QVBoxLayout()
myWindow.setLayout(lyt)
t = MyTableView()
t.setItemDelegate(TableDelegate())
m = MyTableModel([['mike', '12', 'male', 124], ['jack', '15', 'male', 123]])
t.setModel(m)
t.setColumnHidden(1, True)
btn = QPushButton('new')
btn.clicked.connect(m.insertNewRow)
lyt.addWidget(btn)
lyt.addWidget(t)
myWindow.show()
sys.exit(app.exec_())
在
QTableview
中,我将隐藏第1列。
在
QStyledItemDelegate
中,我将实施paint
方法使列0以某种方式同时显示姓名和年龄。
到目前为止,它以这种方式工作。
------------update,代码用于添加新数据----------------
但是当我想往表格中插入一条新的数据记录时(代码我没有放在这里),隐藏的列又会出现,这意味着我又要隐藏它们了
PySide2 中的模型/代理编程新手。
希望得到一些建议