You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何在PySide6的QTableView单元格中添加删除按钮并处理点击事件

在PySide6的QTableView中为每行添加删除按钮的实现方案

1. 修正Delegate的paint方法

不要在paint中创建实际的QPushButton(这种方式不会显示控件,还会浪费资源),而是利用Qt的样式系统绘制按钮的视觉效果,保证样式和系统一致且性能更好:

from PySide6 import QtWidgets, QtGui, QtCore
from typing import Union

class DeleteButtonDelegate(QtWidgets.QStyledItemDelegate):
    btn_clicked = QtCore.Signal(int)  # 自定义信号,传递被点击行的行号

    def paint(self, painter: QtGui.QPainter, option: QtWidgets.QStyleOptionViewItem,
              index: Union[QtCore.QModelIndex, QtCore.QPersistentModelIndex]) -> None:
        # 仅在最后一列绘制删除按钮
        if index.column() == index.model().columnCount() - 1:
            # 配置按钮样式参数
            btn_option = QtWidgets.QStyleOptionButton()
            btn_option.rect = option.rect.adjusted(4, 4, -4, -4)  # 调整按钮与单元格的边距
            btn_option.text = "删除"
            btn_option.state = QtWidgets.QStyle.State_Enabled | QtWidgets.QStyle.State_Active
            
            # 调用系统样式绘制按钮
            QtWidgets.QApplication.style().drawControl(QtWidgets.QStyle.CE_PushButton, btn_option, painter)
        else:
            # 其他列使用父类默认绘制逻辑
            super().paint(painter, option, index)

2. 处理按钮点击事件

重写editorEvent方法,捕获鼠标点击动作,判断点击位置是否在按钮区域内,若是则发出删除信号:
在上述DeleteButtonDelegate类中添加以下代码:

def editorEvent(self, event: QtCore.QEvent, model: QtCore.QAbstractItemModel, option: QtWidgets.QStyleOptionViewItem, index: QtCore.QModelIndex) -> bool:
    # 非操作列直接调用父类逻辑
    if index.column() != model.columnCount() - 1:
        return super().editorEvent(event, model, option, index)
    
    # 处理鼠标左键释放事件
    if event.type() == QtCore.QEvent.MouseButtonRelease and event.button() == QtCore.Qt.LeftButton:
        # 判断点击位置是否在按钮范围内
        btn_rect = option.rect.adjusted(4, 4, -4, -4)
        if btn_rect.contains(event.pos()):
            self.btn_clicked.emit(index.row())
            return True
    return super().editorEvent(event, model, option, index)

3. 完善TableModel的删除功能

确保你的MyTableModel实现removeRow方法(QAbstractTableModel默认未实现),处理数据删除并通知模型更新:

class MyTableModel(QtCore.QAbstractTableModel):
    def __init__(self, data=None, headers=None):
        super().__init__()
        self._data = data or [["行1数据1", "行1数据2"], ["行2数据1", "行2数据2"], ["行3数据1", "行3数据2"]]
        self._headers = headers or ["列1", "列2", "操作"]  # 最后一列设为操作列

    def rowCount(self, parent=QtCore.QModelIndex()) -> int:
        return len(self._data)

    def columnCount(self, parent=QtCore.QModelIndex()) -> int:
        return len(self._headers)

    def data(self, index: QtCore.QModelIndex, role=QtCore.Qt.DisplayRole):
        if not index.isValid():
            return None
        if role == QtCore.Qt.DisplayRole:
            if index.column() < len(self._data[index.row()]):
                return self._data[index.row()][index.column()]
        return None

    def headerData(self, section: int, orientation: QtCore.Qt.Orientation, role=QtCore.Qt.DisplayRole):
        if role == QtCore.Qt.DisplayRole and orientation == QtCore.Qt.Horizontal:
            return self._headers[section]
        return super().headerData(section, orientation, role)

    def removeRow(self, row: int, parent=QtCore.QModelIndex()) -> bool:
        if 0 <= row < len(self._data):
            # 通知模型即将删除行
            self.beginRemoveRows(parent, row, row)
            del self._data[row]
            # 通知模型删除完成
            self.endRemoveRows()
            return True
        return False

4. 主窗口中绑定代理与信号

修改Window类,设置代理并将按钮点击信号绑定到删除逻辑:

class Window(QtWidgets.QMainWindow):
    def __init__(self):
        super().__init__()
        self.setWindowTitle("带删除按钮的表格")
        self.table_view = QtWidgets.QTableView()
        self.setCentralWidget(self.table_view)
        
        self.model = MyTableModel()
        self.table_view.setModel(self.model)
        
        # 为最后一列设置删除按钮代理
        self.delete_delegate = DeleteButtonDelegate()
        self.table_view.setItemDelegateForColumn(self.model.columnCount()-1, self.delete_delegate)
        
        # 绑定删除信号到槽函数
        self.delete_delegate.btn_clicked.connect(self.on_delete_btn_clicked)
        
        # 自动调整列宽适配内容
        self.table_view.resizeColumnsToContents()

    def on_delete_btn_clicked(self, row):
        # 调用模型方法删除对应行
        self.model.removeRow(row)

运行测试

添加主函数启动程序:

if __name__ == "__main__":
    app = QtWidgets.QApplication([])
    window = Window()
    window.show()
    app.exec()

内容的提问来源于stack exchange,提问作者ucag

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.09 02:35:20