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

【Python、Qt】使用QItemDelegate实现单元格的富文本显示+复选框功能

主打一个 折磨 坑多 陪伴。代码为Python,C++的就自己逐条语句慢慢改吧。



Python代码:

import sys
from types import MethodType
from PyQt5.QtCore import Qt,QPoint,QSize,QRect,QEvent
from PyQt5.QtGui import QStandardItemModel, QStandardItem,QTextDocument,QTextCursor
from PyQt5.QtWidgets import QTreeView,QApplication,QItemDelegate,QStyleclass RichDelegate(QItemDelegate):#使用QItemDelegate进行单元格重绘:https://blog.csdn.net/Loc_Haoclass/article/details/106528047__cboxSize=QSize(14,14)#复选框大小__cboxAlignV=Qt.AlignVCenter#竖直位置(居中)__cboxAlignH=Qt.AlignLeft#水平位置(左对齐)def __init__(self,parent=None,*,align=None,size=None):super().__init__(parent)if(align):self.SetCheckboxAlign(align)if(size):self.SetCheckboxSize(size)def SetCheckboxAlign(self,align):#设置复选框位置alignV=[Qt.AlignTop,Qt.AlignVCenter,Qt.AlignBottom]alignH=[Qt.AlignLeft,Qt.AlignHCenter,Qt.AlignRight]alignV=list(filter(lambda a:int(align) & int(a)!=0,alignV))alignH=list(filter(lambda a:int(align) & int(a)!=0,alignH))alignV.append(Qt.AlignVCenter)alignH.append(Qt.AlignLeft)self.__cboxAlignV=alignV[0]self.__cboxAlignH=alignH[0]def SetCheckboxSize(self,size):#设置复选框大小self.__cboxSize=sizedef editorEvent(self,event,model,opt,index):#处理复选框点击逻辑:https://blog.csdn.net/xbnlkdbxl/article/details/51316424if(event.type()==QEvent.MouseButtonRelease):#仅处理鼠标抬起事件if(event.button()==Qt.LeftButton):#仅处理鼠标左键item=index.model().itemFromIndex(index)if(item.isCheckable()):#仅处理复选框存在的情况rect_cbox=self.__GetRect_Checkbox(opt.rect)if(rect_cbox.contains(event.pos())):#仅复选框被点击时翻转状态item.setCheckState(Qt.Unchecked if item.checkState()==Qt.Checked else Qt.Checked)return Truereturn Falsedef drawCheck(self,ptr,opt,rect,state):#绘制复选框(这里直接默认绘制,有想法的可以改成其他绘制例如画个圈之类的super().drawCheck(ptr,opt,rect,state)#默认绘制的复选框总是正方形def paint(self,ptr,opt,index):style=opt.widget.style() if opt.widget else QApplication.style()style.drawControl(QStyle.CE_ItemViewItem, opt, ptr, opt.widget)#这条语句解决了行选中时背景色不变化的问题:https://blog.csdn.net/gongjianbo1992/article/details/108687172rect=QRect(opt.rect)item=index.model().itemFromIndex(index)if(item.isCheckable()):#绘制复选框:https://blog.csdn.net/xbnlkdbxl/article/details/51316424rect_cbox=self.__GetRect_Checkbox(rect)self.drawCheck(ptr,opt,rect_cbox,item.checkState())#计算剩余位置用于绘制文本内容if(self.__cboxAlignH==Qt.AlignRight):#只调整水平位置(应该不会有人那么异端把复选框放在单元格正中间的吧,不会吧不会吧rect.setRight(rect.right()-rect_cbox.width())else:rect.setLeft(rect.left()+rect_cbox.width())tx=index.data()doc=QTextDocument()doc.setHtml(tx)txDot='...'#替换为省略号testPoint=QPoint(rect.width(), rect.height() / 2)#获取能完整显示的字符个数:https://blog.csdn.net/eiilpux17/article/details/118461445pos = doc.documentLayout().hitTest(testPoint, Qt.ExactHit)if(pos!=-1 and pos !=len(doc.toPlainText())):#不能完全显示的情况下进行字符替换docDot=QTextDocument()docDot.setHtml(txDot)docDot.setDocumentMargin(0)#发现调用该语句后doc.size取值恢复正常:https://cloud.tencent.com/developer/ask/sof/105271901testPoint=QPoint(rect.width()-docDot.size().width(), rect.height() / 2)pos = doc.documentLayout().hitTest(testPoint, Qt.ExactHit)if(pos==-1):pos=0cursor=QTextCursor(doc)cursor.setPosition(pos)# cursor.insertText(txDot)cursor.movePosition(QTextCursor.End, QTextCursor.KeepAnchor)cursor.insertText(txDot,cursor.block().charFormat())LT=rect.bottomLeft()LT.setY(LT.y()-doc.size().height())# LT=rect.topLeft()ptr.save()ptr.translate(LT)ptr.setClipRect(rect.translated(-rect.topLeft()))# doc.setDefaultTextOption(doc.defaultTextOption())doc.drawContents(ptr)ptr.restore()def sizeHint(self,opt,index):#设置行高函数:https://blog.csdn.net/Lutx/article/details/6641353tx=index.data()doc=QTextDocument()doc.setHtml(tx)size=doc.size()return QSize(size.width(),size.height())def __GetRect_Checkbox(self,rect):#返回复选框确切位置alignV=[Qt.AlignTop,Qt.AlignVCenter,Qt.AlignBottom]alignH=[Qt.AlignLeft,Qt.AlignHCenter,Qt.AlignRight]posV=[rect.top(),rect.bottom()]posH=[rect.left(),rect.right()]for nape in [[self.__cboxAlignV,alignV,posV,self.__cboxSize.height()],[self.__cboxAlignH,alignH,posH,self.__cboxSize.width()]]:align,alignLst,pos,width=napeindex=alignLst.index(align)if(index==0):#靠左/靠上pos[1]=pos[0]+widthelif(index==1):#居中pos[0]=pos[0]+int((pos[1]-pos[0]-width)/2)pos[1]=pos[0]+widthelif(index==2):#靠右/靠下pos[0]=pos[1]-widthreturn QRect(posH[0],posV[0],posH[1]-posH[0],posV[1]-posV[0])if __name__ == '__main__':app = QApplication(sys.argv)tv=QTreeView()tv.setModel(QStandardItemModel(tv))model=tv.model()model.appendRow([QStandardItem(d) for d in ['<font color="red" size=3> R3 </font>']])model.appendRow([QStandardItem(d) for d in ['<font color="red" size=5> R5 </font>']])model.appendRow([QStandardItem(d) for d in ['<font color="red" size=7> R7 </font>']])model.appendRow([QStandardItem(d) for d in ['<font color="red" style="font-size:50px"> R50px </font>','<font style="background:#0000FF;font-size:70px">B70px</font>']])model.appendRow([QStandardItem(d) for d in ['<font size=5><sub>bbb</sub><sup>ppp</sup><br><s>SSS</s><i>III</i><u>UUU</u></font><br><font color="red" style="background:#00FFFF;font-size:20pt">R20pt</font>']])model.item(1,0).setCheckable(True)model.item(3,1).setCheckable(True)model.item(4,0).setCheckable(True)rich_1=RichDelegate()rich_2=RichDelegate(align=Qt.AlignBottom|Qt.AlignRight)#复选框右对齐是什么邪道行为,太怪了(感觉除了左居中以外的对齐都是邪道tv.setItemDelegateForRow(0,rich_1)tv.setItemDelegateForRow(1,rich_1)tv.setItemDelegateForRow(2,rich_1)tv.setItemDelegateForRow(3,rich_1)tv.setItemDelegateForRow(4,rich_2)tv.show()sys.exit(app.exec())

