PyQt QListView复选框是否单击切换?

2024-09-30 18:27:32 发布

您现在位置:Python中文网/ 问答频道 /正文

我正在尝试创建一个QListView,其中显示项目列表以及是否启用了这些项目。下面的代码可以做到这一点,但我也希望在用户单击复选框时能够切换项目的启用状态(不仅仅是在列表项目的任何位置,特别是在复选框上),我如何才能做到这一点

enter image description here

import sys
from dataclasses import dataclass
from typing import Dict, List, Union
from PyQt5 import QtCore, QtGui, QtWidgets
from PyQt5.QtCore import Qt

@dataclass
class Filter:
    expr: str
    enabled: bool

class Store:
    def __init__(self):
        super().__init__()

        self.filter_viewer: Union["FilterViewer", None] = None
        self.filters: List[Filter] = []

    def update(self):
        if self.filter_viewer is not None:
            self.filter_viewer.list_model.dataChanged.emit(QtCore.QModelIndex(), QtCore.QModelIndex())

    def add_filter(self, expr: str, enabled=True):
        filt = Filter(expr=expr, enabled=enabled)
        self.filters.append(filt)
        self.update()

    def remove_filter(self, index: int):
        self.filters.pop(index)
        self.update()

    def toggle_filter(self, index: int):
        self.filters[index].enabled = not self.filters[index].enabled
        self.update()


class FilterViewer(QtWidgets.QWidget):
    def __init__(self, pgdf: Store):
        super().__init__()
        pgdf.filter_viewer = self
        self.pgdf = pgdf


        self.list_view = self.ListView()
        self.list_model = self.ListModel(pgdf)
        self.list_view.setModel(self.list_model)

        self.text_input = QtWidgets.QLineEdit()
        self.submit_button = QtWidgets.QPushButton("Add Filter")

        self.submit_button.clicked.connect(self.add_filter)
        self.text_input.returnPressed.connect(self.add_filter)
        self.layout = QtWidgets.QVBoxLayout()
        self.layout.addWidget(self.list_view)
        self.layout.addWidget(self.text_input)
        self.layout.addWidget(self.submit_button)
        self.setLayout(self.layout)

    def add_filter(self):
        expr = self.text_input.text()
        self.text_input.setText("")
        self.pgdf.add_filter(expr=expr)
        print(self.pgdf.filters)


    class ListView(QtWidgets.QListView):
        pass

    class ListModel(QtCore.QAbstractListModel):
        def __init__(self, pgdf: Store):
            super().__init__()
            self.pgdf = pgdf

        def data(self, index: QtCore.QModelIndex, role: int):
            row = index.row()
            if role == Qt.DisplayRole:
                filt = self.pgdf.filters[row]
                return filt.expr

            if role == Qt.CheckStateRole:
                filt = self.pgdf.filters[row]
                if filt.enabled:
                    return Qt.Checked
                else:
                    return Qt.Unchecked

        def rowCount(self, parent):
            return len(self.pgdf.filters)

        def flags(self, index):
            return (QtCore.Qt.ItemIsEnabled |
                    QtCore.Qt.ItemIsUserCheckable)


if __name__ == "__main__":
    app = QtWidgets.QApplication(sys.argv)
    pgdf = Store()
    pgdf.add_filter('Generation > 3', enabled=True)
    pgdf.add_filter('Size > 50', enabled=False)
    fv = FilterViewer(pgdf)
    fv.show()
    app.exec_()

Tags: selfaddindexinitdefenabledfilterqt
1条回答
网友
1楼 · 发布于 2024-09-30 18:27:32

QListView复选框的状态由模型决定,因此要更改模型信息,必须覆盖setData()方法:

class ListModel(QtCore.QAbstractListModel):
    def __init__(self, pgdf: Store):
        super().__init__()
        self.pgdf = pgdf

    def data(self, index: QtCore.QModelIndex, role: int):
        row = index.row()
        if role == Qt.DisplayRole:
            filt = self.pgdf.filters[row]
            return filt.expr

        if role == Qt.CheckStateRole:
            filt = self.pgdf.filters[row]
            if filt.enabled:
                return Qt.Checked
            else:
                return Qt.Unchecked

    def setData(self, index, value, role=QtCore.Qt.DisplayRole):
        row = index.row()
        if role == Qt.CheckStateRole:
            filt = self.pgdf.filters[row]
            filt.enabled = bool(value)
            self.dataChanged.emit(index, index, (role,))
            return True
        return False

    def rowCount(self, parent):
        return len(self.pgdf.filters)

    def flags(self, index):
        return QtCore.Qt.ItemIsEnabled | QtCore.Qt.ItemIsUserCheckable

相关问题 更多 >