0

I'm using PyQt5 and would like to mark the line with a single click, that is, make it appear in a different color, e.g. in red. After another click on the same line, the marking should be canceled again.

I have tried different approaches (how to see in my code marked as comments), but didn't find a solution.

class TableViewModel(QtCore.QAbstractTableModel):
    def __init__(self, records, parent=None):
        super().__init__(parent)
        self.datatable = records
        self.color_enabled = False
        self.color_back = QtCore.Qt.magenta
        self.data_changed = pyqtSignal(QtCore.QModelIndex,QtCore.QModelIndex)                

    def rowCount(self, parent=QtCore.QModelIndex):
        return len(self.datatable)

    def columnCount(self, parent=QtCore.QModelIndex):
        return len(self.datatable[0]) if self.datatable else 0  

    def data(self, index, role, **kwargs): #role=QtCore.Qt.DisplayRole?
        #reason = kwargs.get('r', None)
        if index.isValid() and role == QtCore.Qt.DisplayRole:
            return str(self.datatable[index.row()][index.column()])
        if index.isValid() and role == QtCore.Qt.BackgroundRole and self.color_enabled:
            return gui.QBrush(gui.QColor(255, 0, 43))  #red



    def row_clicked(self, index, role = QtCore.Qt.BackgroundRole):
        # numeric position of dataset
        if index is not None:
            row = index.row()
            column = index.column()
            if column == 0:
                self.itemnumber = index.sibling(row, column)
                self.itemname = index.sibling(row, column + 1)
                self.itemsize = index.sibling(row, column + 2)
            elif column == 1:
                self.itemnumber = index.sibling(row, column - 1)
                self.itemname = index.sibling(row, column)
                self.itemsize = index.sibling(row, column + 1)
            elif column == 2:
                self.itemnumber = index.sibling(row, column - 2)
                self.itemname = index.sibling(row, column - 1)
                self.itemsize = index.sibling(row, column)

        return (self.itemnumber, self.itemname, self.itemsize, index) #return objects!!! no real datas
        #print("Ausgewählter Artikel: ",self.itemindex.data(), self.itemname.data(), self.itemsize.data())

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

    def headerData(self, section, orientation, role):
        if role == QtCore.Qt.DisplayRole and orientation == QtCore.Qt.Horizontal:
            return header_table_view[section]
        return QtCore.QAbstractTableModel.headerData(self, section, orientation, role)

    def setData(self, index, value, role=QtCore.Qt.DisplayRole):
        if role == QtCore.Qt.DisplayRole:
            row = index.row()
            column = index.column()
            color = gui.QColor(value)
            #data = value
            #self.datatable[row][column] = data
            #self.dataChanged.emit(index, index)
            return True    

    def changedData(self):
        self.data_changed.emit(pyqtSignal("DataChanged(QModelIndex,QModelIndex)"), self.createIndex(0, 0), self.createIndex(self.rowCount(0)), self.columnCount(0))


    def sort(self, column, order):
        #self.emit(pyqtSignal("layoutAboutToBeChanged()"))
        #self.layoutAboutToBeChanged.emit()
        self.sortCol = column
        self.sortOrder = order
        try:
            self.datatable = sorted(self.datatable, key = operator.itemgetter(column))
            self.data_changed.emit(pyqtSignal("layoutChanged()"))
        except:
            print("keine Sortierung möglich")
        #self.datatable.sort(key=itemgetter(column), reverse=order == QtCore.Qt.DescendingOrder)



    def insertRow(self, item, index=QtCore.QModelIndex()):
        """ Insert a row into the model. """
        #self.beginInsertRows(QtCore.QModelIndex(), position, position + rows - 1)
        TableViewModel.layoutAboutToBeChanged()
        self.append(item)
        TableViewModel.layoutChanged()
        reply = QtWidgets.QMessageBox.information(self, "Meldung zum Artikelliste", "Artikel erfolgreich hinzugefügt!")    
        return True
eyllanesc
  • 235,170
  • 19
  • 170
  • 241

1 Answers1

1

Because you don't provide an MRE I will provide an example created from scratch. I will also assume that when you say line you mean row.

The strategy is to use a role that stores the state (a boolean) of the row, and then change that value when the row is pressed. According to that state a custom delegate will be used to change the backgroundBrush that will be used for painting the items.

import random

from PyQt5 import QtCore, QtGui, QtWidgets


StateRole = QtCore.Qt.UserRole + 1000


class BackgroundColorDelegate(QtWidgets.QStyledItemDelegate):
    def initStyleOption(self, option, index):
        super().initStyleOption(option, index)
        print(index.data(StateRole))
        if index.data(StateRole):
            option.backgroundBrush = QtGui.QColor("red")


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

        self.model = QtGui.QStandardItemModel()
        for i in range(5):
            for j in range(4):
                value = random.randint(0, 10)
                it = QtGui.QStandardItem()
                it.setData(value, QtCore.Qt.DisplayRole)
                self.model.setItem(i, j, it)
        self.tableview = QtWidgets.QTableView()
        self.tableview.setModel(self.model)
        self.tableview.clicked.connect(self.on_clicked)

        delegate = BackgroundColorDelegate(self.tableview)
        self.tableview.setItemDelegate(delegate)

        self.setCentralWidget(self.tableview)

    @QtCore.pyqtSlot(QtCore.QModelIndex)
    def on_clicked(self, index):
        state = False
        for i in range(self.model.columnCount()):
            ix = self.model.index(index.row(), i)
            value = ix.data(StateRole)
            if value is not None:
                state = value
                break
        for i in range(self.model.columnCount()):
            ix = self.model.index(index.row(), i)
            self.model.setData(ix, not state, StateRole)


if __name__ == "__main__":
    import sys

    app = QtWidgets.QApplication(sys.argv)
    w = MainWindow()
    w.show()
    sys.exit(app.exec_())
eyllanesc
  • 235,170
  • 19
  • 170
  • 241