当前位置: 首页 > article >正文

PySide6如何使用自定义委托实现在TableWidget填充颜色

1. 实现的效果

信号在报文中的排布最直观的是用不同颜色表示,有几个信号表格中就有几种颜色,一个信号最少占用一个bit,也就是说一条长度为8个字节的报文最多可以有64种不同的颜色。需要64种不同的颜色,想要通过一个8*8的表格选取不同单元格的颜色实现采集64种不同颜色的目的。

在这里插入图片描述

2. 使用自定义委托实现TableWidget单元格颜色填充

在 QTableWidget 中为指定单元格设置委托并不是直接通过某个方法来实现的,因为 QTableWidget 提供的接口主要是为整行、整列或整个表格设置委托(通过 setItemDelegateForRow, setItemDelegateForColumn, 或 setItemDelegate 方法)。然而,你可以通过一些技巧来为特定的单元格实现不同的委托行为。

一种方法是使用自定义委托,并在委托内部根据单元格的索引(或其他条件)来决定如何绘制和编辑该单元格。这通常涉及到在 paint 和 createEditor 方法中添加额外的逻辑。

委托是一种用于绘制和编辑数据的对象,它允许你自定义单元格的显示和编辑行为。
自定义委托通常用于以下情况:

当你需要改变单元格的绘制方式时,比如改变文本的颜色、字体,或者添加图标、背景色等。
当你需要为单元格提供自定义的编辑器,比如一个下拉列表、一个日期选择器或是一个滑块。
当你需要处理复杂的交互逻辑,比如点击单元格时显示一个工具提示,或者实现拖放功能。

2.1 使用自定义委托实现的程序代码

#!/usr/bin/env python
# -*- coding: utf-8 -*-
# @Author : Logintern09

from PySide6.QtWidgets import (
    QApplication,
    QTableWidget,
    QStyledItemDelegate,
)
from PySide6.QtGui import QColor, QPen, QBrush, QFont
from PySide6.QtCore import Qt, QRect


class ArrowDelegate(QStyledItemDelegate):
    def __init__(self, color_lst, table_widget, parent=None):
        super().__init__(parent)
        self.color_lst = color_lst
        self.table_widget = table_widget

    def _cal_cell_num(self, index):
        row = index.row()
        column = index.column()
        num = row * 8 + column
        return num

    def paint(self, painter, option, index):
        cell_num = self._cal_cell_num(index)
        color = self.color_lst[cell_num]
        self._draw_cell_color(painter, option, color)

        # 绘制表征单元格索引的数字
        self._draw_cell_num(painter, option, index)
        # 绘制表征单元格颜色的十六进制颜色数字
        self._draw_color_text(painter, option, color)

    def _draw_cell_color(self, painter, option, color):
        # 创建一个 QBrush 对象
        brush = QBrush(color)
        # 使用 QPainter 的 setBrush 方法来设置填充颜色
        painter.setBrush(brush)
        # 绘制单元格的背景
        painter.drawRect(option.rect)

    def _draw_color_text(self, painter, option, color_name):
        # 获取目标单元格的矩形区域
        cell_rect = option.rect

        # 设置文本颜色和字体(可选)
        painter.setPen(QPen(QColor(0, 0, 0)))  # 黑色文本
        font = QFont()
        font.setPointSize(5)  # 设置字体大小(可选)
        painter.setFont(font)

        text_rect = QRect(
            cell_rect.left(),  # 文本左边缘与单元格左边缘对齐
            cell_rect.top() + 2,
            cell_rect.width(),  # 文本宽度与单元格宽度相同(可以根据需要调整)
            painter.fontMetrics().height(),  # 文本高度
        )
        painter.drawText(text_rect, Qt.AlignLeft | Qt.AlignVCenter, str(color_name))

    def _draw_cell_num(self, painter, option, index):
        # 获取目标单元格的矩形区域
        cell_rect = option.rect

        # 设置文本颜色和字体(可选)
        painter.setPen(QPen(QColor(0, 0, 0)))  # 黑色文本
        font = QFont()
        font.setPointSize(5)  # 设置字体大小(可选)
        painter.setFont(font)

        # 计算文本的位置
        text_rect = QRect(
            cell_rect.right() - 10,
            cell_rect.bottom()
            - 3
            - painter.fontMetrics().height(),  # 距离单元格底部3像素,并减去文本高度以确保文本不超出单元格
            cell_rect.width(),  # 文本宽度与单元格宽度相同(可以根据需要调整)
            painter.fontMetrics().height(),  # 文本高度
        )
        cell_num = self._cal_cell_num(index)
        painter.drawText(text_rect, Qt.AlignLeft | Qt.AlignVCenter, str(cell_num))


class BasicTableWidget(QTableWidget):

    def __init__(self, parent=None):
        super(BasicTableWidget, self).__init__(parent)

        self.table_widget = QTableWidget(8, 8, self)
        self.table_widget.setFixedSize(700, 400)  # 设置固定大小
        self.table_widget.setHorizontalHeaderLabels([f"{i}" for i in range(8)])
        self.table_widget.setVerticalHeaderLabels([f"{i}" for i in range(8)])
        self._ini_table_style()

        self.color_lst = self._get_color_lst()

    def _ini_table_style(self):
        # self.table_widget.verticalHeader().hide()
        # self.table_widget.horizontalHeader().hide()
        self.set_cell_width()
        self.set_cell_height()
        # Set the selection mode to allow extended (multiple) selection
        self.table_widget.setSelectionMode(QTableWidget.ExtendedSelection)
        style_sheet = """
               QHeaderView::section {
                   background-color: #f0f0f0;  /* 可以设置背景色为浅灰色,如果需要的话 */
                   color: #808080;            /* 设置文字颜色为灰色 */
                   padding: 4px;              /* 可选:设置内边距 */
                   border: 1px solid #d0d0d0;  /* 可选:设置边框 */
               }
               """
        self.table_widget.setStyleSheet(style_sheet)

    def set_cell_width(self):
        for col in range(self.table_widget.columnCount()):
            self.table_widget.setColumnWidth(col, 80)

    def set_cell_height(self):
        for row in range(self.table_widget.rowCount()):
            self.table_widget.setRowHeight(row, 40)

    def _get_color_lst(self):
        color_lst = [
            "#FF5733",
            "#33FF57",
            "#00BFFF",  # 深天蓝色
            "#FFBF00",  # 黄橙色
            "#2196F3",
            "#FFEB3B",
            "#4CAF50",
            "#E91E63",
            "#9C27B0",
            "#93DB70",
            "#03A9F4",
            "#03DAC5",
            "#00BCD4",
            "#DBDB70",
            "#1ABC9C",
            "#2ECC71",
            "#E74C3C",
            "#C0392B",
            "#2980B9",
            "#F2784B",
            "#F1C40F",
            "#16A085",
            "#27AE60",
            "#E67E22",
            "#D35400",
            "#9370DB",
            "#9B59B6",
            "#F39C12",
            "#D2B48C",
            "#ECC74C",
            "#3498DB",
            "#9B5DE5",
            "#1E90FF",
            "#B22222",
            "#FF1493",
            "#DA70D6",
            "#8A2BE2",
            "#8FBC8F",
            "#4682B4",
            "#FAFAD2",
            "#FAF0E6",
            "#FFE4E1",
            "#FFB6C1",
            "#FFA07A",
            "#FF69B4",
            "#CD5C5C",
            "#FFA500",
            "#FFD700",
            "#ADFF2F",
            "#DEB887",
            "#FA8072",
            "#7FFF00",
            "#7FFFD4",
            "#00FFFF",
            "#7CFC00",
            "#ADD8E6",
            "#E0FFFF",
            "#90EE90",
            "#AFEEEE",
            "#DB7093",
            "#FFE4B5",
            "#FFDAB9",
            "#FF6347",
            "#FF4500",
        ]
        return color_lst

    def set_cell_style(self):
        # 创建并设置自定义委托
        arrow_delegate = ArrowDelegate(self.color_lst, self.table_widget)
        self.table_widget.setItemDelegate(arrow_delegate)


class QLayoutWidget(BasicTableWidget):

    def __init__(self, parent=None):
        super(QLayoutWidget, self).__init__(parent)
        self.setWindowFlags(self.windowFlags() | Qt.FramelessWindowHint)
        self.setAttribute(Qt.WA_TranslucentBackground)
        self.setFixedSize(700, 400)

        self.set_cell_style()


if __name__ == "__main__":
    app = QApplication([])
    widget = QLayoutWidget()
    widget.show()
    app.exec()

3. 直接修改TableWidget单元格的背景颜色实现

除了上述自定义委托实现TableWidget单元格的背景颜色填充外,更为直接的方法是直接修改TableWidget单元格的背景颜色实现。

3.1 设置TableWidget单元格的背景颜色

    def set_table_background_color(self, color_lst):
        cell_count = -1
        for row in range(self.table_widget.rowCount()):
            for col in range(self.table_widget.columnCount()):
                cell_count += 1
                item = self.table_widget.item(row, col)
                if item is None:
                    item = QTableWidgetItem()
                    self.table_widget.setItem(row, col, item)
                item.setBackground(QColor(color_lst[cell_count]))

在这里插入图片描述

3.2 将表示颜色的十六进制数值标识在TableWidget单元格的左上角

在 PySide6(或 PyQt6)中,QTableWidget 并没有直接提供设置文本在单元格左上角显示的方法,因为通常单元格的内容是居中对齐的,并且没有内置的属性或方法来改变这种对齐方式并添加额外的文本。

你可以通过子类化 QTableWidgetItem 并重写其 paint 方法来在单元格的左上角绘制自定义文本。

重写 paint 方法
通过重写 paint 方法,你可以完全控制单元格的绘制过程,包括文本的位置、颜色和样式。

paint 方法
使用 painter.save() 和 painter.restore() 保存和恢复画家状态,确保对画家状态的修改不会影响后续绘制。
设置文本颜色和字体。
计算左上角文本的位置和大小。
使用 painter.drawText 在指定位置绘制文本。

class CustomTableWidgetItem(QTableWidgetItem):
    def __init__(self, text, *args, **kwargs):
        super().__init__(text, *args, **kwargs)
        self.text = text

    def paint(self, painter, option, index):
        # 设置文本颜色和字体(可选)
        painter.setPen(QPen(QColor(0, 0, 0)))  # 黑色文本
        font = QFont()
        font.setPointSize(5)  # 设置字体大小(可选)
        painter.setFont(font)

        # Calculate the position for the corner text
        cell_rect = option.rect
        text_rect = QRect(
            cell_rect.left(),  # 文本左边缘与单元格左边缘对齐
            cell_rect.top() + 2,
            cell_rect.width(),  # 文本宽度与单元格宽度相同(可以根据需要调整)
            painter.fontMetrics().height(),  # 文本高度
        )

        # Draw the corner text
        painter.drawText(text_rect, Qt.AlignLeft | Qt.AlignVCenter, self.text)

        painter.restore()

使用 CustomTableWidgetItem 填充表格,并设置每个单元格的左上角文本。实现写入单元格左上角文本之后的设置单元格背景的**函数set_table_background_color()**修改如下:

    def set_table_background_color(self, color_lst):
        cell_count = -1
        for row in range(self.table_widget.rowCount()):
            for col in range(self.table_widget.columnCount()):
                cell_count += 1
                item = self.table_widget.item(row, col)
                if item is None:
                    item = CustomTableWidgetItem(str(color_lst[cell_count]))
                    self.table_widget.setItem(row, col, item)
                item.setBackground(QColor(color_lst[cell_count]))

最终实现的界面效果如下:

在这里插入图片描述


http://www.kler.cn/a/446806.html

相关文章:

  • 二叉搜索树Ⅲ【东北大学oj数据结构8-3】C++
  • App自动化之dom结构和元素定位方式(包含滑动列表定位)
  • C# winform 字符串通过枚举类型转成int类型的数据
  • PC寄存器(Program Counter Register) jvm
  • 有关异步场景的 10 大 Spring Boot 面试问题
  • 源码分析之Openlayers中OverviewMap鹰眼控件
  • CTF 伪造ip的http请求头(学习记录)
  • sql server 查询对象的修改时间
  • 1. 深度学习介绍
  • winpcap抓包原理
  • 记忆组合数据知识
  • 基于LSTM和SSUN模型的高光谱遥感分类实现
  • PCL点云库入门——PCL库中点云数据拓扑关系之K-D树(KDtree)
  • 1、学习大模型总纲
  • FreeRTOS的任务调度
  • 全志H618 Android12修改doucmentsui鼠标单击图片、文件夹选中区域
  • Suno Api V4模型无水印开发「高清音频WAV下载」 —— 「Suno Api系列」第6篇
  • netcore 集成Prometheus
  • 大数据-环保领域
  • 【1.排序】
  • 【Linux】-学习笔记10
  • 呼入机器人:24小时客户服务的未来趋势
  • 秒优科技-供应链管理系统 login/doAction SQL注入漏洞复现
  • Oracle筑基篇-通过一个事务流程筑基Oracle
  • 基于mmdetection进行语义分割(不修改源码)
  • 怎么通过亚矩阵云手机实现营销?