自定义Qtableview如何插入新数据?

问题描述 投票:0回答:0

我有一个由

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 中的模型/代理编程新手。

希望得到一些建议

python-3.x qt pyqt pyside pyside2
© www.soinside.com 2019 - 2024. All rights reserved.