pyqt 自定义QTableWidget

news/2025/10/29 22:39:27/文章来源:https://www.cnblogs.com/qaqaqaq/p/19175542

自定义QTableWidget

`import sys
from PyQt5.QtWidgets import (QApplication, QMainWindow, QVBoxLayout, QWidget,
QComboBox, QTabWidget, QTableWidget, QTableWidgetItem)
from PyQt5.QtCore import Qt
import re

class CustomTableWidget(QTableWidget):
def init(self, rows=0, cols=0, parent=None):
super().init(rows, cols, parent)
# 允许编辑表格
self.setEditTriggers(QTableWidget.DoubleClicked | QTableWidget.EditKeyPressed)
self.setSelectionBehavior(QTableWidget.SelectRows)
self.setSelectionMode(QTableWidget.SingleSelection)
self.setAlternatingRowColors(True)
self.setShowGrid(True)
self.setWordWrap(True)
self.setCornerButtonEnabled(True)

def extract_number(self, text):"""从文本中提取数字"""if not text:return 0# 尝试直接转换为数字try:return float(text)except ValueError:# 如果直接转换失败,尝试提取数字部分numbers = re.findall(r'-?\d+\.?\d*', text)if numbers:return float(numbers[0])return None

class UTTabWidget(QTabWidget):
def init(self, parent=None):
super().init(parent)
self.initUI()

def initUI(self):self.add_tab1("员工信息")self.add_tab2("考勤记录")self.add_tab3("薪资统计")def add_tab1(self, title):tab = CustomTableWidget(10, 5)  # 10行5列tab.setHorizontalHeaderLabels(["ID", "姓名", "实际工时", "标准工时", "结果"])# tab.blockSignals(True)# 添加示例数据data = [["001", "张三", "40", "40", ""],["002", "李四", "38", "40", ""],["003", "王五", "42", "40", ""]]for i, row_data in enumerate(data):for j, cell_data in enumerate(row_data):item = QTableWidgetItem(str(cell_data))tab.setItem(i, j, item)# 绑定事件tab.itemChanged.connect(self.on_tab1_item_changed)for i in range(len(data)):self.update_tab1_result_column(tab, i)self.addTab(tab, title)def add_tab2(self, title):tab = CustomTableWidget(10, 5)  # 10行5列tab.setHorizontalHeaderLabels(["日期", "员工", "实际出勤", "应出勤", "结果"])# 添加示例数据data = [["2023-01-01", "张三", "8", "8", ""],["2023-01-01", "李四", "7", "8", ""],["2023-01-02", "王五", "9", "8", ""]]for i, row_data in enumerate(data):for j, cell_data in enumerate(row_data):item = QTableWidgetItem(str(cell_data))tab.setItem(i, j, item)self.addTab(tab, title)def add_tab3(self, title):tab = CustomTableWidget(10, 5)  # 10行5列tab.setHorizontalHeaderLabels(["月份", "员工", "实发工资", "应发工资", "结果"])# 添加示例数据data = [["1月", "张三", "8000", "8000", ""],["1月", "李四", "7500", "8000", ""],["2月", "王五", "9000", "8500", ""]]for i, row_data in enumerate(data):for j, cell_data in enumerate(row_data):item = QTableWidgetItem(str(cell_data))tab.setItem(i, j, item)self.addTab(tab, title)def on_tab1_item_changed(self, item):"""tab1专用的单元格变更处理函数"""row = item.row()col = item.column()# 只处理第3列和第4列(索引2和3)的变更if col in [2, 3]:self.update_tab1_result_column(item.tableWidget(), row)def update_tab1_result_column(self, table, row):"""更新tab1的结果列"""# 确保行存在且有足够的列数if row >= table.rowCount() or table.columnCount() < 5:return# 获取第三列和第四列的值third_item = table.item(row, 2)fourth_item = table.item(row, 3)if third_item and fourth_item:try:# 提取数字值third_value = float(third_item.text()) if third_item.text() else 0fourth_value = float(fourth_item.text()) if fourth_item.text() else 0# 计算差值diff = third_value - fourth_value# 获取或创建第五列的单元格result_item = table.item(row, 4)if not result_item:result_item = QTableWidgetItem()table.setItem(row, 4, result_item)# 根据差值更新第五列if diff == 0:  # 工时相等为passresult_item.setText("pass")else:result_item.setText("fail")except (ValueError, TypeError):# 如果转换失败,设置为failresult_item = table.item(row, 4)if not result_item:result_item = QTableWidgetItem()table.setItem(row, 4, result_item)result_item.setText("fail")

class PRDTabWidget(QTabWidget):
def init(self, parent=None):
super().init(parent)
self.initUI()

def initUI(self):self.add_tab1("产品信息")self.add_tab2("库存统计")self.add_tab3("销售报告")def add_tab1(self, title):tab = CustomTableWidget(10, 5)  # 10行5列tab.setHorizontalHeaderLabels(["产品编号", "产品名称", "实际成本", "预算成本", "结果"])# 添加示例数据data = [["P001", "笔记本电脑", "4500", "5000", ""],["P002", "台式机", "3500", "3500", ""],["P003", "显示器", "800", "1000", ""]]for i, row_data in enumerate(data):for j, cell_data in enumerate(row_data):item = QTableWidgetItem(str(cell_data))tab.setItem(i, j, item)# 更新结果列for i in range(tab.rowCount()):tab.update_result_column(i)self.addTab(tab, title)def add_tab2(self, title):tab = CustomTableWidget(10, 5)  # 10行5列tab.setHorizontalHeaderLabels(["仓库", "产品", "实际库存", "安全库存", "结果"])# 添加示例数据data = [["一号仓", "笔记本电脑", "50", "30", ""],["二号仓", "台式机", "20", "25", ""],["一号仓", "显示器", "100", "80", ""]]for i, row_data in enumerate(data):for j, cell_data in enumerate(row_data):item = QTableWidgetItem(str(cell_data))tab.setItem(i, j, item)# 更新结果列for i in range(tab.rowCount()):tab.update_result_column(i)self.addTab(tab, title)def add_tab3(self, title):tab = CustomTableWidget(10, 5)  # 10行5列tab.setHorizontalHeaderLabels(["季度", "产品", "实际销量", "目标销量", "结果"])# 添加示例数据data = [["Q1", "笔记本电脑", "200", "250", ""],["Q1", "台式机", "150", "150", ""],["Q2", "显示器", "300", "280", ""]]for i, row_data in enumerate(data):for j, cell_data in enumerate(row_data):item = QTableWidgetItem(str(cell_data))tab.setItem(i, j, item)# 更新结果列for i in range(tab.rowCount()):tab.update_result_column(i)self.addTab(tab, title)

class MainWindow(QMainWindow):
def init(self):
super().init(parent=None)
self.setWindowTitle("auto report v1.0.0")
self.setGeometry(100, 100, 800, 600)
self.initUI()

def initUI(self):# 创建中央部件central_widget = QWidget()self.setCentralWidget(central_widget)# 创建主布局layout = QVBoxLayout(central_widget)# 创建下拉框并添加选项self.category_combo = QComboBox()self.category_combo.addItems(["员工管理","产品管理",])# 创建自定义的tab组件self.tab_widget = UTTabWidget()# 添加组件到布局layout.addWidget(self.category_combo)layout.addWidget(self.tab_widget)# 绑定事件self.category_combo.currentTextChanged.connect(self.update_tabs)def update_tabs(self, text):"""根据下拉框选择更新tabs"""# 保存当前tab的位置current_index = self.tab_widget.currentIndex()# 删除旧的tab_widgetlayout = self.centralWidget().layout()layout.removeWidget(self.tab_widget)self.tab_widget.deleteLater()# 创建新的tab_widgetif text == "员工管理":self.tab_widget = UTTabWidget()elif text == "产品管理":self.tab_widget = PRDTabWidget()else:self.tab_widget = QTabWidget()# 添加新的tab_widget到布局layout.addWidget(self.tab_widget)# 恢复之前的tab位置if current_index < self.tab_widget.count():self.tab_widget.setCurrentIndex(current_index)

def main():
app = QApplication(sys.argv)
window = MainWindow()
window.show()
sys.exit(app.exec_())

if name == "main":
main()
`

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/950302.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

