简体   繁体   English

更改点击PyQt的行颜色

[英]Changing Row Color On Click PyQt

I've been trying to work this for days, with no avail so hopefully you guys can help me. 我一直在努力工作数天,但无济于事,所以希望你们能帮助我。

I've got a custom QSqlTableModel that has this as it's data function: 我有一个自定义的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)

None of it's really relevant to the question except for the BackgroundRole block. 除了BackgroundRole块外,其他都与问题无关。 What I'm trying to do is when I right click on the tableview a context menu appears: 我想要做的是,当我右键单击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)

All I'm trying to do is when I click "Mark Step as Executed" on my context menu, I want the row (or even the cell, I'll take anything at this point) to change to red. 我要做的只是当我单击上下文菜单上的"Mark Step as Executed"时,我希望该行(甚至是单元格,此时我会采取任何措施)都变为红色。

Nothing of what I'm doing is working and I'm hoping someone can assist me. 我所做的一切都没有工作,我希望有人可以帮助我。

A simple solution would be to create a field in the database table and use as a flag to change the background colors, but if you can not make that change in the database you must create a new role. 一个简单的解决方案是在数据库表中创建一个字段并将其用作更改背景色的标志,但是如果您无法在数据库中进行此更改,则必须创建一个新角色。 and then we will use that role to make the necessary changes, for this we will save the flag in a dictionary, the key of the dictionary will be the id since these do not change. 然后我们将使用该角色进行必要的更改,为此,我们将标记保存在字典中,字典的键将是id,因为这些不变。

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

The above only change a selected item until it is refreshed manually, but this behavior is not the one that is wanted to do so the model dataChanged() signal must be issued. 上面的内容只更改一个选定的项目,直到手动刷新它为止,但是此行为不是想要的行为,因此必须发出model 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])

The current implementation has the advantage of being deselected if we change the state from True to False. 如果我们将状态从True更改为False,则当前实现的优点是被取消选择。

self.model().setData(index, False, SqlTableModel.ExecuteRole)

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM