pyqt 自定义QTableWidget

自定义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 0
            fourth_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:  # 工时相等为pass
                result_item.setText("pass")
            else:
                result_item.setText("fail")
        except (ValueError, TypeError):
            # 如果转换失败,设置为fail
            result_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_widget
    layout = self.centralWidget().layout()
    layout.removeWidget(self.tab_widget)
    self.tab_widget.deleteLater()

    # 创建新的tab_widget
    if 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()
`

posted @ 2025-10-29 22:36  QAQAQAQAQAQAQ  阅读(9)  评论(0)    收藏  举报