package com.mes.component; import javax.swing.*; import javax.swing.border.LineBorder; import java.awt.*; /** * 氦检工位面板:读码回显 + 流程状态 + 本底/漏率 + 检测结果 + PLC 信号灯 * 视觉沿用原客户端风格:白底、黑底彩字状态、原图标 * 所有 set 方法可在任意线程调用,内部已切到 EDT */ public class StationPanel extends JPanel { // 状态文字色,沿用原顶栏绿/红 public static final Color STATE_WAIT = Color.GREEN; // 待机(等待扫码)正常状态 public static final Color STATE_BUSY = new Color(0xFF, 0xD5, 0x4F); public static final Color STATE_OK = Color.GREEN; public static final Color STATE_NG = Color.RED; public static final Color STATE_RUN = new Color(0x4F, 0xC3, 0xF7); // 信号灯下标 public static final int SIG_SCAN = 0; // 扫码成功 public static final int SIG_ALLOW = 1; // MES 允许 public static final int SIG_START = 2; // 检测开始 public static final int SIG_END = 3; // 检测结束 public static final int SIG_LEAK = 4; // 泄露 public static final int SIG_BASE = 5; // 本底 public static final int SIG_CODE = 6; // 二维码 private static final String[] SIG_NAMES = {"扫码成功", "MES允许", "检测开始", "检测结束", "泄露", "本底", "二维码"}; private static final Icon DOT_GREEN = stationDot(true); private static final Icon DOT_GREY = stationDot(false); private static final Icon ICON_OK = new ImageIcon(StationPanel.class.getResource("/bg/ok_bg.png")); private static final Icon ICON_NG = new ImageIcon(StationPanel.class.getResource("/bg/ng_bg.png")); private final JLabel[] signalLabels = new JLabel[SIG_NAMES.length]; private final JTextField codeField; private final JLabel stateLabel; private final JTextField baseField; private final JTextField leakField; private final JLabel resultLabel; private final JLabel retryLabel; /** * @param title 工位标题,如 "A 工位" * @param addrs 7 个信号点位,顺序:扫码成功、MES允许、检测开始、检测结束、泄露、本底、二维码 */ public StationPanel(String title, String[] addrs) { setLayout(null); setBackground(Color.WHITE); JLabel titleLabel = new JLabel(title); titleLabel.setFont(new Font("微软雅黑", Font.PLAIN, 24)); titleLabel.setBounds(20, 4, 340, 36); add(titleLabel); stateLabel = new JLabel("等待扫码", SwingConstants.CENTER); stateLabel.setFont(new Font("微软雅黑", Font.BOLD, 32)); stateLabel.setForeground(STATE_WAIT); stateLabel.setOpaque(true); stateLabel.setBackground(Color.BLACK); stateLabel.setBounds(20, 44, 420, 56); add(stateLabel); // 读码回显框:沿用原扫码框样式,只读、居中 codeField = new JTextField(); codeField.setHorizontalAlignment(SwingConstants.CENTER); codeField.setEditable(false); codeField.setFont(new Font("微软雅黑", Font.PLAIN, 28)); codeField.setBounds(20, 106, 420, 46); add(codeField); JLabel baseTitle = new JLabel("本底"); baseTitle.setFont(new Font("微软雅黑", Font.PLAIN, 20)); baseTitle.setForeground(new Color(0x61, 0x61, 0x61)); baseTitle.setBounds(30, 158, 90, 32); add(baseTitle); baseField = new JTextField(); baseField.setEditable(false); baseField.setHorizontalAlignment(SwingConstants.CENTER); baseField.setFont(new Font("微软雅黑", Font.BOLD, 24)); baseField.setBounds(120, 158, 160, 32); add(baseField); JLabel leakTitle = new JLabel("漏率"); leakTitle.setFont(new Font("微软雅黑", Font.PLAIN, 20)); leakTitle.setForeground(new Color(0x61, 0x61, 0x61)); leakTitle.setBounds(30, 194, 90, 32); add(leakTitle); leakField = new JTextField(); leakField.setEditable(false); leakField.setHorizontalAlignment(SwingConstants.CENTER); leakField.setFont(new Font("微软雅黑", Font.BOLD, 24)); leakField.setBounds(120, 194, 160, 32); add(leakField); // 检测结果显示在工位右侧,带边框;未出结果时灰显 OK resultLabel = new JLabel("OK", SwingConstants.CENTER); resultLabel.setFont(new Font("微软雅黑", Font.BOLD, 30)); resultLabel.setForeground(new Color(0xBD, 0xBD, 0xBD)); resultLabel.setIconTextGap(12); resultLabel.setOpaque(true); resultLabel.setBackground(Color.WHITE); resultLabel.setBorder(new LineBorder(new Color(0xA0, 0xA0, 0xA0))); resultLabel.setBounds(290, 156, 150, 70); add(resultLabel); retryLabel = new JLabel("该工件为返修件", SwingConstants.CENTER); retryLabel.setFont(new Font("微软雅黑", Font.BOLD, 18)); retryLabel.setForeground(Color.RED); retryLabel.setBounds(20, 228, 250, 26); retryLabel.setVisible(false); add(retryLabel); // PLC 信号灯:两列排布,点位写在括号里 for (int i = 0; i < SIG_NAMES.length; i++) { int col = i / 4; int row = i % 4; JLabel lamp = new JLabel(SIG_NAMES[i] + "(" + addrs[i] + ")"); lamp.setIcon(DOT_GREY); lamp.setFont(new Font("微软雅黑", Font.PLAIN, 16)); lamp.setForeground(new Color(0x42, 0x42, 0x42)); lamp.setBounds(20 + col * 210, 258 + row * 26, 205, 26); add(lamp); signalLabels[i] = lamp; } } /** 生成小圆点图标,避免直接用 36x36 大图标 */ private static Icon stationDot(boolean green) { ImageIcon src = new ImageIcon(StationPanel.class.getResource(green ? "/bg/green_dot.png" : "/bg/grey_dot.png")); Image img = src.getImage().getScaledInstance(18, 18, Image.SCALE_SMOOTH); return new ImageIcon(img); } /** 点亮/熄灭某个信号灯,index 用 SIG_xxx 常量 */ public void setSignal(int index, boolean on) { if (index < 0 || index >= signalLabels.length) { return; } SwingUtilities.invokeLater(() -> signalLabels[index].setIcon(on ? DOT_GREEN : DOT_GREY)); } public void setCode(String code) { SwingUtilities.invokeLater(() -> codeField.setText(code == null ? "" : code)); } /** color 用 STATE_xxx 常量,同一色调的文字显示在黑底上 */ public void setState(String text, Color color) { SwingUtilities.invokeLater(() -> { stateLabel.setText(text); stateLabel.setForeground(color); }); } public void setData(String base, String leak) { SwingUtilities.invokeLater(() -> { baseField.setText(base == null ? "" : base); leakField.setText(leak == null ? "" : leak); }); } /** result 传 OK / NG,其他值显示 -- */ public void setResult(String result) { SwingUtilities.invokeLater(() -> { if ("OK".equalsIgnoreCase(result)) { resultLabel.setIcon(ICON_OK); resultLabel.setText("OK"); resultLabel.setForeground(STATE_OK); } else if ("NG".equalsIgnoreCase(result)) { resultLabel.setIcon(ICON_NG); resultLabel.setText("NG"); resultLabel.setForeground(STATE_NG); } else { resultLabel.setIcon(null); resultLabel.setText("OK"); resultLabel.setForeground(new Color(0xBD, 0xBD, 0xBD)); } }); } public void setRetry(boolean show) { SwingUtilities.invokeLater(() -> retryLabel.setVisible(show)); } /** 复位到等待扫码 */ public void reset() { SwingUtilities.invokeLater(() -> { codeField.setText(""); baseField.setText(""); leakField.setText(""); stateLabel.setText("等待扫码"); stateLabel.setForeground(STATE_WAIT); resultLabel.setIcon(null); resultLabel.setText("OK"); resultLabel.setForeground(new Color(0xBD, 0xBD, 0xBD)); retryLabel.setVisible(false); for (JLabel lamp : signalLabels) { lamp.setIcon(DOT_GREY); } }); } }