QTreeView Checkboxes QTreeView Checkboxes python python

QTreeView Checkboxes


Firstly, you'll need to modify TreeItem to keep track of the checked state:

private:    ...    bool checked;

and a setter and getter:

bool isChecked() const { return checked; }void setChecked( bool set ) { checked = set; }

Now the model will need to be modified so that the view knows about the check state:

QVariant TreeModel::data(const QModelIndex &index, int role) const{    if (!index.isValid())        return QVariant();    TreeItem *item = static_cast<TreeItem*>(index.internalPointer());    if ( role == Qt::CheckStateRole && index.column() == 0 )        return static_cast< int >( item->isChecked() ? Qt::Checked : Qt::Unchecked );    if (role != Qt::DisplayRole)        return QVariant();    return item->data(index.column());}

and modify the model's flags method to let views know that the model contains checkable items:

Qt::ItemFlags TreeModel::flags(const QModelIndex &index) const{    if (!index.isValid())        return 0;    Qt::ItemFlags flags = Qt::ItemIsEnabled | Qt::ItemIsSelectable;    if ( index.column() == 0 )        flags |= Qt::ItemIsUserCheckable;    return flags;}

I think this should do it. If you want to be able to update the TreeItem check state when the user ticks and unpicks the items, then you'll need to provide the QAbstractItemModel::setData method in your TreeModel.


I converted the above to PyQt for my own purposes and figured I'd share.

def data(self, index, role):    if not index.isValid():        return None    item = index.internalPointer();    if role == Qt.CheckStateRole and index.column() == self.check_col:        return int( Qt.Checked if item.isChecked() else Qt.Unchecked )    return super(TreeModel, self).data(index, role)def flags(self, index):    if not index.isValid():        return None    if index.column() == self.check_col:        flags = Qt.ItemIsEnabled | Qt.ItemIsSelectable | Qt.ItemIsUserCheckable    else:        flags = super(TreeModel, self).flags(index)    return flagsdef setData(self, index, value, role=Qt.EditRole):    if index.column() == self.check_col:        if role == Qt.EditRole:            return False        if role == Qt.CheckStateRole:            item = self.getItem(index)            item.setChecked(value)            self.dataChanged.emit(index, index)            return True    return super(TreeModel, self).setData(index, value, role)


Here is another PyQt complete woking example using QStandardItemModel:

model = QStandardItemModel()parent_item = model.invisibleRootItem()  # type: QStandardItemfor row in [    (Qt.Unchecked, 'unchecked'),    (Qt.PartiallyChecked, 'partially'),    (Qt.Checked, 'checked')]:    checked, text = row    check_item = QStandardItem('')    check_item.setCheckable(True)    check_item.setCheckState(checked)    parent_item.appendRow([check_item, QStandardItem(text)])treeview.setModel(model)

Btw, this should also work for any C++ applications.