Изменение цвета строки при нажатии PyQt

Я пытался работать с этим в течение нескольких дней, но безрезультатно, поэтому, надеюсь, вы, ребята, сможете мне помочь.

У меня есть пользовательский QSqlTableModel, который имеет эту функцию данных:

def data(self, index, role):
    #Formats Cells according to data in them
    if role == QtCore.Qt.TextAlignmentRole:
        if index.column() == 2:
            text = QtSql.QSqlTableModel.data(self, self.index(index.row(), 2), QtCore.Qt.DisplayRole)

            if text.split():
                if not re.search(r'start|Z[NARXTFEISL]|gv', text.split()[0], re.I):
                    return QtCore.Qt.AlignHCenter | QtCore.Qt.AlignTop
                else: return QtCore.Qt.AlignLeft
            else: pass
        else: return QtCore.Qt.AlignLeft

    if role == QtCore.Qt.BackgroundRole:
        if 'MILESTONE' in  QtSql.QSqlTableModel.data(self, self.index(index.row(), 2), QtCore.Qt.DisplayRole):
            return QtGui.QBrush(QtCore.Qt.yellow)


    return QtSql.QSqlTableModel.data(self, index, role)

Ничто из этого не имеет отношения к вопросу, кроме блока BackgroundRole. Что я пытаюсь сделать, так это когда я щелкаю правой кнопкой мыши tableview, появляется контекстное меню:

menu = QMenu()
stepx = menu.addAction('Mark Step as Executed')
stepdx = menu.addAction('Clear Step Execution')

action = menu.exec_(self.tableView.mapToGlobal(pos))
index = self.model.index(self.tableView.rowAt(pos.y()), 2)

if action == stepx:
    logging.info(' Executed Step: ' + str(self.tableView.rowAt(pos.y()) + 1))
    self.model.setData(index, QtCore.QVariant(QtGui.QBrush(QtCore.Qt.red)), QtCore.Qt.BackgroundRole)

Все, что я пытаюсь сделать, это когда я нажимаю "Mark Step as Executed" в своем контекстном меню, я хочу, чтобы строка (или даже ячейка, я возьму что угодно) стала красной.

Ничто из того, что я делаю, не работает, и я надеюсь, что кто-то может мне помочь.


person aseylys    schedule 25.09.2017    source источник


Ответы (1)


Простым решением было бы создать поле в таблице базы данных и использовать его в качестве флага для изменения цвета фона, но если вы не можете внести это изменение в базу данных, вы должны создать новую роль. а затем мы будем использовать эту роль для внесения необходимых изменений, для этого мы сохраним флаг в словаре, ключ словаря будет идентификатором, поскольку они не меняются.

class SqlTableModel(QtSql.QSqlTableModel):
    ExecuteRole = QtCore.Qt.UserRole + 1

    def __init__(self, parent=None, db = QtSql.QSqlDatabase()):
        QtSql.QSqlTableModel.__init__(self, parent, db)
        self.d = {}

    def data(self, index, role):
        if role == self.ExecuteRole:
            _id = self.getId(index)
            if _id in self.d.keys():
                return self.d[_id]
            return False

        if role == QtCore.Qt.BackgroundRole:
            if self.data(index, self.ExecuteRole):
                return QtGui.QBrush(QtCore.Qt.red)
            if 'MILESTONE' in QtSql.QSqlTableModel.data(self, self.index(index.row(), 2), QtCore.Qt.DisplayRole):
                return QtGui.QBrush(QtCore.Qt.yellow)

        return QtSql.QSqlTableModel.data(self, index, role)

    def getId(self, index):
        ix = self.fieldIndex("id")
        return self.data(self.index(index.row(), ix), QtCore.Qt.DisplayRole)

    def setData(self, index, value, role):
        if role == self.ExecuteRole:
            self.d[self.getId(index)] = value
            return True
        return QtSql.QSqlTableModel.setData(self, index, value, role)

    def roleNames(self):
        rn = QtSql.QSqlTableModel.roleNames(self)
        rn[self.SelectRole] = QtCore.QByteArray(b'execute')
        return rn

Вышеизложенное изменяет только выбранный элемент, пока он не будет обновлен вручную, но это не то поведение, которое требуется, поэтому должен быть выдан сигнал модели dataChanged().

class TableView(QtWidgets.QTableView):
    def contextMenuEvent(self, event):
        pos = event.pos()
        menu = QtWidgets.QMenu()
        stepx = menu.addAction('Mark Step as Executed')
        stepdx = menu.addAction('Clear Step Execution')

        action = menu.exec_(self.mapToGlobal(pos))
        if action == stepx:
            if self.model():
                index = self.model().index(self.rowAt(pos.y()), 2)
                self.model().setData(index, True, SqlTableModel.ExecuteRole)
                self.model().dataChanged.emit(self.model().index(index.row(), 0),
                                              self.model().index(index.row(), self.model().columnCount()-1),
                                              [QtCore.Qt.BackgroundRole])

Преимущество текущей реализации состоит в том, что ее выбор будет отменен, если мы изменим состояние с True на False.

self.model().setData(index, False, SqlTableModel.ExecuteRole)
person eyllanesc    schedule 25.09.2017
comment
Большое спасибо за это! Это работает в том смысле, что он действительно меняет цвет, и мне нравится, что я могу вернуть цвет. Однако кажется, что вся таблица краснеет. Не только выбранная строка. С чего бы это? - person aseylys; 25.09.2017
comment
Ты уверен? В моем тесте просто измените выбранную строку, попробуйте следующий пример и дайте мне знать, если у вас возникнет такая же ошибка: >gist.github.com/eyllanesc/150e981878122e171bd25dc470781a87 - person eyllanesc; 25.09.2017
comment
Если вы поделитесь своим проектом, чтобы проверить, где вы допустили ошибку. Если мой ответ поможет вам, не забудьте отметить его как правильный, пожалуйста. - person eyllanesc; 25.09.2017
comment
Ваш пример работает, а мой нет. Я считаю, что это как-то связано с тем, как я инициализирую qTableView. Но вот мой проект на данный момент. github.com/aseylys/sView РЕДАКТИРОВАТЬ: И я отметил вас как ответившего, потому что вы это сделали, это мои программы неумение сотрудничать вот в чем проблема - person aseylys; 25.09.2017
comment
@aseylys Как мне загрузить базу данных? Я не вижу никаких данных в таблице. - person eyllanesc; 25.09.2017
comment
File->Open Script, извините, я еще не добрался до README. - person aseylys; 25.09.2017
comment
Проблема в том, что у вас нет первичного ключа в вашей таблице, но я думаю, что Row # можно использовать, изменив: ix = self.fieldIndex("id") на ix = self.fieldIndex("Row #") - person eyllanesc; 25.09.2017