I have a QTableView containing a column with checkboxes. Now I want to sort this column.
But as soon as I set a QSortFilterProxyModel as table model, the checkbox is no more shown.
What must I do that this works?
With QSortFilterProxyModel
Without QSortFilterProxyModel
The code is based on another example for a centered checkbox and is without using the QSortFilterProxyModel.
Change the line self.table_view.setModel(table_model) to self.table_view.setModel(proxy_model) to show the behaviour.
import sys
import pandas as pd
from PySide6.QtCore import Qt, Property, Signal, QAbstractTableModel
from PySide6.QtCore import QSortFilterProxyModel
from PySide6.QtWidgets import QCheckBox, QHBoxLayout, QStyledItemDelegate, QTableView, QWidget, QApplication, QMainWindow
class CenterCheckBox(QWidget):
toggled = Signal(bool)
def __init__(self, parent):
super().__init__(parent)
layout = QHBoxLayout(self)
layout.setContentsMargins(0, 0, 0, 0)
self.check = QCheckBox()
layout.addWidget(self.check, alignment=Qt.AlignmentFlag.AlignCenter)
self.check.setFocusProxy(self)
self.check.toggled.connect(self.toggled)
# set a 0 spacing to avoid an empty margin due to the missing text
self.check.setStyleSheet('color: red; spacing: 0px;')
self.setAutoFillBackground(True)
@Property(bool, user=True) # note the user property parameter
def checkState(self):
return self.check.isChecked()
@checkState.setter
def checkState(self, state):
self.check.setChecked(state)
class MyCheckboxDelegate(QStyledItemDelegate):
def __init__(self, parent):
super().__init__(parent)
def createEditor(self, parent, option, index):
check = CenterCheckBox(parent)
check.toggled.connect(lambda: self.commitData.emit(check))
return check
def setModelData(self, editor, model, index):
model.setData(index, editor.checkState)
class TableModel(QAbstractTableModel):
def __init__(self, data):
super().__init__()
print(data)
self._data = data
def rowCount(self, index=None):
return self._data.shape[0]
def columnCount(self, parent=None):
return self._data.shape[1]
def data(self, index, role=Qt.ItemDataRole.DisplayRole):
if index.isValid():
if role == Qt.ItemDataRole.DisplayRole or role == Qt.ItemDataRole.EditRole:
if self._data.columns[index.column()]=='Delete':
return ''
value = self._data.iloc[index.row(), index.column()]
return str(value)
class MyWindow(QMainWindow):
def __init__(self, *args):
QMainWindow.__init__(self, *args)
table_model = TableModel(pd.DataFrame([['1', '1'], ['0', '0']]))
self.table_view = QTableView()
proxy_model = QSortFilterProxyModel(self)
proxy_model.setSourceModel(table_model)
self.table_view.setModel(table_model)
self.table_view.setSortingEnabled(True)
self.table_view.setItemDelegateForColumn(0, MyCheckboxDelegate(self))
for row in range(0, table_model.rowCount()):
self.table_view.openPersistentEditor(table_model.index(row, 0))
self.setCentralWidget(self.table_view)
app = QApplication(sys.argv)
window = MyWindow()
window.show()
sys.exit(app.exec_())
GePe is a new contributor to this site. Take care in asking for clarification, commenting, and answering.
Check out our Code of Conduct.