Search code examples
pythonpython-3.xpyside2qabstracttablemodelqitemdelegate

Text can be seen behind delegate widgets in QTableView


I have a QTableView that uses QItemDelegate and QAbstractTableModel. A row contains a QPushButton, QCheckBox, QCombobox and QTimeEdit. My issue is that text appears behind the widgets. When a cell containing the QPushButton and QCheckBox are selected and then deselected true or false appears behind the widget. The text given for QCombobox and QTimeEdit are also visible behind the widgets.

Minimal example:

import sys
from PySide2.QtWidgets import QApplication, QMainWindow, QWidget, QVBoxLayout, QPushButton, QItemDelegate, QTimeEdit, \
    QCheckBox, QComboBox, QTableView
from PySide2.QtCore import QAbstractTableModel, Qt, QTime
from PySide2.QtGui import QIcon


class Delegate(QItemDelegate):

    def __init__(self):
        QItemDelegate.__init__(self)

        self.type_items = ["Job", "Activity"]

    def createEditor(self, parent, option, index):

        # CHECKBOX, COMBOBOX, LINEEDIT, TIMEDIT
        if index.column() == 0:
            pushButton = QPushButton(parent)
            # icon = QIcon("Images/cross.png")
            # pushButton.setIcon(icon)
            return pushButton
        elif index.column() == 1:
            checkBox = QCheckBox(parent)
            return checkBox
        elif index.column() == 2:
            comboBox = QComboBox(parent)
            for text in self.type_items:
                comboBox.addItem(text, (index.row(), index.column()))
            return comboBox
        elif index.column() == 3:
            timeEdit = QTimeEdit(parent)
            timeEdit.setDisplayFormat('HH:mm')
            return timeEdit
        return super().createEditor(parent, option, index)


class TableModel(QAbstractTableModel):
    def __init__(self, data):
        super(TableModel, self).__init__()
        self._data = data

    def data(self, index, role):
        if role in (Qt.DisplayRole, Qt.EditRole):
            return self._data[index.row()][index.column()]

    def rowCount(self, index=None):
        return len(self._data)

    def columnCount(self, index=None):
        return len(self._data[0])

    def flags(self, index):
        return super().flags(index) | Qt.ItemIsEditable

    def setData(self, index, value, role=Qt.EditRole):
        if role == Qt.EditRole:
            self._data[index.row()][index.column()] = value
            self.dataChanged.emit(index, index)
            return True
        return False


class MainWindow(QMainWindow):
    def __init__(self, parent=None):
        super(MainWindow, self).__init__(parent)

        # PARENT WIDGET
        localWidget = QWidget()

        self.table = QTableView(localWidget)

        data = [["", Qt.CheckState.Checked, "Job", QTime(2, 1)], ["", Qt.CheckState.Unchecked, "Activity", QTime(3, 0)]]

        self.model = TableModel(data)
        self.table.setModel(self.model)
        self.table.setItemDelegate(Delegate())

        # VERTICAL LAYOUT
        layout_v = QVBoxLayout()
        layout_v.addWidget(self.table)
        localWidget.setLayout(layout_v)

        for row in range(self.model.rowCount()):
            for column in range(self.model.columnCount()):
                index = self.model.index(row, column)
                self.table.openPersistentEditor(index)

        col_widths = [40, 40, 90, 65]
        for col in range(self.model.columnCount()):
            self.table.setColumnWidth(col, col_widths[col])

        self.setCentralWidget(localWidget)
        self.show()


app = QApplication(sys.argv)
window = MainWindow()
window.show()
sys.exit(app.exec_())

How can I stop the text showing behind the widgets?


Solution

  • A possible solution is that the text that is painted is an empty string.

    class Delegate(QItemDelegate):
        def __init__(self):
            QItemDelegate.__init__(self)
    
            self.type_items = ["Job", "Activity"]
    
        def drawDisplay(self, painter, option, rect, text):
            super().drawDisplay(painter, option, rect, "")
    
        def createEditor(self, parent, option, index):
            # ...