运行结果:

运行结果


补充:

1、我的代码仅完成富文本显示,像是往单元格里塞入按钮、下拉列表亦或是其他控件不在本篇讨论范围之内,有需要的可以参考[CSDN]QStyledItemDelegate单元格数据渲染与编辑、[51CTO]QTableWidget使用setCellWidget设置控件居中显示或是自行搜索其他文章
2、复选框的绘制样式甚至可以自定义,像是画成圆圈或是其他东西,又或是嫌黑色不好看改成紫色绿色啥的,只不过得自己实现就是了,重绘仅需QPainter倒少了挺多麻烦(只不过还是挺麻烦的所以没这需求就没必要自找麻烦


参考资料:

  • 使用QItemDelegate显示富文本:[CSDN]https://blog.csdn.net/Loc_Haoclass/article/details/106528047
  • QItemDelegate实现CheckBox复选框功能:[CSDN]https://blog.csdn.net/xbnlkdbxl/article/details/51316424
  • QStyledItemDelegate单元格数据渲染与编辑:[CSDN]https://blog.csdn.net/gongjianbo1992/article/details/108687172
  • 精确获取字符完整显示个数:[CSDN]https://blog.csdn.net/eiilpux17/article/details/118461445
  • QItemDelegate单元格设置行高:[CSDN]https://blog.csdn.net/Lutx/article/details/6641353

本文发布于CSDN,未经个人同意不得私自转载:https://blog.csdn.net/weixin_44733774/article/details/133838003

相关文章:

【Python、Qt】使用QItemDelegate实现单元格的富文本显示+复选框功能

主打一个 折磨 坑多 陪伴。代码为Python&#xff0c;C的就自己逐条语句慢慢改吧。 Python代码&#xff1a; import sys from types import MethodType from PyQt5.QtCore import Qt,QPoint,QSize,QRect,QEvent from PyQt5.QtGui import QStandardItemModel, QStandardItem,QTe…...

【JVM】JVM类加载机制

JVM类加载机制 加载双亲委派模型 验证准备解析初始化 JVM的类加载机制,就是把类,从硬盘加载到内存中 Java程序,最开始是一个Java文件,编译成.class文件,运行Java程序,JVM就会读取.class文件,把文件的内容,放到内存中,并且构造成.class类对象 加载 这里的加载是整个类加载的一…...

【面试经典150 | 区间】汇总区间

文章目录 Tag题目来源题目解读解题思路方法一&#xff1a;一次遍历复杂度分析 其他语言python3C 写在最后 Tag 【一次遍历】【数组】【字符串】 题目来源 228. 汇总区间 题目解读 给定一个无重复的升序数组 nums&#xff0c;需要将这个数组按照以下规则进行汇总&#xff1…...

主流接口测试框架对比

公司计划系统的开展接口自动化测试&#xff0c;需要我这边调研一下主流的接口测试框架给后端测试&#xff08;主要测试接口&#xff09;的同事介绍一下每个框架的特定和使用方式。后端同事根据他们接口的特点提出一下需求&#xff0c;看哪个框架更适合我们。 需求 1、接口编写…...

LeetCode 150.逆波兰表达式求值

题目链接 力扣&#xff08;LeetCode&#xff09;官网 - 全球极客挚爱的技术成长平台 题目解析 首先我们需要知道什么是逆波兰表达式&#xff0c;像我们平常遇到的都是中缀表达式&#xff0c;然而逆波兰确实后缀表达式&#xff0c;因此这个题目隐含的意思就是将一个后缀表达式转…...

华为---企业WLAN组网基本配置示例---AC+AP组网

ACAP组网所需的物理条件 1、无线AP---收发无线信号&#xff1b; 2、无线控制器(AC)---用来控制管理多个AP&#xff1b; 3、PoE交换机---能给AP实现网络连接和供电的交换机&#xff1b; 4、授权&#xff1a;默认AC管理的AP数量有限&#xff0c;买授权才能管控更多AP。 WLAN创建…...

循环结构的运用

乘法口诀起源于中国&#xff0c;是古代人进行乘法、除法、开方等运算的基本法则&#xff0c;距今已经有两千多年的历史了&#xff0c;如何运用现代计算机技术快速写出九九乘法表呢&#xff1f; 循环结构可以用来重复执行一条或者多条语句&#xff0c;利用循环结构可以减少源程序…...

深度强化学习第 1 章 机器学习基础

1.1线性模型 线性模型&#xff08;linear models&#xff09;是一类最简单的有监督机器学习模型&#xff0c;常被用于简单的机 器学习任务。可以将线性模型视为单层的神经网络。本节讨论线性回归、逻辑斯蒂回归&#xff08;logistic regression&#xff09;、 softmax 分类器等…...

第一章 STM32 CubeMX (CAN通信发送)基础篇

第一章 STM32 CubeMX &#xff08;CAN通信&#xff09;基础篇 文章目录 第一章 STM32 CubeMX &#xff08;CAN通信&#xff09;基础篇STM32中文手册简介简介stm32f1系列CAN的特点CAN连接网络示意图硬件电路CAN波特率计数 一、 STM32 CubeMX设置设置波特率工程目录结构添加CAN驱…...

原子性操作

原子性操作是指一个操作在执行过程中不会被中断&#xff0c;要么全部执行成功&#xff0c;要么全部不执行&#xff0c;不会出现部分执行的情况。原子性操作对于多线程并发编程至关重要&#xff0c;因为它可以确保多个线程之间不会出现竞态条件或数据不一致性。 在计算机科学中…...

论文阅读:Segment Any Point Cloud Sequences by Distilling Vision Foundation Models

目录 概要 Motivation 整体架构流程 技术细节 小结 论文地址&#xff1a;[2306.09347] Segment Any Point Cloud Sequences by Distilling Vision Foundation Models (arxiv.org) 代码地址&#xff1a;GitHub - youquanl/Segment-Any-Point-Cloud: [NeurIPS23 Spotlight]…...

Netty 入门 — 亘古不变的Hello World

这篇文章我们正式开始学习 Netty&#xff0c;在入门之前我们还是需要了解什么是 Netty。 什么是 Netty 为什么很多人都推崇 Java boy 去研究 Netty&#xff1f;Netty 这么高大上&#xff0c;它到底是何方神圣&#xff1f; 用官方的话说&#xff1a;Netty 是一款异步的、基于事…...

idea插件开发javax.net.ssl.SSLException: No PSK available. Unable to resume.

idea插件开发,编译出错 javax.net.ssl.SSLException: No PSK available. Unable to resume.at java.base/sun.security.ssl.Alert.createSSLException(Alert.java:129)at java.base/sun.security.ssl.Alert.createSSLException(Alert.java:117)at java.base/sun.security.ssl.…...

Selenium的WebDriver操作页面的超时或者元素重叠引起的ElementClickInterceptedException

超时 处理由页面加载引起的超时是在使用 Selenium 进行自动化测试中常见的任务。页面加载可能因网络速度慢、页面复杂性或异步操作而导致超时。以下是一些处理页面加载超时的方法&#xff1a; 1.设置隐式等待时间&#xff1a; 使用 implicitly_wait 方法可以设置隐式等待时间…...

oracle数据库的缓存设置

Oracle缓存由两个参数控制SGA_TARGET和PGA_AGGREGATE_TARGET&#xff0c;设置了这两个参数&#xff0c;其他的基本内存部分都由Oracle自动配置为最优值&#xff0c;这也是Oracle推荐的方式。 SGA_TARGET 和PGA_AGGREGATE_TARGET是动态参数&#xff0c;可以在不重启数据库的情况…...

算法通关村第一关-链表青铜挑战笔记

欢迎来到 : 第一关青铜关 java如何创建链表链表怎么增删改查 我们先了解链表 单链表的概念 我们从简单的创建和增删改查开始. 链表的概念 线性表分为顺序表(数组组成)和链表(节点组成) . 链表又分: 单向 双向有哨兵节点 无哨兵节点循环 不循环 链表是一种物理存储单…...

✔ ★【备战实习(面经+项目+算法)】 10.15学习时间表

✔ ★【备战实习&#xff08;面经项目算法&#xff09;】 坚持完成每天必做如何找到好工作1. 科学的学习方法&#xff08;专注&#xff01;效率&#xff01;记忆&#xff01;心流&#xff01;&#xff09;2. 每天认真完成必做项&#xff0c;踏实学习技术 认真完成每天必做&…...

pytorch 训练时raise EOFError EOFError

训练到一半时获取验证数据报错 报错代码 imgs next(iter(val_dataloader)) val_dataloader DataLoader(ImageDataset("data/%s" % opt.dataset_name, transforms_transforms_, unalignedTrue, mode"test"),batch_size5,shuffleTrue,num_workers2,)def …...

node.js+NPM包管理器+Webpack打包工具+前端项目搭建

javascript运行环境&#xff08;无需依赖html文件&#xff09; BFF&#xff0c;服务于前端的后端 官网下载安装&#xff0c;node -v查看是否安装成功 ①、创建一个01.js文件 //引入http模块 const httprequire(http)//创建服务器 http.createServer(function(request,respo…...

PCL点云处理之基于FPFH特征的全局配准流程具体实现(二百二十一)

PCL点云处理之基于FPFH特征的全局配准流程具体实现(二百二十一) 一、算法介绍二、算法实现1.代码2.效果一、算法介绍 PCL点云库提供的多种工具,可以组合为一套完整的点云配准流程,这里选择FPFH特征,进行具体的配准流程实现,主要内容包括点云读取、点云法线计算、点云特征…...

ai_drive67_基于不确定性的多视图决策融合

论文链接&#xff1a;https://openreview.net/forum?idOOsR8BzCnl5 https://arxiv.org/abs/2102.02051 代码链接&#xff1a;https://github.com/hanmenghan/TMC Zongbo Han, Changqing Zhang, Huazhu Fu, Joey Tianyi Zhou, Trusted Multi-View Classification, Internatio…...

Docker逃逸---procfs文件挂载

一、产生原因 将宿主机/proc目录挂载进了容器&#xff0c;而该目录内的/proc/sys/kernel/core_pattern文件是负责进程奔溃时内存数据转储的&#xff0c;当第一个字符是| 管道符时&#xff0c;后面的部分会以命令行的方式进行解析并运行&#xff0c;攻击者可以将恶意文件写入该…...

[Python小项目] 从桌面壁纸到AI绘画

从桌面壁纸到AI绘画 一、前言 1.1 确认问题 由于生活和工作需要&#xff0c;小编要长时间的使用电脑&#xff0c;小编又懒&#xff0c;一个主题用半年的那种&#xff0c;所以桌面壁纸也是处于常年不更换的状态。即时改变主题也是在微软自带的壁纸中选择&#xff0c;而这些自…...

【Docker 内核详解】namespace 资源隔离(五):User namespaces

【Docker 内核详解 - namespace 资源隔离】系列包含&#xff1a; namespace 资源隔离&#xff08;一&#xff09;&#xff1a;进行 namespace API 操作的 4 种方式namespace 资源隔离&#xff08;二&#xff09;&#xff1a;UTS namespace & IPC namespacenamespace 资源隔…...

网络原理必知会

衔接上文&#xff1a;网络原理必知会_念君思宁的博客-CSDN博客 流量控制&#xff1a; 流量控制也是保证可靠性的机制 对于滑动窗口&#xff0c;批量发送数据而言&#xff0c;窗口越大&#xff0c;相当于批量发送的数据越多&#xff0c;整体的速度也就越快了&#xff0c;但是&…...

ELK 日志分析系统介绍与部署

目录 一、ELK 简介: 1.开源工具介绍&#xff1a; 2.其它组件&#xff1a; 2.1 Filebeat&#xff1a; 2.2 Fluentd&#xff1a; 2.3 缓存/消息队列&#xff08;redis、kafka、RabbitMQ等&#xff09;&#xff1a; 3. filebeat 结合 logstash 带来好处&#xff1a; 二、为什么要…...

Android 内存治理之线程

1、 前言 当我们在应用程序中启动一个线程的时候&#xff0c;也是有可能发生OOM错误的。当我们看到以下log的时候&#xff0c;就说明系统分配线程栈失败了。 java.lang.OutOfMemoryError: pthread_create (1040KB stack) failed: Out of memory这种情况可能是两种原因导致的。…...

三、K8S之ReplicaSet

ReplicaSet 一、概述 Kubernetes最核心的功能是编排&#xff0c;编排操作都是依靠控制器对象来完成&#xff0c;高级控制器控制着基础的控制器&#xff0c;基础控制器再去控制Pod&#xff0c;Pod里面再包容器。K8S项目里API对象层级大概就是这样。 而ReplicaSet这个控制器是…...

【基础篇】四、本地部署Flink

文章目录 1、本地独立部署会话模式的Flink2、本地独立部署会话模式的Flink集群3、向Flink集群提交作业4、Standalone方式部署单作业模式5、Standalone方式部署应用模式的Flink Flink的常见三种部署方式&#xff1a; 独立部署&#xff08;Standalone部署&#xff09;基于K8S部署…...

简述什么是迭代器(Iterator)?

迭代器(Iterator)是一种设计模式,Java 中的迭代器是集合框架中的一个接口,它可以让程序员遍历集合中的元素而无需暴露集合的内部结构。使用迭代器可以遍历任何类型的集合,例如 List、Set 和 Map 等。 通过调用集合类的 iterator() 方法可以获取一个迭代器,并使用 hasNext…...