自定义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()
`