价值主体的技术实现:基于Free Transformer潜变量Z的AI元人文架构探索

基于Free Transformer的潜变量Z技术探索"价值主体行为"时,岐金兰揭示的两个核心担忧,指出了理论技术化过程中的关键风险。这些风险若不能得到妥善解决,将导致AI元人文构想从生机勃勃的价值生态系统,蜕变…

第二十二天

《程序员修炼之道:从小工到专家》阅读笔记:思维重塑 在技术迭代如浪潮的行业里,这本书并非罗列API的工具书,而是为程序员搭建了从“完成任务”到“创造价值”的思维桥梁。它最核心的启示在于:优秀的程序员,本质是…

Problemsetting

List of my problems其实我很不会出题, 所以不会常更新可能不会更新.Problem Difficulty[集训队互测 2023] 优惠购物 3300【UER #12】电子运动 2800【UNR #9】星图 2800【UNR #9】Sing 2900Canvas Painting ?cooperat…

记录一下我最近一年写的脚本,不知不觉近100个了!

记录一下我最近一年写的脚本,不知不觉近100个了! 一个系统初始化的脚本 @echo offecho 右击鼠标以管理员身份运行,按任意键退出 echo 开启远程桌面连接Wmic OS Get Caption | Findstr /i "7" >nul …

The 2025 Hunan Collegiate Programming Contest

Preface 不知道 VP 什么就找了场 QOJ 上最新的比赛,结果发现打的时候就我们一个队,全程无榜就很难受 而且这场的题目质量确实让人不敢恭维,一堆原题和典题,基本没有那种有意思的思维题 最后 9 of 11,剩下两个感觉…

List of my problems

