在PyQT5中对Item类在选中时保持原有颜色的方法

自己的一个工具里面用到了QTreeWidget,因为涉及到股票数据的显示,所以在Item上,不同列的含义不同,所以颜色也不一样,比如红色上涨,绿色下跌等。但是用了后,发现选中后,自己设置的颜色就无效了。

我的需求如下:

1、选中一行Item后,前景色保持原样,只多了个背景颜色,醒目一点;

2、窗口失去焦点时,不要把颜色改成了Inactive类型的颜色,还是保持原来的颜色,但是背景色可以变暗一点。

摸了半天,终于搞成了,我用了StyleSheet,所以还踩了坑,下面给出主要的做法吧,应该对QListWidget,QTrableWidget都类似。

首先,你需要定义前景色,比如第10列是根据正负显示不同的颜色,有类似这样的语句:

col = 10
if val > 0:
    item.setData(col, Qt.ItemDataRole.ForegroundRole, QColor(0xFF0000))
elif val < 0:
    item.setData(col, Qt.ItemDataRole.ForegroundRole, QColor(0x00FF00))
else:
    item.setData(col, Qt.ItemDataRole.ForegroundRole, QColor(0xFFFFFF))

然后,你需要重载 QStyledItemDelegate,如果没用到StyleSheet就用 QItemDelegate(我一开始没注意,照网上的用的这个,发现没有任何效果),重载函数一样。

class MyDelegate(QtWidgets.QStyledItemDelegate):
    '''重载后,绘制Item的时候,使文字的前景色保持不变'''
    def paint(self, painter, option, index):
        if option.state & QtWidgets.QStyle.StateFlag.State_Selected: # 只针对选中了的行
            # 根据窗口状态,获取ColorGroup
            cg = (
                QtGui.QPalette.ColorGroup.Normal
                if option.state & QtWidgets.QStyle.StateFlag.State_Enabled
                else QtGui.QPalette.ColorGroup.Disabled
            )
            # 对失去焦点重新计算cg
            if cg == QtGui.QPalette.ColorGroup.Normal and not (option.state & QtWidgets.QStyle.StateFlag.State_Active):
                cg = QtGui.QPalette.ColorGroup.Inactive

            # 记录先前的高亮颜色
            old_c = option.palette.color(QtGui.QPalette.ColorRole.HighlightedText)
            # 提取程序自己设置的前景色
            itemForegroundColor = index.data(Qt.ItemDataRole.ForegroundRole)
            if itemForegroundColor is not None:
                c = itemForegroundColor
            else: # 如果没设置前景色的item,直接使用文本色
                c = option.palette.color(QtGui.QPalette.ColorRole.Text)
            
            # 修改option中的高亮颜色并绘制
            option.palette.setColor(cg, QtGui.QPalette.ColorRole.HighlightedText, c)
            super().paint(painter, option, index)

            # 恢复先前的颜色
            option.palette.setColor(cg, QtGui.QPalette.ColorRole.HighlightedText, old_c)
        else: # 没选中的默认绘制
            super().paint(painter, option, index)

然后,在QTreeWidget初始化的地方,加一行:

treeWidget = QTreeWidget()
# ...
treeWidget.setItemDelegate(MyDelegate())

把我的style也列一下:


        QTreeWidget {
            show-decoration-selected: 1;
            outline: none;
        }
        QHeaderView::section {
            background-color:black;
            border:1px solid #3f3f3f;
            text-align:center;
            qproperty-defaultAlignment: AlignHCenter;
        }
        QTreeWidget::item {
            border: 1px solid #0f0f0f;
            margin:0px;
            padding:2px;
            qproperty-defaultAlignment: AlignHCenter;
        }
        QTreeWidget::item:selected:active {
            background-color:#000064;
        }
        QTreeWidget::item:selected:!active {
            background-color:#000032;
        }

看看效果图:

选中时:

  失去焦点后:

仅供参考 !

  • 1
    点赞
  • 6
    收藏
    觉得还不错? 一键收藏
  • 2
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值