jiateng_ws/ui/main_window_ui.py
2025-07-19 21:30:51 +08:00

1034 lines
46 KiB
Python
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

from PySide6.QtWidgets import (
QMainWindow, QWidget, QLabel, QGridLayout, QVBoxLayout, QHBoxLayout,
QTableWidget, QTableWidgetItem, QHeaderView, QFrame, QSplitter,
QPushButton, QLineEdit, QAbstractItemView, QComboBox, QSizePolicy, QTextEdit
)
from PySide6.QtGui import QFont, QAction, QBrush, QColor
from PySide6.QtCore import Qt, QDateTime, QTimer
class MainWindowUI(QMainWindow):
# 定义字段映射为类属性,方便外部引用
FIELD_MAPPING = {
"库房": "lib",
"机台": "jt",
"客户": "customerexp",
"订单数量": "maxsl",
"规格": "size",
"材质": "cz",
"种类": "type_name",
"钢厂": "cd",
"炉号": "luno",
"轴型": "zx_name",
"标签": "template_name",
"打印材质": "cz",
"底托类型": "spack_type",
"强度范围": "qx",
"强度": "qd",
"延伸要求": "ysl",
"线材类型": "xclx",
"包装方式": "bzfs",
"轴重要求": "zzyq",
"线径公差": "xj",
"备注": "remarks_hb"
}
def __init__(self,username):
super().__init__()
self.username = username
self.setWindowTitle(f"腾智微丝产线包装系统")
self.resize(1200, 800)
self.init_ui()
def init_ui(self):
# 设置字体
self.title_font = QFont("微软雅黑", 20, QFont.Bold)
self.second_title_font = QFont("微软雅黑", 14, QFont.Bold)
self.normal_font = QFont("微软雅黑", 12)
self.small_font = QFont("微软雅黑", 9)
# 创建菜单栏
self.create_menu()
# 创建中央部件
self.central_widget = QWidget()
self.setCentralWidget(self.central_widget)
# 创建主布局 - 水平分割
self.main_layout = QHBoxLayout(self.central_widget)
self.main_layout.setContentsMargins(5, 5, 5, 5)
self.main_layout.setSpacing(5)
# 创建左侧面板
self.left_panel = QWidget()
self.left_layout = QVBoxLayout(self.left_panel)
self.left_layout.setContentsMargins(0, 0, 0, 0)
self.left_layout.setSpacing(5)
self.create_left_panel()
# 创建右侧面板
self.right_panel = QWidget()
self.right_layout = QVBoxLayout(self.right_panel)
self.right_layout.setContentsMargins(0, 0, 0, 0)
self.right_layout.setSpacing(5)
self.create_right_panel()
# 添加左右面板到主布局
self.main_layout.addWidget(self.left_panel, 1) # 左侧面板占比较小
self.main_layout.addWidget(self.right_panel, 2) # 右侧面板占比较大
def create_menu(self):
# 创建菜单栏
self.menubar = self.menuBar()
# 用户操作菜单
self.user_menu = self.menubar.addMenu("用户操作页")
self.main_action = QAction("主页面", self)
self.user_menu.addAction(self.main_action)
# 系统设置菜单
self.system_menu = self.menubar.addMenu("系统设置")
self.settings_action = QAction("设置页面", self)
self.system_menu.addAction(self.settings_action)
def create_left_panel(self):
# 创建标题容器
self.title_container = QWidget()
self.title_layout = QHBoxLayout(self.title_container)
self.title_layout.setContentsMargins(10, 10, 10, 10)
self.title_layout.setSpacing(10)
# 创建用户名标签
self.username_label = QLabel(self.username)
self.username_label.setFont(self.normal_font)
self.username_label.setStyleSheet("color: #666666;")
self.username_label.setAlignment(Qt.AlignLeft | Qt.AlignVCenter)
# 创建主标题标签
self.title_label = QLabel("腾智微丝产线包装系统")
self.title_label.setFont(self.title_font) # 较大的字体
self.title_label.setAlignment(Qt.AlignCenter)
self.title_label.setStyleSheet("color: #1a237e;")
# 创建时间标签
self.time_label = QLabel()
self.time_label.setFont(self.normal_font)
self.time_label.setStyleSheet("color: #666666;")
self.time_label.setAlignment(Qt.AlignRight | Qt.AlignVCenter)
# 创建定时器更新时间
self.timer = QTimer(self)
self.timer.timeout.connect(self.update_time)
self.timer.start(1000) # 每秒更新一次
self.update_time() # 立即更新一次时间
# 将标签添加到标题布局中
self.title_layout.addWidget(self.username_label, 1)
self.title_layout.addWidget(self.title_label, 2) # 中间标题占据更多空间
self.title_layout.addWidget(self.time_label, 1)
# 设置标题容器的样式
self.title_container.setStyleSheet("background-color: #f5f5f5; border-radius: 4px;")
self.left_layout.addWidget(self.title_container)
# 项目信息表格 - 使用QFrame包裹添加边框
self.project_frame = QFrame()
self.project_frame.setFrameShape(QFrame.StyledPanel)
self.project_frame.setLineWidth(1)
self.project_frame.setFixedHeight(150) # 调整这个值可以控制整体高度
self.project_layout = QVBoxLayout(self.project_frame)
self.project_layout.setContentsMargins(5, 5, 5, 5)
# 项目表格
self.project_table = QTableWidget(4, 4)
self.project_table.setHorizontalHeaderLabels(["用电", "数量", "产量", "开机率"])
self.project_table.setVerticalHeaderLabels(["当日", "当月", "当年", "累计"])
#设置字体
self.project_table.setFont(self.normal_font)
# 设置垂直表头宽度
self.project_table.verticalHeader().setFixedWidth(60)
self.project_table.horizontalHeader().setSectionResizeMode(QHeaderView.Stretch)
self.project_table.verticalHeader().setSectionResizeMode(QHeaderView.Stretch)
self.project_table.setEditTriggers(QTableWidget.NoEditTriggers) # 设置为不可编辑
self.project_layout.addWidget(self.project_table)
self.left_layout.addWidget(self.project_frame)
# 任务信息区域 - 使用QFrame包裹添加边框
self.task_frame = QFrame()
self.task_frame.setFrameShape(QFrame.StyledPanel)
self.task_frame.setLineWidth(1)
self.task_frame.setFixedHeight(180)
self.task_layout = QVBoxLayout(self.task_frame)
self.task_layout.setContentsMargins(8, 8, 8, 8)
# 任务标签
self.task_label = QLabel("任务")
self.task_label.setFont(self.normal_font)
self.task_label.setAlignment(Qt.AlignLeft)
self.task_label.setStyleSheet("font-weight: bold; color: #333333;")
self.task_layout.addWidget(self.task_label)
# 订单行
self.order_layout = QHBoxLayout()
self.order_layout.setAlignment(Qt.AlignLeft) # 设置整个布局左对齐
self.order_label = QLabel("工程号")
self.order_label.setFont(QFont("微软雅黑", 12, QFont.Bold))
self.order_label.setFixedHeight(30)
self.order_label.setStyleSheet("padding: 0 5px; color: #333333;")
self.order_edit = QLineEdit()
self.order_edit.setFixedHeight(30)
self.order_edit.setFixedWidth(150)
self.order_edit.setReadOnly(False)
self.order_edit.setFont(QFont("微软雅黑", 12))
self.order_edit.setText("") # 设置默认订单号
self.order_edit.setStyleSheet("background-color: #f9f9f9; border: 1px solid #cccccc; border-radius: 3px; padding: 2px 5px;")
self.order_layout.addWidget(self.order_label)
self.order_layout.addWidget(self.order_edit)
self.order_layout.addStretch() # 添加弹性空间,将组件推到左侧
self.task_layout.addLayout(self.order_layout)
# 任务表格 - 使用合并单元格实现一级二级标题
self.task_table = QTableWidget(3, 4) # 3行4列一级标题行、二级标题行、数据行
self.task_table.setEditTriggers(QTableWidget.NoEditTriggers) # 设置为不可编辑
self.task_table.horizontalHeader().setVisible(False)
self.task_table.verticalHeader().setVisible(False)
self.task_table.setShowGrid(True)
# 设置列宽均等
self.task_table.horizontalHeader().setSectionResizeMode(QHeaderView.Stretch)
# 第一行:订单量和完成量 (一级标题)
self.task_table.setSpan(0, 0, 1, 2) # 订单量跨2列
self.task_table.setSpan(0, 2, 1, 2) # 完成量跨2列
order_item = QTableWidgetItem("订单量")
order_item.setTextAlignment(Qt.AlignCenter)
order_item.setFont(self.normal_font)
self.task_table.setItem(0, 0, order_item)
completed_item = QTableWidgetItem("完成量")
completed_item.setTextAlignment(Qt.AlignCenter)
completed_item.setFont(self.normal_font)
self.task_table.setItem(0, 2, completed_item)
# 第二行:二级标题
headers = ["总生产数量", "总生产公斤", "已完成数量", "已完成公斤"]
for col, header in enumerate(headers):
item = QTableWidgetItem(header)
item.setTextAlignment(Qt.AlignCenter)
item.setFont(self.small_font)
self.task_table.setItem(1, col, item)
# 设置行高
self.task_table.setRowHeight(0, 30) # 一级标题行高
self.task_table.setRowHeight(1, 30) # 二级标题行高
self.task_table.setRowHeight(2, 30) # 数据行高
self.task_layout.addWidget(self.task_table)
self.left_layout.addWidget(self.task_frame)
# 上料区 - 使用QFrame包裹添加边框
self.material_frame = QFrame()
self.material_frame.setFrameShape(QFrame.StyledPanel)
self.material_frame.setLineWidth(1)
self.material_frame.setFixedHeight(380) # 保持上料区高度不变
self.material_frame.setStyleSheet("QFrame { background-color: #f8f8f8; }")
self.material_layout = QHBoxLayout(self.material_frame)
self.material_layout.setContentsMargins(0, 0, 0, 0)
self.material_layout.setSpacing(0)
# 上料区标签
self.material_label = QLabel("托盘入库")
self.material_label.setFont(self.normal_font)
self.material_label.setAlignment(Qt.AlignCenter)
self.material_label.setFixedWidth(100) # 设置固定宽度
self.material_label.setStyleSheet("background-color: #e0e0e0; border-right: 1px solid #cccccc; font-weight: bold;")
self.material_layout.addWidget(self.material_label)
# 上料区内容 - 订单信息表格
self.material_content = QWidget()
self.material_content.setStyleSheet("background-color: white;")
self.material_content_layout = QVBoxLayout(self.material_content)
self.material_content_layout.setContentsMargins(10, 10, 10, 10)
# 移除滚动区域,直接使用表格
# 创建订单号输入框
self.order_info_layout = QHBoxLayout()
self.order_no_label = QLabel("订单号:")
self.order_no_label.setFont(self.normal_font)
self.order_no_label.setFixedWidth(60)
self.order_no_input = QLineEdit()
self.order_no_input.setFont(self.normal_font)
self.order_no_input.setReadOnly(True)
self.order_no_input.setStyleSheet("background-color: #f5f5f5; border: 1px solid #cccccc; padding: 3px;")
self.order_info_layout.addWidget(self.order_no_label)
self.order_info_layout.addWidget(self.order_no_input)
self.order_info_layout.addStretch()
# 添加托盘完成按钮
self.tray_complete_button = QPushButton("托盘完成")
self.tray_complete_button.setFont(self.normal_font)
self.tray_complete_button.setStyleSheet("""
QPushButton {
padding: 5px 8px;
background-color: #e8f5e9;
border: 1px solid #4caf50;
}
QPushButton:hover {
background-color: #c8e6c9;
}
""")
self.order_info_layout.addWidget(self.tray_complete_button)
self.material_content_layout.addLayout(self.order_info_layout)
# 创建信息表格 - 使用QTableWidget实现
self.info_table = QTableWidget()
# 计算需要的行数21个字段每行2个字段最后两行是备注跨列
# 前20个字段需要10行备注占用2行总共12行
self.info_table.setRowCount(12) # 10行常规字段 + 2行备注
self.info_table.setColumnCount(4) # 4列标签1, 值1, 标签2, 值2
self.info_table.setShowGrid(True) # 显示网格线
self.info_table.horizontalHeader().setVisible(False) # 隐藏水平表头
self.info_table.verticalHeader().setVisible(False) # 隐藏垂直表头
# 设置表格样式
self.info_table.setStyleSheet("""
QTableWidget {
border-top: 1px solid #cccccc;
border-left: 1px solid #cccccc;
border-right: none;
border-bottom: none;
gridline-color: #cccccc;
}
""")
# 定义字段和对应的数据键
field_mapping = self.FIELD_MAPPING
# 创建标签和值的字典,用于后续更新
self.info_labels = {}
self.info_values = {}
# 填充表格内容
row = 0
col = 0
for i, field_name in enumerate(field_mapping.keys()):
if field_name == "备注": # 备注行特殊处理
# 创建标签
label = QLabel("备注")
label.setFont(self.normal_font)
label.setAlignment(Qt.AlignLeft | Qt.AlignVCenter)
label.setStyleSheet("background-color: #FAFAFA; padding: 5px;")
# 创建值改为QTextEdit
value = QTextEdit("")
value.setFont(self.normal_font)
value.setStyleSheet("background-color: white; padding: 5px; border: 1px solid #cccccc;")
value.setFixedHeight(70) # 增加高度为两行
value.setVerticalScrollBarPolicy(Qt.ScrollBarAlwaysOff)
value.setHorizontalScrollBarPolicy(Qt.ScrollBarAlwaysOff)
value.setFrameStyle(QFrame.NoFrame)
value.setLineWrapMode(QTextEdit.WidgetWidth) # 允许自动换行
value.setContentsMargins(0, 0, 0, 0)
value.setAcceptRichText(False)
value.setTabChangesFocus(True)
# 保存引用
self.info_labels["备注"] = label
self.info_values["备注"] = value
# 添加到表格,占用两行
self.info_table.setCellWidget(row, 0, label)
self.info_table.setCellWidget(row, 1, value)
self.info_table.setSpan(row, 0, 2, 1) # 标签跨越2行1列
self.info_table.setSpan(row, 1, 2, 3) # 值跨越2行3列
else:
# 创建标签
label = QLabel(field_name)
label.setFont(self.normal_font)
label.setAlignment(Qt.AlignLeft | Qt.AlignVCenter)
label.setStyleSheet("background-color: #FAFAFA; padding: 5px;")
# 根据字段类型创建不同的值组件
if field_name == "库房":
# 库房字段使用QComboBox完全复刻托盘号组件的配置
value = QComboBox()
value.setFixedHeight(35)
value.setStyleSheet("QComboBox { border: 1px solid #cccccc; padding: 3px; background-color: white; } QComboBox::drop-down { border: none; width: 20px; }")
value.setFont(QFont("微软雅黑", 12))
value.setEditable(False) # 设置为不可编辑,确保是纯下拉选择
value.setInsertPolicy(QComboBox.NoInsert) # 不自动插入用户输入到列表中
value.setMaxVisibleItems(10) # 设置下拉框最多显示10个项目
# 添加默认选项
value.addItem("成品库")
value.addItem("退回仓")
value.addItem("散装库")
value.addItem("不合格库(线材)")
value.addItem("废丝库")
value.setCurrentIndex(0) # 默认选择第一个
elif field_name == "机台":
# 机台字段使用QLineEdit与其他字段保持一致
value = QLineEdit("")
value.setFont(self.normal_font)
value.setAlignment(Qt.AlignLeft | Qt.AlignVCenter)
value.setStyleSheet("background-color: white; padding: 5px; border: 1px solid #cccccc;")
value.setFrame(False)
value.setContentsMargins(0, 0, 0, 0)
value.setFixedHeight(35)
elif field_name == "订单数量":
# 订单数量字段使用QLineEdit与其他字段保持一致
value = QLineEdit("")
value.setFont(self.normal_font)
value.setAlignment(Qt.AlignLeft | Qt.AlignVCenter)
value.setStyleSheet("background-color: white; padding: 5px; border: 1px solid #cccccc;")
value.setFrame(False)
value.setContentsMargins(0, 0, 0, 0)
value.setFixedHeight(35)
elif field_name == "线材类型":
# 线材类型字段使用QComboBox与库房组件配置相同
value = QComboBox()
value.setFixedHeight(35)
value.setStyleSheet("QComboBox { border: 1px solid #cccccc; padding: 3px; background-color: white; } QComboBox::drop-down { border: none; width: 20px; }")
value.setFont(QFont("微软雅黑", 12))
value.setEditable(False) # 设置为不可编辑,确保是纯下拉选择
value.setInsertPolicy(QComboBox.NoInsert) # 不自动插入用户输入到列表中
value.setMaxVisibleItems(10) # 设置下拉框最多显示10个项目
# 添加默认选项后续会从API动态加载
value.addItem("请选择")
value.setCurrentIndex(0) # 默认选择第一个
elif field_name == "炉号":
# 炉号字段使用QLineEdit + 查询按钮,复刻订单号的逻辑
# 创建水平布局容器
value_container = QWidget()
value_layout = QHBoxLayout(value_container)
value_layout.setContentsMargins(0, 0, 0, 0)
value_layout.setSpacing(0)
# 创建输入框
value = QLineEdit("")
value.setFont(self.normal_font)
value.setAlignment(Qt.AlignLeft | Qt.AlignVCenter)
value.setStyleSheet("background-color: white; padding: 5px; border: 1px solid #cccccc; border-right: none;")
value.setFixedHeight(35)
# 创建查询按钮
query_button = QPushButton("...")
query_button.setFont(self.normal_font)
query_button.setFixedSize(35, 35)
query_button.setStyleSheet("""
QPushButton {
border: 1px solid #cccccc;
border-left: none;
background-color: #f5f5f5;
color: #333333;
font-weight: bold;
}
QPushButton:hover {
background-color: #e0e0e0;
}
QPushButton:pressed {
background-color: #d0d0d0;
}
""")
# 添加到布局
value_layout.addWidget(value)
value_layout.addWidget(query_button)
# 保存按钮引用,以便后续连接信号
self.luno_query_button = query_button
# 将容器作为值组件
value = value_container
elif field_name == "包装方式":
# 包装方式字段使用QLineEdit与其他字段保持一致
value = QLineEdit("")
value.setFont(self.normal_font)
value.setAlignment(Qt.AlignLeft | Qt.AlignVCenter)
value.setStyleSheet("background-color: white; padding: 5px; border: 1px solid #cccccc;")
else:
# 其他字段使用QLineEdit
value = QLineEdit("")
value.setFont(self.normal_font)
value.setAlignment(Qt.AlignLeft | Qt.AlignVCenter)
value.setStyleSheet("background-color: white; padding: 5px; border: 1px solid #cccccc;")
value.setFrame(False)
value.setContentsMargins(0, 0, 0, 0)
value.setFixedHeight(35)
# 保存引用
self.info_labels[field_name] = label
self.info_values[field_name] = value
# 添加到表格
self.info_table.setCellWidget(row, col * 2, label)
self.info_table.setCellWidget(row, col * 2 + 1, value)
# 更新行列索引
col += 1
if col >= 2: # 每行两组数据
col = 0
row += 1
# 设置行高
for i in range(self.info_table.rowCount()):
if i == 10: # 备注行第11行索引为10
self.info_table.setRowHeight(i, 35) # 备注行第一行高度
self.info_table.setRowHeight(i + 1, 35) # 备注行第二行高度
break
else:
self.info_table.setRowHeight(i, 35) # 普通行高度
# 设置表格自适应宽度
self.info_table.horizontalHeader().setSectionResizeMode(QHeaderView.Stretch)
# 设置表格填充整个容器
self.info_table.setSizePolicy(QSizePolicy.Expanding, QSizePolicy.Expanding)
# 直接添加表格到主布局
self.material_content_layout.addWidget(self.info_table)
self.material_layout.addWidget(self.material_content)
self.left_layout.addWidget(self.material_frame)
# 托盘号区域 - 使用QFrame包裹添加边框
self.tray_frame = QFrame()
self.tray_frame.setFrameShape(QFrame.StyledPanel)
self.tray_frame.setLineWidth(1)
# 移除固定高度,让托盘号的高度自适应其内容
self.tray_frame.setFixedHeight(40) # 进一步减小高度,刚好容纳控件
self.tray_frame.setStyleSheet("QFrame { background-color: #f8f8f8; }")
self.tray_layout = QHBoxLayout(self.tray_frame)
self.tray_layout.setContentsMargins(0, 0, 0, 0) # 移除内边距,确保没有上下边界 # 移除所有边距
self.tray_layout.setSpacing(0) # 移除所有间距
self.tray_label = QLabel("托盘号")
self.tray_label.setFont(self.normal_font)
self.tray_label.setAlignment(Qt.AlignCenter)
self.tray_label.setFixedWidth(100) # 设置固定宽度
self.tray_label.setStyleSheet("background-color: #e0e0e0; border-right: 1px solid #cccccc; font-weight: bold;")
self.tray_layout.addWidget(self.tray_label)
self.tray_edit = QComboBox()
self.tray_edit.setFixedHeight(40) # 设置固定高度与父容器相同
self.tray_edit.setStyleSheet("QComboBox { border: none; padding: 0px 10px; background-color: white; } QComboBox::drop-down { border: none; width: 20px; }")
self.tray_edit.setFont(QFont("微软雅黑", 12))
self.tray_edit.setEditable(True) # 允许手动输入
self.tray_edit.setInsertPolicy(QComboBox.NoInsert) # 不自动插入用户输入到列表中
self.tray_edit.setMaxVisibleItems(10) # 设置下拉框最多显示10个项目
self.tray_edit.completer().setCaseSensitivity(Qt.CaseInsensitive) # 设置补全不区分大小写
self.tray_edit.completer().setFilterMode(Qt.MatchContains) # 设置模糊匹配模式
# 允许清空选择
self.tray_edit.setCurrentText("")
self.tray_layout.addWidget(self.tray_edit)
self.left_layout.addWidget(self.tray_frame)
# 上下料区 - 使用QFrame包裹添加边框
self.output_frame = QFrame()
self.output_frame.setFrameShape(QFrame.StyledPanel)
self.output_frame.setLineWidth(1)
self.output_frame.setFixedHeight(100) # 保持高度不变
self.output_frame.setStyleSheet("QFrame { background-color: #f8f8f8; }")
self.output_layout = QHBoxLayout(self.output_frame)
self.output_layout.setContentsMargins(0, 0, 0, 0)
self.output_layout.setSpacing(0)
# 上料区(拆垛层数)
self.input_area = QWidget()
self.input_area.setFixedWidth(200) # 设置固定宽度
self.input_area.setStyleSheet("background-color: white;")
self.input_area_layout = QVBoxLayout(self.input_area)
self.input_area_layout.setContentsMargins(5, 5, 5, 5)
self.input_area_layout.setSpacing(5)
# 上料区标签
self.input_area_label = QLabel("上料区")
self.input_area_label.setFont(self.normal_font)
self.input_area_label.setAlignment(Qt.AlignCenter)
self.input_area_label.setStyleSheet("font-weight: bold; color: #333333;")
self.input_area_layout.addWidget(self.input_area_label)
# 拆垛层数显示
self.stow_level_label = QLabel("拆垛层数: 1")
self.stow_level_label.setFont(self.normal_font)
self.stow_level_label.setAlignment(Qt.AlignCenter)
self.stow_level_label.setStyleSheet("color: #333333; background-color: #f5f5f5; padding: 5px; border: 1px solid #cccccc; border-radius: 3px;")
self.input_area_layout.addWidget(self.stow_level_label)
self.output_layout.addWidget(self.input_area)
# 下料区(下料层数、下料位置)
self.output_area = QWidget()
self.output_area.setStyleSheet("background-color: white;")
self.output_area_layout = QVBoxLayout(self.output_area)
self.output_area_layout.setContentsMargins(5, 5, 5, 5)
self.output_area_layout.setSpacing(5)
# 下料区标签
self.output_area_label = QLabel("下料区")
self.output_area_label.setFont(self.normal_font)
self.output_area_label.setAlignment(Qt.AlignCenter)
self.output_area_label.setStyleSheet("font-weight: bold; color: #333333;")
self.output_area_layout.addWidget(self.output_area_label)
# 下料层数显示
self.unload_level_label = QLabel("下料层数: 0/0")
self.unload_level_label.setFont(self.normal_font)
self.unload_level_label.setAlignment(Qt.AlignCenter)
self.unload_level_label.setStyleSheet("color: #333333; background-color: #f5f5f5; padding: 5px; border: 1px solid #cccccc; border-radius: 3px;")
self.output_area_layout.addWidget(self.unload_level_label)
# 下料位置显示
self.unload_position_label = QLabel("下料位置: 0")
self.unload_position_label.setFont(self.normal_font)
self.unload_position_label.setAlignment(Qt.AlignCenter)
self.unload_position_label.setStyleSheet("color: #333333; background-color: #f5f5f5; padding: 5px; border: 1px solid #cccccc; border-radius: 3px;")
self.output_area_layout.addWidget(self.unload_position_label)
self.output_layout.addWidget(self.output_area)
self.left_layout.addWidget(self.output_frame)
# 产线控制区 - 使用QFrame包裹添加边框
self.control_frame = QFrame()
self.control_frame.setFrameShape(QFrame.StyledPanel)
self.control_frame.setLineWidth(1)
self.control_layout = QHBoxLayout(self.control_frame)
self.control_layout.setContentsMargins(0, 0, 0, 0)
self.control_layout.setSpacing(0)
self.control_label = QLabel("产线")
self.control_label.setFont(self.normal_font)
self.control_label.setAlignment(Qt.AlignCenter)
self.control_label.setFixedWidth(100) # 设置固定宽度
self.control_label.setStyleSheet("background-color: #e0e0e0; border-right: 1px solid #cccccc; font-weight: bold;")
self.control_layout.addWidget(self.control_label)
# 按钮容器
self.button_container = QWidget()
self.button_layout = QGridLayout(self.button_container)
self.button_layout.setContentsMargins(10, 10, 10, 10)
self.button_layout.setSpacing(10) # 增加按钮间距
# 创建按钮并设置样式
button_style = """
QPushButton {
padding: 8px 16px;
font-weight: bold;
border-radius: 4px;
}
"""
self.input_button = QPushButton("上料")
self.input_button.setFont(self.normal_font)
self.input_button.setStyleSheet(button_style + "background-color: #e3f2fd; border: 1px solid #2196f3;")
self.output_button = QPushButton("下料")
self.output_button.setFont(self.normal_font)
self.output_button.setStyleSheet(button_style + "background-color: #fff8e1; border: 1px solid #ffc107;")
self.start_button = QPushButton("开始")
self.start_button.setFont(self.normal_font)
self.start_button.setStyleSheet(button_style + "background-color: #e8f5e9; border: 1px solid #4caf50;")
self.stop_button = QPushButton("暂停")
self.stop_button.setFont(self.normal_font)
self.stop_button.setStyleSheet(button_style + "background-color: #ffebee; border: 1px solid #f44336;")
self.report_button = QPushButton("报表")
self.report_button.setFont(self.normal_font)
self.report_button.setStyleSheet(button_style + "background-color: #e0e0e0; border: 1px solid #cccccc;")
# 使用网格布局排列按钮
self.button_layout.addWidget(self.input_button, 0, 0)
self.button_layout.addWidget(self.output_button, 0, 1)
self.button_layout.addWidget(self.start_button, 0, 2)
self.button_layout.addWidget(self.stop_button, 0, 3)
self.button_layout.addWidget(self.report_button, 0, 4)
self.control_layout.addWidget(self.button_container)
self.left_layout.addWidget(self.control_frame)
# 添加弹性空间,确保控件紧凑排列在顶部
self.left_layout.addStretch()
def create_right_panel(self):
# 创建右侧整体框架
self.right_frame = QFrame()
self.right_frame.setFrameShape(QFrame.NoFrame) # 移除框架边框
self.right_frame.setLineWidth(0)
self.right_layout.addWidget(self.right_frame)
# 右侧整体使用垂直布局,不设置边距
self.right_frame_layout = QVBoxLayout(self.right_frame)
self.right_frame_layout.setContentsMargins(0, 0, 0, 0)
self.right_frame_layout.setSpacing(0)
# 创建一个垂直分割器,用于控制两个表格的高度比例
self.right_splitter = QSplitter(Qt.Vertical)
# 创建微丝产线表格的容器
self.process_container = QWidget()
self.process_container_layout = QVBoxLayout(self.process_container)
self.process_container_layout.setContentsMargins(0, 0, 0, 0)
self.process_container_layout.setSpacing(0)
# 创建包装记录表格的容器
self.record_container = QWidget()
self.record_container_layout = QVBoxLayout(self.record_container)
self.record_container_layout.setContentsMargins(0, 0, 0, 0)
self.record_container_layout.setSpacing(0)
# 创建微丝产线表格
self.create_process_table()
self.process_container_layout.addWidget(self.process_frame)
# 创建包装记录表格
self.create_record_table()
self.record_container_layout.addWidget(self.record_frame)
# 将两个容器添加到分割器中
self.right_splitter.addWidget(self.process_container)
self.right_splitter.addWidget(self.record_container)
# 设置初始大小比例微丝产线占1/3包装记录占2/3
self.right_splitter.setSizes([100, 200]) # 比例为1:2
# 将分割器添加到右侧布局
self.right_frame_layout.addWidget(self.right_splitter)
# 添加一个通用的表格样式设置方法
def setup_table_common(self, table, hide_headers=True):
"""设置表格的通用样式和属性
Args:
table: 要设置的QTableWidget对象
hide_headers: 是否隐藏默认的表头
"""
# 设置为不可编辑
table.setEditTriggers(QAbstractItemView.NoEditTriggers)
# 隐藏默认表头
if hide_headers:
table.horizontalHeader().setVisible(False)
table.verticalHeader().setVisible(False)
# 显示网格线
table.setShowGrid(True)
# 移除外边框
table.setFrameShape(QFrame.NoFrame)
# 设置表格样式
table.setStyleSheet("""
QTableWidget {
gridline-color: #dddddd;
border: none;
background-color: white;
}
QTableWidget::item {
border: none;
padding: 3px;
}
QTableWidget::item:selected {
background-color: #e0e0ff;
color: black;
}
""")
# 允许用户调整列宽
table.horizontalHeader().setSectionResizeMode(QHeaderView.Interactive)
table.horizontalHeader().setStretchLastSection(True)
return table
# 添加一个通用的表头项创建方法
def create_header_item(self, text, font=None, alignment=Qt.AlignCenter, bg_color="#f8f8f8"):
"""创建表头单元格项
Args:
text: 表头文本
font: 字体默认为None使用self.normal_font
alignment: 对齐方式
bg_color: 背景色
Returns:
QTableWidgetItem: 创建的表头项
"""
item = QTableWidgetItem(text)
item.setTextAlignment(alignment)
item.setFont(font or self.normal_font)
item.setBackground(QBrush(QColor(bg_color)))
return item
def create_process_table(self):
"""创建微丝产线表格,包含上料、检验、包装部分"""
# 创建微丝产线框架
self.process_frame = QFrame()
self.process_frame.setFrameShape(QFrame.NoFrame) # 移除边框
self.process_frame.setLineWidth(0)
self.process_frame.setStyleSheet("QFrame { background-color: #f5f5f5; }") # 与其他标题背景色一致
self.process_layout = QVBoxLayout(self.process_frame)
self.process_layout.setContentsMargins(0, 0, 0, 0)
self.process_layout.setSpacing(0)
# 微丝产线标题
self.process_title = QLabel("微丝产线")
self.process_title.setFont(self.second_title_font)
self.process_title.setAlignment(Qt.AlignLeft | Qt.AlignVCenter)
self.process_title.setFixedHeight(40)
self.process_title.setStyleSheet("background-color: #f5f5f5; padding: 5px;") # 移除底部边框
self.process_layout.addWidget(self.process_title)
# 创建表格内容区域
self.process_content = QWidget()
self.process_content_layout = QVBoxLayout(self.process_content)
self.process_content_layout.setContentsMargins(0, 0, 0, 0)
self.process_content_layout.setSpacing(0)
# 创建表格 - 支持动态配置检验列数
self.inspection_columns = 1 # 默认至少显示1列
# 默认检验标题实际运行时将通过InspectionConfigManager获取
self.inspection_headers = ["检验项"]
total_columns = 2 + self.inspection_columns + 2 # 上料2列 + 检验N列 + 包装2列
self.process_table = QTableWidget(8, total_columns) # 8行1行标题区域 + 1行列标题 + 6行数据
# 应用通用表格设置
self.setup_table_common(self.process_table)
# 设置行高
self.process_table.setRowHeight(0, 30) # 标题区域行高
self.process_table.setRowHeight(1, 30) # 列标题行高
# 设置数据行的行高
for row in range(2, 8): # 工序行
self.process_table.setRowHeight(row, 35)
# 设置列宽
self.set_process_table_column_widths()
# 创建表头 - 合并单元格
self.create_process_table_headers()
# 添加表格到布局
self.process_content_layout.addWidget(self.process_table)
self.process_layout.addWidget(self.process_content)
def create_record_table(self):
"""创建包装记录表格"""
# 创建包装记录框架
self.record_frame = QFrame()
self.record_frame.setFrameShape(QFrame.NoFrame) # 移除边框
self.record_frame.setLineWidth(0)
self.record_frame.setStyleSheet("QFrame { background-color: #f5f5f5; }") # 与其他标题背景色一致
self.record_layout = QVBoxLayout(self.record_frame)
self.record_layout.setContentsMargins(0, 0, 0, 0)
self.record_layout.setSpacing(0)
# 包装记录标题
self.record_title = QLabel("包装记录")
self.record_title.setFont(self.second_title_font)
self.record_title.setAlignment(Qt.AlignLeft | Qt.AlignVCenter)
self.record_title.setFixedHeight(40)
self.record_title.setStyleSheet("background-color: #f5f5f5; padding: 5px;") # 移除底部边框
# 创建标题容器,用于水平布局标题和按钮
self.record_title_container = QWidget()
self.record_title_layout = QHBoxLayout(self.record_title_container)
self.record_title_layout.setContentsMargins(5, 0, 5, 0)
self.record_title_layout.setSpacing(10)
# 添加标题到布局
self.record_title_layout.addWidget(self.record_title)
# 添加弹性空间,确保标题居左
self.record_title_layout.addStretch() # 添加弹性空间
# 将标题容器添加到记录布局
self.record_layout.addWidget(self.record_title_container)
# 创建表格
self.record_table = QTableWidget(13, 10) # 13行10列序号、订单、工程号、品名、规格、托号、轴包装号、重量、净重、完成时间
# 应用通用表格设置但保留表头
self.setup_table_common(self.record_table, hide_headers=False)
# 设置列标题
record_headers = ["序号", "订单", "工程号", "品名", "规格", "托号", "轴包装号", "毛重", "净重", "完成时间"]
self.record_table.setHorizontalHeaderLabels(record_headers)
# 设置表头样式
self.record_table.horizontalHeader().setStyleSheet("""
QHeaderView::section {
background-color: #f8f8f8;
padding: 4px;
border: 1px solid #dddddd;
font-weight: bold;
}
""")
# 设置行高
self.record_table.setRowHeight(12, 35) # 合计行高
# 设置数据行的行高
for row in range(0, 12): # 记录行
self.record_table.setRowHeight(row, 35)
# 设置列宽
column_widths = [60, 170, 170, 120, 120, 150, 100, 100, 100, 160]
for col, width in enumerate(column_widths):
self.record_table.setColumnWidth(col, width)
self.record_table.horizontalHeader().resizeSection(col, width)
# 添加表格到布局
self.record_layout.addWidget(self.record_table)
# 添加一个通用的单元格创建方法
def create_cell_item(self, text, alignment=Qt.AlignCenter):
"""创建表格单元格项
Args:
text: 单元格文本
alignment: 对齐方式
Returns:
QTableWidgetItem: 创建的单元格项
"""
item = QTableWidgetItem(str(text))
item.setTextAlignment(alignment)
return item
def set_inspection_columns(self, columns, headers=None):
"""设置检验列数和标题
Args:
columns: 检验列数量
headers: 检验列标题列表如果为None则使用默认标题
"""
# 确保列数在1-6之间
columns = max(1, min(6, columns))
# 保存旧的列数
old_column_count = self.process_table.columnCount()
# 清除表头行的所有项目
if old_column_count > 0:
for c_idx in range(old_column_count):
# 第0行 - 主标题
item_r0 = self.process_table.takeItem(0, c_idx)
if item_r0:
del item_r0
# 第1行 - 子标题
item_r1 = self.process_table.takeItem(1, c_idx)
if item_r1:
del item_r1
# 清除所有单元格合并
for row in range(2):
for col in range(old_column_count):
try:
self.process_table.setSpan(row, col, 1, 1)
except:
pass # 忽略错误,可能有些单元格没有合并
# 更新检验列数
self.inspection_columns = columns
# 更新检验标题
if headers is not None and len(headers) >= columns:
self.inspection_headers = headers[:columns] # 只使用前N个标题
elif len(self.inspection_headers) < columns:
# 如果当前标题不足,扩展标题列表
current_len = len(self.inspection_headers)
for i in range(current_len, columns):
self.inspection_headers.append(f"检验项{i+1}")
# 截断多余的标题
if len(self.inspection_headers) > columns:
self.inspection_headers = self.inspection_headers[:columns]
# 计算总列数
total_columns = 2 + self.inspection_columns + 3 # 上料2列 + 检验N列 + 包装3列
self.process_table.setColumnCount(total_columns)
# 重新设置列宽
self.set_process_table_column_widths()
# 重新创建表头
self.create_process_table_headers()
def create_process_table_headers(self):
"""创建微丝产线表格的表头,实现合并单元格"""
# 第一行:上料、检验、包装标题区域
# 上料区域2列
self.process_table.setSpan(0, 0, 1, 2)
self.process_table.setItem(0, 0, self.create_header_item("上料"))
# 检验区域(动态列数)
self.process_table.setSpan(0, 2, 1, self.inspection_columns)
self.process_table.setItem(0, 2, self.create_header_item("检验"))
# 包装区域3列
packaging_start_col = 2 + self.inspection_columns
self.process_table.setSpan(0, packaging_start_col, 1, 3)
self.process_table.setItem(0, packaging_start_col, self.create_header_item("包装"))
# 第二行:列标题
# 上料区域列标题
material_headers = ["序号", "工程号"]
for col, header in enumerate(material_headers):
self.process_table.setItem(1, col, self.create_header_item(header))
# 检验区域列标题 - 可动态配置
for i in range(self.inspection_columns):
header_text = ""
if i < len(self.inspection_headers):
header_text = self.inspection_headers[i]
else:
header_text = f"检验项{i+1}" # 如果没有定义足够的标题,使用默认标题
self.process_table.setItem(1, 2 + i, self.create_header_item(header_text))
# 包装区域列标题
packaging_headers = ["贴标", "毛重", "净重"]
for i, header in enumerate(packaging_headers):
self.process_table.setItem(1, packaging_start_col + i, self.create_header_item(header))
def set_process_table_column_widths(self):
"""设置微丝产线表格的列宽 - 支持动态配置检验列"""
# 上料区域列宽
self.process_table.setColumnWidth(0, 70) # 序号
self.process_table.setColumnWidth(1, 190) # 工程号
# 检验区域列宽
for i in range(self.inspection_columns):
self.process_table.setColumnWidth(2 + i, 140) # 检验列
# 包装区域列宽
packaging_start_col = 2 + self.inspection_columns
self.process_table.setColumnWidth(packaging_start_col, 140) # 贴标
self.process_table.setColumnWidth(packaging_start_col + 1, 140) # 毛重
self.process_table.setColumnWidth(packaging_start_col + 2, 140) # 净重
def update_time(self):
current_time = QDateTime.currentDateTime().toString('yyyy-MM-dd hh:mm:ss')
self.time_label.setText(current_time)