PySide6学习笔记--QStyledItemDelegate简单实现

目录

简述

自定义的QStyledItemDelegate

主窗体

运行结果

不实现paint

painter绘制图形

参考 


简述

己见,model穿了一件view的外衣,但觉得差点什么,就找QStyledItemDelegate裁缝来加工改造。成果怎样,则需要通过使用(即编辑单元格,可能是QSpinBox或QComboBox...等等)来知晓。

自定义的QStyledItemDelegate

class StuDelegate(QStyledItemDelegate):  # 自定义的QStyledItemDelegate
    def __init__(self, parent=None):
        super().__init__(parent)
        self.x_and_y = None  # 点击的(x, y)坐标
    # 创建编辑
    def createEditor(self, parent: QWidget, option: QStyleOptionViewItem, index: QModelIndex) ->None:
        return None  # 此时不要创建编辑渲染
    # 绘制
    def paint(self, painter: QPainter, option: QStyleOptionViewItem, index: QModelIndex) -> None:
        # 此处option.rect 就是 index中(n , 3)项的图形(n为数据行)
        edit_btn = self.get_btn('编辑', option.rect.left(), option.rect.top(), option.rect.width() / 2, option.rect.height())
        delete_btn = self.get_btn('删除', option.rect.left() + option.rect.width() / 2, option.rect.top(), option.rect.width() / 2, option.rect.height())
        # 按钮创建
        QPushButton().style().drawControl(QStyle.ControlElement.CE_PushButton, edit_btn, painter)
        QPushButton().style().drawControl(QStyle.ControlElement.CE_PushButton, delete_btn, painter)
    # 自定义按钮的创建
    def get_btn(self, txt, x, y, width, height) -> QStyleOptionButton:
        btn = QStyleOptionButton()  # 样式按钮
        btn.rect = QRect(x, y, width, height)  # 设置矩形
        btn.text = txt  # 设置文本
        if self.x_and_y and btn.rect.contains(self.x_and_y):  # 当存在点击并且在矩形按钮范围内部
            btn.state = QStyle.StateFlag.State_Active | QStyle.StateFlag.State_Sunken  # 样式的状态效果
        else:
            btn.state = QStyle.StateFlag.State_Enabled | QStyle.StateFlag.State_Raised
        return btn
    # 编辑事件
    def editorEvent(self, event: QEvent, model: QStandardItemModel, option: QStyleOptionViewItem, index: QModelIndex) -> bool:
        if event.type() == QEvent.Type.MouseButtonPress:  # 按下事件
            self.x_and_y = event.position().toPoint()  # QPointF 转成 QPoint
            if option.rect.top() < self.x_and_y.y() < option.rect.bottom():
                if self.x_and_y.x() < int(option.rect.left() + option.rect.right()) / 2:  # 中间点判断
                    QMessageBox.information(None, '提示', '这是编辑')  # 消息提示框
                else:
                    QMessageBox.information(None, '提示', '这是删除')
        elif event.type() == QEvent.Type.MouseButtonRelease:  # 释放事件
            self.x_and_y = None
        return True

绘制按钮的方式有很多,以下就是2种(此处使用drawControl):
QStyle.drawPrimitive(peoptp[, widget=None])
QStyle.drawControl(elementoptp[, widget=None])--通过提供的painter和option来绘制指定的element。

主窗体

class StuWin(QWidget):
    def __init__(self):
        super().__init__()
        self.stu_lis = [['学习a', 16, '男'], ['学习b', 17, '男'], ['练习c', 18, '男']]
        self.initUI()
    def initUI(self):
        self.setWindowTitle('学习练习')
        self.move_center(600, 200)
        layout = QVBoxLayout()
        model = QStandardItemModel()
        model.setRowCount(3)
        model.setColumnCount(3)
        model.setHorizontalHeaderLabels(['姓名', '年龄', '性别', '操作'])
        for rowIndex, row in enumerate(self.stu_lis):
            for colIndex, col in enumerate(row):
                model.setItem(rowIndex, colIndex, QStandardItem(str(col)))
        view = QTableView()
        view.horizontalHeader().setSectionResizeMode(QHeaderView.ResizeMode.Stretch)
        view.setEditTriggers(QTableView.EditTrigger.NoEditTriggers)
        view.setSelectionBehavior(QTableView.SelectionBehavior.SelectRows)
        view.setModel(model)
        view.setItemDelegateForColumn(3, StuDelegate())
        layout.addWidget(view)
        self.setLayout(layout)
    def move_center(self, width, height):
        w = QGuiApplication.primaryScreen().size().width()
        h = QGuiApplication.primaryScreen().size().height()
        self.setGeometry((w - width) / 2, (h - height) / 2, width, height)

运行结果

不实现paint

不需要自定义绘制的时候,无需实现paint(),只需要重写下述方法:
def createEditor(self, parent, option, index): ... 创建所需控件,例如QSpinBox等等
def setEditorData(self, editor, index): ... 设置控件数据,QSpinBox().setValue(...
def setModelData(self, editor, model, index): ... 设置模型数据,model.setData(...
def updateEditorGeometry(self, editor, option, index): ... 简单布局

painter绘制图形

    def paint(self, painter: QPainter, option: QStyleOptionViewItem, index: QModelIndex) -> None:
        h_center1 = option.rect.left()
        v_center1 = option.rect.bottom() - option.rect.height()
        painter.drawEllipse(h_center1, v_center1, option.rect.width() / 2, option.rect.height())
        painter.drawText(h_center1 + 25, option.rect.bottom() - 10, '编辑')
        h_center2 = option.rect.left() + option.rect.width() / 2
        v_center2 = option.rect.bottom() - option.rect.height()
        painter.drawEllipse(h_center2, v_center2, option.rect.width() / 2, option.rect.height())
        painter.drawText(h_center2 + 25, option.rect.bottom() - 10, '删除')
这里仅仅使用了 QPinter 进行绘制图形,依据option的坐标,运行结果如下:

参考 

Model/View Programming

QStyle

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值