PyQt5之带图标QCheckBox实现

效果预览

直接看图,效果展现为在Checkbox后跟随图标实现友好的界面交互且可勾选
在这里插入图片描述

核心代码说明

控件初始化

类的构造函数__init__在窗口中创建了一个垂直布局QVBoxLayout,并在布局内添加了一个QListView用于展示可勾选的列表项(通过CheckableItemModelCheckBoxDelegate来实现相关的数据模型与委托逻辑)

    def __init__(self):
        super().__init__()
        self.setWindowTitle("QCheckBoxIcon Demo")
        __desktop = QDesktopWidget()
        __screen_width = __desktop.screenGeometry().width()
        __screen_height = __desktop.screenGeometry().height()
        self.setGeometry(int(__screen_width * 0.25),
                           int(__screen_height * 0.25),
                           __screen_width // 2,
                           __screen_height // 2)

        self._layout = QVBoxLayout()
        self._list_view = QListView()
        self._model = CheckableItemModel()
        delegate = CheckBoxDelegate()
        self._list_view.setModel(self._model)
        self._list_view.setItemDelegate(delegate)
        self._layout.addWidget(self._list_view, alignment=Qt.AlignTop)      # 可不对齐
        self.setLayout(self._layout)
  • self._model = CheckableItemModel()创建一个CheckableItemModel对象,这个类是自定义的数据模型,用于管理可勾选列表项的数据,并按照PyQt5的数据模型机制与视图QListView进行交互,提供数据展示、更新等功能
  • delegate = CheckBoxDelegate() 创建一个CheckBoxDelegate对象,用于处理列表视图QListView中列表项的委托逻辑,用于编辑勾选状态的勾选框QCheckBox、设置其初始数据以及将编辑后的数据更新回数据模型等操作
  • self._list_view.setItemDelegate(delegate)CheckBoxDelegate对象设置给QListView作为其委托,用于处理列表项的特定编辑和展示逻辑,使得QListView在处理可勾选列表项时能按照自定义的委托逻辑进行操作

自定义勾选框模型

CheckableItemModel类继承自QAbstractListModel,是在PyQt5框架下用于为列表视图(提供自定义数据模型的类。它旨在管理一系列具有可勾选特性、可能带有图标的列表项,使得视图能够根据其提供的数据和规则来展示相应的界面元素,并处理用户与这些元素交互时的数据更新等操作,常用于构建如配置选项列表、文件筛选列表等具有可勾选功能的界面场景

class CheckableItemModel(QAbstractListModel):
    """
    图标勾选框模型
    - items 项列表
    """
    def __init__(self, items = None):
        super().__init__()
        if items is None:
            self._items = []
        else:
            self._items = items

    def rowCount(self, parent=QModelIndex(), *args, **kwargs):
        return len(self._items)

    def data(self, index, role=Qt.DisplayRole):
        """
        - Qt.DisplayRole 描述
        - Qt.CheckStateRole 勾选状态
        - Qt.DecorationRole 图标
        """
        if role == Qt.DisplayRole:
            return self._items[index.row()].name()
        elif role == Qt.CheckStateRole:
            if self._items[index.row()].checkbox():
                return Qt.Checked if self._items[index.row()].checked_status() else Qt.Unchecked
            else:
                return None
        elif role == Qt.DecorationRole:
            return self._items[index.row()].icon()
        return None

    def setData(self, index, value, role=Qt.EditRole):
        if role == Qt.CheckStateRole:
            self._items[index.row()].checked_set(value == Qt.Checked)
            self.dataChanged.emit(index, index, [role])
            return True
        return False

    def flags(self, index):
        flags = Qt.ItemIsEnabled | Qt.ItemIsSelectable
        if self._items[index.row()].checkbox():
            flags |= Qt.ItemIsUserCheckable
        return flags

    def addItem(self, checkable_item):
        self.beginInsertRows(QModelIndex(), self.rowCount(), self.rowCount())
        self._items.append(checkable_item)
        self.endInsertRows()
  • rowCount 重写了父类QAbstractListModelrowCount方法。这个方法的作用是告知视图数据模型中包含的行数,也就是列表项的数量
  • data方法根据传入的索引index和指定的角色role来返回相应的数据内容,供视图展示使用
  • Qt.DisplayRole视图期望获取用于显示的文本信息;Qt.CheckStateRole视图期望获取该项的勾选状态信息;Qt.DecorationRole图期望获取用于装饰显示的图标信息
  • setData用于处理视图传来的对数据的修改请求,根据传入的索引index、新的值value以及角色role来更新数据模型中的相应数据,并反馈更新是否成功。当role为Qt.CheckStateRole时,表示是对勾选状态的修改操作。通过索引获取对应的列表项,然后调用其checked_set方法,将传入的value与Qt.Checked进行比较,根据比较结果来更新列表项的勾选状态。之后,通过self.dataChanged.emit()发出信号,通知视图对应的数据项在勾选状态这一角色下的数据已发生改变,触发视图进行界面更新,最后返回True表示数据更新成功
  • flags方法用于设置每个列表项对应的标志位,以告知视图该项具有哪些交互特性。Qt.ItemIsEnabled标志,表示该项是启用状态,用户可以与之交互,比如鼠标悬停、点击等操作;Qt.ItemIsSelectable标志,表示该项可以被选择,Qt.ItemIsUserCheckable标志,表示该项可由用户进行勾选操作
  • addItem方法用于向数据模型中添加新的列表项,调用self.beginInsertRows方法,传入一个QModelIndex以及当前的行数,这一步操作是通知视图即将要插入新的行数据,让视图做好相应的准备,比如更新内部的数据结构、布局等,以正确响应后续数据的变化。self.endInsertRows方法,告知视图行插入操作已经完成,触发视图进行最终的界面更新,确保新添加的列表项能够正确地显示在视图中

勾选框委托

CheckBoxDelegate 类继承自 QStyledItemDelegate,在 PyQt5 图形用户界面编程框架中,委托类用于自定义视图中各个数据项的显示和编辑行为。这个特定的类主要聚焦于处理列表项中与复选框QCheckBox相关的编辑逻辑,包括创建用于编辑的复选框、设置其初始状态以及将编辑后的状态回写到数据模型中,从而实现了列表项中可勾选功能的完整交互流程,确保用户对复选框的操作能够正确地反映在数据层面,并与对应的视图展示相匹配

class CheckBoxDelegate(QStyledItemDelegate):
    def createEditor(self, parent, option, index):
        if index.data(Qt.CheckStateRole) is not None:
            check_box = QCheckBox(parent)
            check_box.stateChanged.connect(lambda state, idx=index: self.commitData.emit(check_box))
            return check_box
        else:
            return None

    def setEditorData(self, editor, index):
        value = index.data(Qt.CheckStateRole)
        if value is not None:
            editor.setCheckState(value)

    def setModelData(self, editor, model, index):
        if editor is not None:
            model.setData(index, editor.checkState(), Qt.CheckStateRole)
  • createEditor 方法的主要职责是为视图中的可编辑数据项创建对应的编辑器部件。当对应的数据项需要展示和编辑复选框(时,就创建一个 QCheckBox作为编辑器
    – 首先,通过 index.data(Qt.CheckStateRole) 获取指定索引 index 对应的数据项的勾选状态角色数据。如果这个值不为 None,意味着该项在视图中应该呈现出可勾选的复选框形式,并且可以进行编辑操作
    – 接着,创建一个 QCheckBox 对象,并将其传递的 parent 参数作为其父部件,这样可以确保它在视图的相应位置正确显示,并且遵循父部件的布局和显示规则
    – 然后,将创建好的 QCheckBoxstateChanged 信号连接到一个匿名函数。这个匿名函数捕获复选框改变后的状态值以及当前的 index,并在内部调用 self.commitData.emit(check_box)commitData.emit 方法是委托类中用于通知数据模型更新数据的重要机制,当复选框的状态改变时,通过这个信号发射,触发后续的数据更新操作,将新的状态写回到数据模型中
  • setEditorData 方法用于设置QCheckBox的初始数据,确保编辑器在显示给用户进行编辑操作前,其状态与对应的数据项的当前勾选状态一致
    – 首先,通过 index.data(Qt.CheckStateRole) 获取指定索引 index 对应的数据项的当前勾选状态值,这个值可能是 Qt.CheckedQt.Unchecked 或者 Qt.PartiallyChecked对应的枚举值
    – 然后,调用QCheckBoxsetCheckState 方法,将获取到的状态值赋给 QCheckBox,使其初始显示的勾选状态与数据模型中对应的数据项的状态相匹配,这样用户看到的就是准确反映当前数据状态的复选框外观
  • setModelData 方法的作用是在QCheckBox的状态发生改变后,将改变后的状态数据写回到数据模型中,以实现数据的更新和同步,保证视图与数据模型之间的数据一致性
    – 如果可编辑的复选框并且其状态已经发生了改变,此时调用数据模型的 setData 方法,传入当前的索引 indexQCheckBox的当前勾选状态(通过 editor.checkState 获取)以及角色 Qt.CheckStateRole,告知数据模型对应索引的数据项在勾选状态方面发生了改变,需要更新相应的数据,使得数据模型能够根据新的勾选状态来保存和管理数据,进而触发视图根据更新后的数据进行重新展示等后续操作,保持整个界面与数据的同步性

调用演示

if __name__ == '__main__':
    app = QApplication(sys.argv)
    widget = ApplicationCheckableItem()

    widget.add_item(CheckableItem("Item 1 checkbox", True, "usb.png"))
    widget.add_item(CheckableItem("Item 2 no checkbox", False, "usb.png", checkbox=False))
    widget.add_item(CheckableItem("Item 3 checkbox", False, "usb.png"))

    widget.show()
    sys.exit(app.exec_())

完整代码获取

完整代码请从我的资源获取

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值