PyQt5 更改 QAbstractTableModel 中的 BackgroundRole 设置

Posted

技术标签:

【中文标题】PyQt5 更改 QAbstractTableModel 中的 BackgroundRole 设置【英文标题】:PyQt5 Change BackgroundRole Settings in QAbstractTableModel 【发布时间】:2020-05-07 01:46:36 【问题描述】:

我在 PyQT5 中使用 QTableView 来显示数据表。

我可以根据条件设置每个单元格的背景颜色。例如将单元格变为红色:

class TableModel(QtCore.QAbstractTableModel):

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

    def data(self, index, role):

        if role == Qt.BackgroundRole:
            if condition == ...
                return QtGui.QColor('#9C0006')

但是,我不想将背景颜色应用于整个单元格,而是仅将颜色应用于单元格的一部分(基于单元格的值)。比如这样:

QT 是否可以做到这一点,如果可以,我需要更改哪些设置?我相信QBrush 允许我设置填充模式(即像上图一样的渐变),但是是否有类可以处理相对于单元格大小的背景颜色“项目”的 size ,它在单元格内的位置?

更新:

我现在在 Python 中有以下代码,它将渐变的长度设置为单元格宽度的 50%(我以后可以动态设置)。

if role == Qt.BackgroundRole:
    percent = 0.5

    gradient = QtGui.QLinearGradient(QtCore.QPointF(0, 0), QtCore.QPointF(1, 0))
    gradient.setColorAt(0, Qt.red)
    gradient.setColorAt(percent, Qt.white)
    gradient.setColorAt(1, Qt.white)
    gradient.setCoordinateMode(QtGui.QLinearGradient.ObjectMode)


    return QtGui.QBrush(gradient)

这提供了以下格式:

有没有办法为每个单元格的顶部和底部提供 5% 的填充,以便渐变格式仅填充单元格垂直空间的 90%,而不是当前的 100%? IE。像这样的东西(见前 3 行)。

我想我需要设置 QBrush 坐标以便 QBrush 操作只发生在部分单元格上?但是,我似乎在 QBrush 文档中找不到与坐标相关的任何内容。这可能吗?

【问题讨论】:

这种行为只能通过项目委托实现,并通过覆盖其paint() 方法。如果您已经尝试过,请向我们提供 minimal, reproducible example,否则请对此进行一些研究,然后通过提供上述 MRE 来编辑您的问题,以防您仍需要帮助。 谢谢,我试试看。 @musicamante,使用项目委托不是义务。您可以使用QBrushQLinearGradient 中的Qt::BackgroundRole 实现此行为 @thibsc 是的,你完全正确。恐怕我已经习惯了代表(而且也很累......),以至于我没有考虑过最简单的解决方案。 您在编辑中询问的是完全不同的问题:完整的项目绘制取决于样式,因此在这种情况下可能需要委托(或至少使用 QStyleProxy);我建议您创建一个新问题。 【参考方案1】:

这种行为可以通过使用QBrushQGradient来实现,我给你一个Qt C++的例子,只适应python:

QBrush::QBrush(const QGradient &gradient)QLinearGradient

QVariant data(const QModelIndex &index, int role) const override 
    QVariant ret;
    if (index.isValid())
        if (role == Qt::BackgroundRole)
            bool convert = false;
            double percent = index.data().toDouble(&convert);
            if (convert)
                QColor c = (percent < 25 ? Qt::red
                             : (percent < 50 ? Qt::yellow
                                 : (percent < 75 ? Qt::green : Qt::cyan)));
                QLinearGradient grad(QPointF(0, 0), QPointF(1, 0));
                grad.setCoordinateMode(QGradient::CoordinateMode::ObjectBoundingMode);
                grad.setColorAt(0, c);
                grad.setColorAt(percent/100.0, Qt::white);
                grad.setColorAt(1, Qt::white);

                ret = QBrush(grad);
            
         else 
            ret = QAbstractTableModel::data(index, role);
        
    
    return ret;


结果:你会得到这样的结果:

【讨论】:

我建议做一个小的修改:使用Qt::white 并不总是一件好事,特别是如果当前样式使用不同的Base 调色板颜色,或者如果项目视图的背景使用自定义样式表或调色板:Qt::transparent 可能会更一致。我还会根据实际的 python 代码调整您的答案,因为问题使用该语言,但我通常不喜欢编辑答案;如果您对此感到满意并且不能/不会自己做,请告诉我。 @musicamante,如果当然Qt::transparent 更好,是的。这只是一个简单的示例,如果您想为 python 进行编辑,我没问题,但我认为即使在 C++ 中答案也很有帮助,因为在 python 中翻译这段代码并不困难;) @thibsc 是的,即使在 C++ 中也很有帮助,它给了我可以适应 python 的总体思路 :)

以上是关于PyQt5 更改 QAbstractTableModel 中的 BackgroundRole 设置的主要内容,如果未能解决你的问题,请参考以下文章

Pyqt5 qtablewidget 检测单元格何时更改

Pyqt5 检查按钮颜色并更改按钮颜色

在pyqt5中动态更改数据破折号

PyQt5 动态更改应用程序主题/调色板

更改 PyQt5 的调色板

PyQT5 复选框更改指示器和刻度颜色