其实我很不会出题, 所以不会常更新.Problem Difficulty[集训队互测 2023] 优惠购物 3300【UER #12】电子运动 2800【UNR #9】星图 2800【UNR #9】Sing 2900Canvas Painting ?cooperated (modified solution/idea):Pr…

歌声转换SVC主流方法原理剖析1 — DDSP-SVC

pre 本文SVC指的是歌声转换(Singing Voice Conversion (SVC)),例如常见且开源的 So-VITS-SVC, RVC, DDSP-SVC 关键词:歌声转换、声音克隆、音色 最早在23年刷到了惠惠的冬之花翻唱,惊为天人,一直对这块很感兴趣,…

SpringBoot整合邮件发送

一、邮件发送核心认知 1. 什么是邮件发送 邮件发送是应用程序中通过邮件服务器将信息传递给指定收件人的功能,支持纯文本、附件、图片、HTML 模板等多种形式。在 Spring Boot 中,借助 Spring 提供的邮件服务封装,可…

vyos syslog配置

设置syslog服务器和端口set system syslog host 10.1.1.2 port 514 设置记录全部内容 set system syslog console facility all 提交并保存 commit save稍后即可在日志服务器上看到日志。 如需记录到文件,使用下列命…

Unity3D URP中材质设置emission自发光但是没有辉光Bloom效果

如图,勾选了emission并且调高了强度,物体没有向外发光的辉光效果,原因是没有设置后处理,需要在Package Manager里下载post processing,然后新建Global Volume然后点开ProFile选中场景的profile即可,如果没有可以…

Ishibuchi教授与Lie Meng Pang博士受邀于本课题组开展学术交流与指导

2025年9月26日,本课题组成功举办了一场高水平的国际学术交流活动。此次活动邀请到了南方科技大学讲座教授、IEEE Fellow Hisao Ishibuchi 教授以及南方科技大学计算机科学与工程系的Lie Meng Pang 博士来院进行学术指…

【倒计时10天】第20届国际生物启发式计算:理论与应用会议(BIC-TA 2025)将于2025年11月7-9日在武汉召开!

【倒计时10天】各位老师好!第20届国际生物启发式计算:理论与应用会议(BIC-TA 2025)将于2025年11月7-9日在武汉召开!🔔 本次会议由华中科技大学主办,武汉科技大学、湖北省运筹学会协办。 会议已邀请四川大学Gar…

[TOOL] 二进制文件阅读与分析入门指南

[TOOL] 二进制文件阅读与分析入门指南$(".postTitle2").removeClass("postTitle2").addClass("singleposttitle");ChatGPT生成(2025年10月29日22:11:13)目录二进制文件阅读与分析入门…

[TOOL] hexdump: 二进制文件阅读指南

[TOOL] hexdump: 二进制文件阅读指南$(".postTitle2").removeClass("postTitle2").addClass("singleposttitle");DeepSeek生成(2025年10月29日22:03:39)目录Hexdump 二进制文件阅读指…

题解:CodeForces 715E Complete the Permutations

题意 对于两个排列 \(p,q\),定义它们的距离为将 \(p\) 变成 \(q\) 的最小操作次数,其中每次操作可以交换 \(p\) 中两个元素的位置。现在给定两个长度为 \(n\) 的排列 \(p,q\),其中一些位置被替换成了 \(0\)。对于每…

[TOOL] hexdump: 二进制文件分析指南

[TOOL] hexdump: 二进制文件分析指南$(".postTitle2").removeClass("postTitle2").addClass("singleposttitle");DeepSeek生成(2025年10月29日22:03:39)目录Hexdump 二进制文件分析指…

Day26-C:\Users\Lenovo\Desktop\note\code\JavaSE\Basic\src\com\Threadcase

等待唤醒机制 生产者和消费者package Basic.src.com.Threadcase.Threadwaitnotify;public class Desk {/** 控制生产者和消费者的执行* *///桌子上是否有面条 0;没有面条 1:有面条public static int foodFlag = 0;…

题解:CF715E Complete the Permutations

题意 对于两个排列 \(p,q\),定义它们的距离为将 \(p\) 变成 \(q\) 的最小操作次数,其中每次操作可以交换 \(p\) 中两个元素的位置。现在给定两个长度为 \(n\) 的排列 \(p,q\),其中一些位置被替换成了 \(0\)。对于每…

日总结 20

YARN(Yet Another Resource Negotiator)是 Hadoop 生态中的核心集群资源管理与任务调度框架,旨在解耦 Hadoop 1.x 中 MapReduce 的计算与资源管理功能,通过 ResourceManager(全局资源管理)、NodeManager(节点资…

重组蛋白与传统蛋白的区别:从来源到特性的全面解析

在生命科学研究中,蛋白质作为重要的实验试剂,其获取方式和特性直接影响研究结果。传统蛋白与重组蛋白在多个维度存在显著差异,本文将系统解析二者的区别。 一、定义与来源的本质差异 传统蛋白通常指从生物体组织、器…