Skip to content

Instantly share code, notes, and snippets.

@eyllanesc
Last active December 15, 2020 11:05
Show Gist options
  • Save eyllanesc/ade64a8cd1bd534d473b51a3aec888c5 to your computer and use it in GitHub Desktop.
Save eyllanesc/ade64a8cd1bd534d473b51a3aec888c5 to your computer and use it in GitHub Desktop.
from PySide2.QtCore import Qt, QSize, QRect, QEvent
from PySide2.QtWidgets import QStyledItemDelegate, QStyleOptionViewItem, QApplication, QStyle, QTableWidget, \
QTableWidgetItem
class ItemDelegate(QStyledItemDelegate):
def paint(self, painter, option, index):
opt = QStyleOptionViewItem(option)
if index.column() == 0:
textMargin = QApplication.style().pixelMetric(QStyle.PM_FocusFrameHMargin) + 1
newRect = QStyle.alignedRect(option.direction, Qt.AlignCenter,
QSize(option.decorationSize.width() + 5,
option.decorationSize.height()),
QRect(option.rect.x() + textMargin, option.rect.y(),
option.rect.width() - (2 * textMargin),
option.rect.height()))
opt.rect = newRect
QStyledItemDelegate.paint(self, painter, opt, index)
def editorEvent(self, event, model, option, index):
flags = model.flags(index)
if not (flags & Qt.ItemIsUserCheckable) or not (flags & Qt.ItemIsEnabled):
return False
value = index.data(Qt.CheckStateRole)
if event.type() == QEvent.MouseButtonRelease:
textMargin = QApplication.style().pixelMetric(QStyle.PM_FocusFrameHMargin) + 1
checkRect = QStyle.alignedRect(option.direction, Qt.AlignCenter,
option.decorationSize,
QRect(option.rect.x() + (2 * textMargin),
option.rect.y(),
option.rect.width() - (2 * textMargin),
option.rect.height()))
if not checkRect.contains(event.pos()):
return False
elif event.type() == QEvent.KeyPress:
if event.key() != Qt.Key_Space and event.key() != Qt.Key_Select:
return False
else:
return False
state = Qt.Unchecked if value == Qt.Checked else Qt.Checked
return model.setData(index, state, Qt.CheckStateRole)
class Table(QTableWidget):
def __init__(self):
QTableWidget.__init__(self, 3, 1)
self.setItemDelegate(ItemDelegate(self))
for i in range(self.rowCount()):
for j in range(self.columnCount()):
it = QTableWidgetItem()
self.setItem(i, j, it)
it.setFlags(Qt.ItemIsEnabled | Qt.ItemIsUserCheckable)
it.setCheckState(Qt.Checked if (i + j) % 2 == 0 else Qt.Unchecked)
if __name__ == '__main__':
import sys
app = QApplication(sys.argv)
w = Table()
w.show()
sys.exit(app.exec_())
@sharpordie
Copy link

Thanks for this code snippet.
Would you know how to remove the weird thing on the right side of the active cell?

@eyllanesc
Copy link
Author

eyllanesc commented Oct 11, 2020

@sharpordie try with this code:

from PySide2.QtCore import Qt
from PySide2.QtWidgets import (
    QApplication,
    QProxyStyle,
    QStyle,
    QTableWidget,
    QTableWidgetItem,
)


class ProxyStyle(QProxyStyle):
    def subElementRect(self, e, opt, widget):
        r = super().subElementRect(e, opt, widget)
        if e == QStyle.SE_ItemViewItemCheckIndicator:
            r.moveCenter(opt.rect.center())
        return r


class Table(QTableWidget):
    def __init__(self):
        QTableWidget.__init__(self, 3, 1)
        self._style = ProxyStyle(self.style())
        self.setStyle(self._style)
        for i in range(self.rowCount()):
            for j in range(self.columnCount()):
                it = QTableWidgetItem()
                self.setItem(i, j, it)
                it.setFlags(Qt.ItemIsEnabled | Qt.ItemIsUserCheckable)
                it.setCheckState(Qt.Checked if (i + j) % 2 == 0 else Qt.Unchecked)


if __name__ == "__main__":
    import sys

    app = QApplication(sys.argv)
    w = Table()
    w.show()
    sys.exit(app.exec_())

@sharpordie
Copy link

Sorry for the HUGE delay.
Thank you very much, it's working perfectly.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment