826220679@qq.com
10 天以前 176cfa1a137d2050d4e8a105dfdbdc8f1b32afb2
src/dell_system/MessageViewPanel.java
@@ -16,50 +16,46 @@
import udptcp.UDPPortBReceiver;
public class MessageViewPanel extends JPanel {
    /**
     *
     */
    private static final long serialVersionUID = 1L;
    private ResourceBundle messages;   // 国际化消息资源包
    // UI组件声明
    private JButton btnStart, btnPause, btnClear, btnSend; // 控制按钮:开始、暂停、清除、发送
    private static JComboBox<String> cbDataType; // 下拉框:数据类型、协议、设备ID
    private ResourceBundle messages;
    private JButton btnStart, btnPause, btnClear, btnSend;
    private static JComboBox<String> cbDataType;
    private static JComboBox<String> cbProtocol;
    private static JComboBox<String> cbDeviceId;
    private static JComboBox<String> cbRemoteDevice; // 远程设备下拉框
    private static JCheckBox chkAutoSave; // 复选框:自动保存、显示来源、十六进制显示、ASCII显示
    private static JComboBox<String> cbRemoteDevice;
    private static JCheckBox chkAutoSave;
    private static JCheckBox chkShowSource;
    private static JCheckBox chkHexDisplay;
    private static JCheckBox chkAsciiDisplay;
    private static JTextArea txtDataView; // 数据显示区域
    private JScrollPane scrollPane; // 带滚动条的面板
    private JTextField txtSendData; // 发送数据文本框
    private JRadioButton rdoSendHex; // HEX发送单选按钮
    private JRadioButton rdoSendAscii; // ASCII发送单选按钮
    private JCheckBox chkAppendNewline; // 回车换行复选框
    // 添加静态变量跟踪窗口可见状态
    private static JTextArea txtDataView;
    private JScrollPane scrollPane;
    private JTextField txtSendData;
    private JRadioButton rdoSendHex;
    private JRadioButton rdoSendAscii;
    private JCheckBox chkAppendNewline;
    private static final ThreadLocal<StringBuilder> SB =
            ThreadLocal.withInitial(() -> new StringBuilder(256));
    private static final char[] DIGITS = "0123456789".toCharArray();
    private static final String COLON = ":";
    private static final String PREFIX = "[";
    private static final String SUFFIX = "]";
    public static volatile boolean isWindowVisible = false;
    // 状态变量
    private static boolean isCapturing = false; // 是否正在捕获数据的标志
    // 修改为Map存储设备及其本地端口
    private static boolean isCapturing = false;
    private static boolean isStarted = false; // 新增:跟踪开始按钮状态
    private static Map<String, Integer> remoteDeviceLocalPortMap = new HashMap<>();
    // 构造函数
    public MessageViewPanel(ResourceBundle messages) {
        this.messages = messages; // 初始化消息资源包
        initializeUI(); // 初始化用户界面
    }
    public MessageViewPanel(ResourceBundle messages) {
        this.messages = messages;
        initializeUI();
    }
    public void addNotify() {
        super.addNotify();
        Window window = SwingUtilities.getWindowAncestor(this);
        if (window != null) {
            isWindowVisible = true; // 面板已添加到可见窗口
            isWindowVisible = true;
            window.addWindowListener(new WindowAdapter() {
                @Override
                public void windowClosing(WindowEvent e) {
@@ -74,154 +70,129 @@
        }
    }
    // 初始化UI组件
    private void initializeUI() {
        setLayout(new GridBagLayout()); // 使用网格袋布局
        GridBagConstraints gbc = new GridBagConstraints(); // 布局约束对象
        gbc.insets = new Insets(5, 10, 5, 10); // 设置组件间距(上、左、下、右)
        gbc.anchor = GridBagConstraints.WEST; // 组件靠左对齐
        gbc.fill = GridBagConstraints.HORIZONTAL; // 水平填充
        setBackground(new Color(240, 245, 249)); // 设置背景色
        setLayout(new GridBagLayout());
        GridBagConstraints gbc = new GridBagConstraints();
        gbc.insets = new Insets(5, 10, 5, 10);
        gbc.anchor = GridBagConstraints.WEST;
        gbc.fill = GridBagConstraints.HORIZONTAL;
        setBackground(new Color(240, 245, 249));
        // 下拉框区域
        gbc.gridx = 0; // 起始列
        gbc.gridy = 0; // 起始行
        gbc.gridwidth = 1; // 占用1列宽度
        gbc.weightx = 0.25; // 水平权重
        gbc.gridx = 0;
        gbc.gridy = 0;
        gbc.gridwidth = 1;
        gbc.weightx = 0.25;
        // 数据类型下拉框面板
        JPanel dataTypePanel = new JPanel(new BorderLayout(5, 0)); // 使用边界布局
        dataTypePanel.setBackground(new Color(240, 245, 249)); // 设置背景色
        dataTypePanel.add(createLabel(messages.getString("MESSAGE_VIEW_DATA_TYPE")), BorderLayout.WEST); // 添加标签
        cbDataType = new JComboBox<>(); // 创建下拉框
        loadtyps();// 添加"所有类型"选项
        dataTypePanel.add(cbDataType, BorderLayout.CENTER); // 将下拉框添加到面板中央
        add(dataTypePanel, gbc); // 将面板添加到主面板
        JPanel dataTypePanel = new JPanel(new BorderLayout(5, 0));
        dataTypePanel.setBackground(new Color(240, 245, 249));
        dataTypePanel.add(createLabel(messages.getString("MESSAGE_VIEW_DATA_TYPE")), BorderLayout.WEST);
        cbDataType = new JComboBox<>();
        loadtyps();
        dataTypePanel.add(cbDataType, BorderLayout.CENTER);
        add(dataTypePanel, gbc);
        // 协议下拉框
        gbc.gridx++; // 移动到下一列
        JPanel protocolPanel = new JPanel(new BorderLayout(5, 0)); // 协议选择面板
        protocolPanel.setBackground(new Color(240, 245, 249)); // 设置背景色
        protocolPanel.add(createLabel(messages.getString("MESSAGE_VIEW_PROTOCOL")), BorderLayout.WEST); // 添加协议标签
        cbProtocol = new JComboBox<>(new String[]{ // 创建协议下拉框并初始化选项
                messages.getString("MESSAGE_VIEW_ALL_PROTOCOLS"), // 所有协议
                "UDP", // UDP协议
                "TCP", // TCP协议
                "MQTT", // MQTT协议
                "HTTP" // HTTP协议
        gbc.gridx++;
        JPanel protocolPanel = new JPanel(new BorderLayout(5, 0));
        protocolPanel.setBackground(new Color(240, 245, 249));
        protocolPanel.add(createLabel(messages.getString("MESSAGE_VIEW_PROTOCOL")), BorderLayout.WEST);
        cbProtocol = new JComboBox<>(new String[]{
                "ALL",
                "55AA01", "55AA02", "55AA03", "55AA05", "55AA07",
                "55AA0A", "55AA0C", "55AA12", "55AA14", "55AA20",
                "GNGGA", "XTB"
        });
        protocolPanel.add(cbProtocol, BorderLayout.CENTER); // 将下拉框添加到面板中央
        add(protocolPanel, gbc); // 将面板添加到主面板
        protocolPanel.add(cbProtocol, BorderLayout.CENTER);
        add(protocolPanel, gbc);
        // 设备ID下拉框
        gbc.gridx++; // 移动到下一列
        JPanel devicePanel = new JPanel(new BorderLayout(5, 0)); // 设备ID选择面板
        devicePanel.setBackground(new Color(240, 245, 249)); // 设置背景色
        devicePanel.add(createLabel(messages.getString("MESSAGE_VIEW_DEVICE_ID")), BorderLayout.WEST); // 添加设备ID标签
        cbDeviceId = new JComboBox<>(); // 创建设备ID下拉框
        cbDeviceId.setEditable(true); // 设置为可编辑,允许手动输入设备ID
        cbDeviceId.addItem(messages.getString("MESSAGE_VIEW_ALL_DEVICES")); // 添加"所有设备"选项
        loadDeviceIds(); // 加载设备ID列表
        devicePanel.add(cbDeviceId, BorderLayout.CENTER); // 将下拉框添加到面板中央
        add(devicePanel, gbc); // 将面板添加到主面板
        gbc.gridx++;
        JPanel devicePanel = new JPanel(new BorderLayout(5, 0));
        devicePanel.setBackground(new Color(240, 245, 249));
        devicePanel.add(createLabel(messages.getString("MESSAGE_VIEW_DEVICE_ID")), BorderLayout.WEST);
        cbDeviceId = new JComboBox<>();
        cbDeviceId.setEditable(true);
        cbDeviceId.addItem("ALL");
        loadDeviceIds();
        devicePanel.add(cbDeviceId, BorderLayout.CENTER);
        add(devicePanel, gbc);
        // 远程设备下拉框
        gbc.gridx++; // 移动到下一列
        JPanel remoteDevicePanel = new JPanel(new BorderLayout(5, 0)); // 远程设备选择面板
        remoteDevicePanel.setBackground(new Color(240, 245, 249)); // 设置背景色
        remoteDevicePanel.add(createLabel(messages.getString("MESSAGE_VIEW_REMOTE_DEVICE")), BorderLayout.WEST); // 添加远程设备标签
        cbRemoteDevice = new JComboBox<>(); // 创建远程设备下拉框
        cbRemoteDevice.setEditable(true); // 设置为可编辑
        cbRemoteDevice.addItem(messages.getString("MESSAGE_VIEW_ALL_DEVICES")); // 添加"所有设备"选项
        remoteDevicePanel.add(cbRemoteDevice, BorderLayout.CENTER); // 将下拉框添加到面板中央
        add(remoteDevicePanel, gbc); // 将面板添加到主面板
        gbc.gridx++;
        JPanel remoteDevicePanel = new JPanel(new BorderLayout(5, 0));
        remoteDevicePanel.setBackground(new Color(240, 245, 249));
        remoteDevicePanel.add(createLabel(messages.getString("MESSAGE_VIEW_REMOTE_DEVICE")), BorderLayout.WEST);
        cbRemoteDevice = new JComboBox<>();
        cbRemoteDevice.setEditable(true);
        cbRemoteDevice.addItem(messages.getString("MESSAGE_VIEW_ALL_DEVICES"));
        remoteDevicePanel.add(cbRemoteDevice, BorderLayout.CENTER);
        add(remoteDevicePanel, gbc);
        // 复选框区域
        gbc.gridx = 0; // 重置列位置
        gbc.gridy++; // 移动到下一行
        gbc.gridwidth = 4; // 横跨4列
        gbc.weightx = 1.0; // 水平权重
        // 复选框区域 - 简化为两个复选框
        gbc.gridx = 0;
        gbc.gridy++;
        gbc.gridwidth = 4;
        gbc.weightx = 1.0;
        JPanel checkboxPanel = new JPanel(new GridLayout(1, 4, 6, 0)); // 创建网格布局面板(1行4列)
        checkboxPanel.setBackground(new Color(240, 245, 249)); // 设置背景色
        chkAutoSave = createStyledCheckbox(messages.getString("MESSAGE_VIEW_AUTO_SAVE")); // 创建自动保存复选框
        chkShowSource = createStyledCheckbox(messages.getString("MESSAGE_VIEW_SHOW_SOURCE")); // 创建显示来源复选框
        chkHexDisplay = createStyledCheckbox(messages.getString("MESSAGE_VIEW_HEX_DISPLAY")); // 创建十六进制显示复选框
        chkAsciiDisplay = createStyledCheckbox(messages.getString("MESSAGE_VIEW_ASCII_DISPLAY")); // 创建ASCII显示复选框
        // 将复选框添加到面板
        JPanel checkboxPanel = new JPanel(new GridLayout(1, 2, 6, 0)); // 修改为2列
        checkboxPanel.setBackground(new Color(240, 245, 249));
        chkAutoSave = createStyledCheckbox(messages.getString("MESSAGE_VIEW_AUTO_SAVE"));
        chkShowSource = createStyledCheckbox(messages.getString("MESSAGE_VIEW_SHOW_SOURCE"));
        // 移除了十六进制和ASCII显示复选框
        checkboxPanel.add(chkAutoSave);
        checkboxPanel.add(chkShowSource);
        checkboxPanel.add(chkHexDisplay);
        checkboxPanel.add(chkAsciiDisplay);
        add(checkboxPanel, gbc); // 将复选框面板添加到主面板
        add(checkboxPanel, gbc);
        // 数据显示区域
        gbc.gridy++; // 移动到下一行
        gbc.weighty = 1.0; // 垂直权重
        gbc.fill = GridBagConstraints.BOTH; // 双向填充
        gbc.gridy++;
        gbc.weighty = 1.0;
        gbc.fill = GridBagConstraints.BOTH;
        txtDataView = new JTextArea(); // 创建文本区域
        txtDataView.setFont(new Font("Monospaced", Font.PLAIN, 14)); // 设置等宽字体
        txtDataView.setEditable(false); // 设置为不可编辑
        scrollPane = new JScrollPane(txtDataView); // 创建带滚动条的面板
        txtDataView = new JTextArea();
        txtDataView.setFont(new Font("Monospaced", Font.PLAIN, 14));
        txtDataView.setEditable(false);
        scrollPane = new JScrollPane(txtDataView);
        scrollPane.setPreferredSize(new Dimension(800, 400));
        scrollPane.setBorder(BorderFactory.createTitledBorder( // 设置带标题的边框
                BorderFactory.createLineBorder(new Color(180, 180, 220)), // 边框颜色
                messages.getString("MESSAGE_VIEW_DATA_PANEL"), // 标题文本
                TitledBorder.LEFT, // 标题位置
                TitledBorder.TOP, // 标题位置
                new Font("微软雅黑", Font.BOLD, 12), // 标题字体
                new Color(70, 130, 180) // 标题颜色
                ));
        scrollPane.setBorder(BorderFactory.createTitledBorder(
                BorderFactory.createLineBorder(new Color(180, 180, 220)),
                messages.getString("MESSAGE_VIEW_DATA_PANEL"),
                TitledBorder.LEFT,
                TitledBorder.TOP,
                new Font("微软雅黑", Font.BOLD, 12),
                new Color(70, 130, 180)
        ));
        add(scrollPane, gbc); // 将滚动面板添加到主面板
        add(scrollPane, gbc);
        // 按钮面板区域
        gbc.gridy++; // 移动到下一行
        gbc.weighty = 0; // 重置垂直权重
        gbc.fill = GridBagConstraints.HORIZONTAL; // 水平填充
        gbc.gridy++;
        gbc.weighty = 0;
        gbc.fill = GridBagConstraints.HORIZONTAL;
        // 按钮面板
        JPanel buttonPanel = new JPanel(new FlowLayout(FlowLayout.LEFT, 10, 5)); // 使用流式布局(左对齐)
        buttonPanel.setBackground(new Color(240, 245, 249)); // 设置背景色
        btnStart = createStyledButton(messages.getString("MESSAGE_VIEW_START"), new Color(70, 130, 180)); // 创建开始按钮(蓝色)
        btnPause = createStyledButton(messages.getString("MESSAGE_VIEW_PAUSE"), new Color(218, 165, 32)); // 创建暂停按钮(金色)
        btnClear = createStyledButton(messages.getString("MESSAGE_VIEW_CLEAR"), new Color(205, 92, 92)); // 创建清除按钮(红色)
        JPanel buttonPanel = new JPanel(new FlowLayout(FlowLayout.LEFT, 10, 5));
        buttonPanel.setBackground(new Color(240, 245, 249));
        btnStart = createStyledButton(messages.getString("MESSAGE_VIEW_START"), new Color(70, 130, 180));
        btnPause = createStyledButton(messages.getString("MESSAGE_VIEW_PAUSE"), new Color(218, 165, 32));
        btnClear = createStyledButton(messages.getString("MESSAGE_VIEW_CLEAR"), new Color(205, 92, 92));
        // 发送相关控件
        txtSendData = new JTextField(30); // 发送数据文本框
        txtSendData.setFont(new Font("微软雅黑", Font.PLAIN, 12)); // 设置字体
        btnSend = createStyledButton(messages.getString("MESSAGE_VIEW_SEND"), new Color(60, 179, 113)); // 创建发送按钮(绿色)
        txtSendData = new JTextField(30);
        txtSendData.setFont(new Font("微软雅黑", Font.PLAIN, 12));
        btnSend = createStyledButton(messages.getString("MESSAGE_VIEW_SEND"), new Color(60, 179, 113));
        // 创建发送选项面板
        JPanel sendOptionsPanel = new JPanel(new FlowLayout(FlowLayout.LEFT, 5, 0));
        sendOptionsPanel.setBackground(new Color(240, 245, 249));
        // 创建单选按钮组
        ButtonGroup sendFormatGroup = new ButtonGroup();
        // 创建HEX发送单选按钮
        rdoSendHex = createStyledRadioButton(messages.getString("MESSAGE_VIEW_SEND_HEX"));
        // 创建ASCII发送单选按钮
        rdoSendAscii = createStyledRadioButton(messages.getString("MESSAGE_VIEW_SEND_ASCII"));
        // 将单选按钮添加到按钮组
        sendFormatGroup.add(rdoSendHex);
        sendFormatGroup.add(rdoSendAscii);
        // 默认选中ASCII发送
        rdoSendAscii.setSelected(true);
        // 回车换行复选框
        chkAppendNewline = createStyledCheckbox(messages.getString("MESSAGE_VIEW_APPEND_NEWLINE"));
        sendOptionsPanel.add(rdoSendHex);
        sendOptionsPanel.add(rdoSendAscii);
        sendOptionsPanel.add(chkAppendNewline);
        // 将按钮添加到按钮面板
        buttonPanel.add(btnStart);
        buttonPanel.add(btnPause);
        buttonPanel.add(btnClear);
@@ -229,55 +200,46 @@
        buttonPanel.add(btnSend);
        buttonPanel.add(sendOptionsPanel);
        add(buttonPanel, gbc); // 将按钮面板添加到主面板
        add(buttonPanel, gbc);
        // 设置按钮动作
        setupActions();
    }
    // 创建带样式的标签
    private JLabel createLabel(String text) {
        JLabel label = new JLabel(text); // 创建标签
        label.setFont(new Font("微软雅黑", Font.BOLD, 12)); // 设置字体
        label.setForeground(new Color(70, 70, 70)); // 设置前景色
        JLabel label = new JLabel(text);
        label.setFont(new Font("微软雅黑", Font.BOLD, 12));
        label.setForeground(new Color(70, 70, 70));
        return label;
    }
    // 创建带样式的按钮
    private JButton createStyledButton(String text, Color bgColor) {
        JButton button = new JButton(text); // 创建按钮
        button.setFont(new Font("微软雅黑", Font.BOLD, 12)); // 设置字体
        button.setBackground(bgColor); // 设置背景色
        button.setForeground(Color.WHITE); // 设置前景色(白色)
        button.setFocusPainted(false); // 禁用焦点边框
        button.setBorder(BorderFactory.createCompoundBorder( // 设置复合边框
                BorderFactory.createLineBorder(bgColor.darker(), 1), // 外部边框(深色)
                BorderFactory.createEmptyBorder(5, 15, 5, 15) // 内部边距
                ));
        JButton button = new JButton(text);
        button.setFont(new Font("微软雅黑", Font.BOLD, 12));
        button.setBackground(bgColor);
        button.setForeground(Color.WHITE);
        button.setFocusPainted(false);
        button.setBorder(BorderFactory.createCompoundBorder(
                BorderFactory.createLineBorder(bgColor.darker(), 1),
                BorderFactory.createEmptyBorder(5, 15, 5, 15)
        ));
        return button;
    }
    // 创建带样式的复选框
    private JCheckBox createStyledCheckbox(String text) {
        JCheckBox checkBox = new JCheckBox(text); // 创建复选框
        checkBox.setFont(new Font("微软雅黑", Font.PLAIN, 12)); // 设置字体
        checkBox.setBackground(new Color(240, 245, 249)); // 设置背景色
        checkBox.setForeground(new Color(70, 70, 70)); // 设置前景色
        JCheckBox checkBox = new JCheckBox(text);
        checkBox.setFont(new Font("微软雅黑", Font.PLAIN, 12));
        checkBox.setBackground(new Color(240, 245, 249));
        checkBox.setForeground(new Color(70, 70, 70));
        return checkBox;
    }
    // 创建带样式的单选按钮
    private JRadioButton createStyledRadioButton(String text) {
        JRadioButton radioButton = new JRadioButton(text); // 创建单选按钮
        radioButton.setFont(new Font("微软雅黑", Font.PLAIN, 12)); // 设置字体
        radioButton.setBackground(new Color(240, 245, 249)); // 设置背景色
        radioButton.setForeground(new Color(70, 70, 70)); // 设置前景色
        // 美化选中效果
        JRadioButton radioButton = new JRadioButton(text);
        radioButton.setFont(new Font("微软雅黑", Font.PLAIN, 12));
        radioButton.setBackground(new Color(240, 245, 249));
        radioButton.setForeground(new Color(70, 70, 70));
        radioButton.setIcon(new RadioButtonIcon(false));
        radioButton.setSelectedIcon(new RadioButtonIcon(true));
        // 添加鼠标悬停效果
        radioButton.addMouseListener(new java.awt.event.MouseAdapter() {
            public void mouseEntered(java.awt.event.MouseEvent evt) {
                radioButton.setForeground(new Color(30, 144, 255));
@@ -286,11 +248,9 @@
                radioButton.setForeground(new Color(70, 70, 70));
            }
        });
        return radioButton;
    }
    // 自定义单选按钮图标
    private static class RadioButtonIcon implements Icon {
        private static final int SIZE = 14;
        private final boolean selected;
@@ -305,19 +265,14 @@
            g2d.setRenderingHint(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON);
            if (selected) {
                // 选中状态 - 蓝色填充
                g2d.setColor(new Color(70, 130, 180));
                g2d.fillOval(x, y, SIZE, SIZE);
                // 内圆 - 白色
                g2d.setColor(Color.WHITE);
                g2d.fillOval(x + SIZE/4, y + SIZE/4, SIZE/2, SIZE/2);
            } else {
                // 未选中状态 - 灰色边框
                g2d.setColor(new Color(150, 150, 150));
                g2d.drawOval(x, y, SIZE-1, SIZE-1);
            }
            g2d.dispose();
        }
@@ -332,77 +287,65 @@
        }
    }
    // 加载数据类型
    private void loadtyps() {
        cbDataType.removeAllItems();
        // 添加国际化选项
        cbDataType.addItem(messages.getString("MESSAGE_VIEW_ALL_TYPES"));
        cbDataType.addItem(messages.getString("MESSAGE_VIEW_UDP_PORT_A"));
        cbDataType.addItem(messages.getString("MESSAGE_VIEW_UDP_PORT_B"));
        cbDataType.addItem(messages.getString("MESSAGE_VIEW_TCP_PORT"));
        cbDataType.addItem(messages.getString("MESSAGE_VIEW_MQTT_PORT"));
        cbDataType.addItem("UDPA");
        cbDataType.addItem("UDPB");
        cbDataType.addItem("TCP");
    }
    // 设置按钮动作
    private void setupActions() {
        btnStart.addActionListener(e -> startCapture()); // 开始按钮绑定开始捕获方法
        btnPause.addActionListener(e -> pauseCapture()); // 暂停按钮绑定暂停捕获方法
        btnClear.addActionListener(e -> clearDisplay()); // 清除按钮绑定清除显示方法
        btnSend.addActionListener(e -> sendData()); // 发送按钮绑定发送方法
        btnStart.addActionListener(e -> startCapture());
        btnPause.addActionListener(e -> pauseCapture());
        btnClear.addActionListener(e -> clearDisplay());
        btnSend.addActionListener(e -> sendData());
    }
    // 开始捕获数据
    private void startCapture() {
        if (!isCapturing) { // 如果当前未在捕获状态
            isCapturing = true; // 设置捕获状态为true
            btnStart.setEnabled(false); // 禁用开始按钮
            btnPause.setEnabled(true); // 启用暂停按钮
            // 启动数据捕获线程
        if (!isCapturing) {
            isStarted = true; // 设置开始标志
            isCapturing = true;
            btnStart.setEnabled(false);
            btnPause.setEnabled(true);
        }
    }
    // 暂停捕获数据
    private void pauseCapture() {
        isCapturing = false; // 设置捕获状态为false
        btnStart.setEnabled(true); // 启用开始按钮
        btnPause.setEnabled(false); // 禁用暂停按钮
        isStarted = false; // 清除开始标志
        isCapturing = false;
        btnStart.setEnabled(true);
        btnPause.setEnabled(false);
    }
    // 清除数据显示
    private void clearDisplay() {
        txtDataView.setText(""); // 清空文本区域
        txtDataView.setText("");
    }
    // 发送数据到远程设备
    private void sendData() {
        // 使用新方法获取当前资源包
        ResourceBundle currentMessages = Languages.getCurrentMessages();
        ResourceBundle currentMessages = Languages.getCurrentMessages();
        String selectedDevice = (String) cbRemoteDevice.getSelectedItem();
        if (selectedDevice == null || selectedDevice.equals(currentMessages.getString("MESSAGE_VIEW_ALL_DEVICES"))) {
            JOptionPane.showMessageDialog(this,
                    currentMessages.getString("MESSAGE_VIEW_SELECT_DEVICE"),
                    currentMessages.getString("WARNING"),
            JOptionPane.showMessageDialog(this,
                    currentMessages.getString("MESSAGE_VIEW_SELECT_DEVICE"),
                    currentMessages.getString("WARNING"),
                    JOptionPane.WARNING_MESSAGE);
            return;
        }
        // 获取本地端口
        Integer localPort = remoteDeviceLocalPortMap.get(selectedDevice);
        if (localPort == null) {
            JOptionPane.showMessageDialog(this,
            JOptionPane.showMessageDialog(this,
                    "无法确定设备的接收端口",
                    currentMessages.getString("ERROR"),
                    currentMessages.getString("ERROR"),
                    JOptionPane.ERROR_MESSAGE);
            return;
        }
        // 解析IP和端口
        String[] parts = selectedDevice.split(":");
        if (parts.length != 2) {
            JOptionPane.showMessageDialog(this,
                    currentMessages.getString("MESSAGE_VIEW_INVALID_DEVICE"),
                    currentMessages.getString("ERROR"),
            JOptionPane.showMessageDialog(this,
                    currentMessages.getString("MESSAGE_VIEW_INVALID_DEVICE"),
                    currentMessages.getString("ERROR"),
                    JOptionPane.ERROR_MESSAGE);
            return;
        }
@@ -412,28 +355,26 @@
        try {
            port = Integer.parseInt(parts[1]);
        } catch (NumberFormatException ex) {
            JOptionPane.showMessageDialog(this,
                    currentMessages.getString("MESSAGE_VIEW_INVALID_PORT"),
                    currentMessages.getString("ERROR"),
            JOptionPane.showMessageDialog(this,
                    currentMessages.getString("MESSAGE_VIEW_INVALID_PORT"),
                    currentMessages.getString("ERROR"),
                    JOptionPane.ERROR_MESSAGE);
            return;
        }
        String dataToSend = txtSendData.getText();
        if (dataToSend.isEmpty()) {
            JOptionPane.showMessageDialog(this,
                    currentMessages.getString("MESSAGE_VIEW_EMPTY_DATA"),
                    currentMessages.getString("WARNING"),
            JOptionPane.showMessageDialog(this,
                    currentMessages.getString("MESSAGE_VIEW_EMPTY_DATA"),
                    currentMessages.getString("WARNING"),
                    JOptionPane.WARNING_MESSAGE);
            return;
        }
        // 添加回车换行
        if (chkAppendNewline.isSelected()) {
            dataToSend += "\r\n";
        }
        // 记录发送数据到界面
        SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
        String timestamp = sdf.format(new Date());
@@ -441,21 +382,15 @@
        displayData.append("[SEND][").append(timestamp).append("][").append(ip).append(":").append(port).append("] ");
        if (rdoSendHex.isSelected()) {
            // HEX格式发送
            String hexData = toHexString(dataToSend);
            displayData.append(hexData);
            if (localPort == UDPPortAReceiver.PORT) {
                // 传入是否HEX发送的标志
                UDPPortAReceiver.sendData(ip, port, dataToSend, true);
            } else if (localPort == UDPPortBReceiver.PORT) {
                // 传入是否HEX发送的标志
                UDPPortBReceiver.sendData(ip, port, dataToSend, true);
            }
        } else {
            // ASCII格式发送
            displayData.append(dataToSend);
            // 实际发送ASCII数据(这里需要调用UDP发送方法)
            if (localPort == UDPPortAReceiver.PORT) {
                UDPPortAReceiver.sendData(ip, port, dataToSend, false);
            } else if (localPort == UDPPortBReceiver.PORT) {
@@ -463,22 +398,17 @@
            }
        }
        // 在EDT线程中更新UI
        SwingUtilities.invokeLater(() -> {
            txtDataView.append(displayData.toString() + "\n");
            // 自动滚动到底部
            txtDataView.setCaretPosition(txtDataView.getDocument().getLength());
        });
    }
    // 修改添加远程设备方法
    // 在MessageViewPanel类中修改addRemoteDevice方法
    public static void addRemoteDevice(String ip, int port, int localPort) {
        String device = ip + ":" + port;
        if (!remoteDeviceLocalPortMap.containsKey(device)) {
            remoteDeviceLocalPortMap.put(device, localPort);
            SwingUtilities.invokeLater(() -> {
                // 检查下拉框中是否已存在该设备
                boolean exists = false;
                ComboBoxModel<String> model = cbRemoteDevice.getModel();
                for (int i = 0; i < model.getSize(); i++) {
@@ -495,120 +425,56 @@
        }
    }
    // 捕获数据的核心方法
    // 修改通用数据显示方法
    public static void showData(String rawData, String ip, int port, int localPort, String deviceId) {
        if (!isWindowVisible) {
    public static void showData(String rawData, String ip, int port, int localPort,
                               String DataType, String Protocol, String Id) {
        // 双重检查:窗口可见且已点击开始按钮
        if (!isWindowVisible || !isStarted) {
            return;
        }
        // 获取当前选择
        if (cbDataType == null || cbProtocol == null || cbDeviceId == null) {
            return;
        }
        String selectedDataType = (String) cbDataType.getSelectedItem();
        String selectedProtocol = (String) cbProtocol.getSelectedItem();
        String selectedDeviceId = (String) cbDeviceId.getSelectedItem();
        // 使用新方法获取当前资源包
        ResourceBundle messages = Languages.getCurrentMessages();
        boolean DataTypeboolean = "ALL".equals(selectedDataType) || selectedDataType.equals(DataType);
        boolean Protocolboolean = "ALL".equals(selectedProtocol) || selectedProtocol.equals(Protocol);
        boolean DeviceIdboolean = "ALL".equals(selectedDeviceId) || selectedDeviceId.equals(Id);
        
        String allTypes = messages.getString("MESSAGE_VIEW_ALL_TYPES");
        String allProtocols = messages.getString("MESSAGE_VIEW_ALL_PROTOCOLS");
        String allDevices = messages.getString("MESSAGE_VIEW_ALL_DEVICES");
        String udpPortA = messages.getString("MESSAGE_VIEW_UDP_PORT_A");
        String udpPortB = messages.getString("MESSAGE_VIEW_UDP_PORT_B");
        String udpProtocol = "UDP"; // 直接使用协议名称
        if (DataTypeboolean && Protocolboolean && DeviceIdboolean) {
            StringBuilder sb = SB.get();
            sb.setLength(0);
        // 检查数据类型过滤
        boolean dataTypeMatch = selectedDataType.equals(allTypes) ||
                (localPort == UDPPortAReceiver.PORT && selectedDataType.equals(udpPortA)) ||
                (localPort == UDPPortBReceiver.PORT && selectedDataType.equals(udpPortB));
            if (chkShowSource.isSelected()) {
                sb.append(PREFIX);
                formatTime(sb);
                sb.append(',').append(ip).append(COLON).append(port).append(SUFFIX);
            }
            sb.append(rawData);
        // 检查协议过滤
        boolean protocolMatch = selectedProtocol.equals(allProtocols) ||
                (localPort == UDPPortAReceiver.PORT && selectedProtocol.equals(udpProtocol)) ||
                (localPort == UDPPortBReceiver.PORT && selectedProtocol.equals(udpProtocol));
        // 检查设备ID过滤
        boolean deviceIdMatch=false;
        if("1".equals(deviceId)) {
            deviceIdMatch=true;
        }else {
            deviceIdMatch = selectedDeviceId.equals(allDevices) ||
                    (deviceId != null && deviceId.equals(selectedDeviceId));
        }
        // 只有当所有条件都匹配时才显示
        if (!(dataTypeMatch && protocolMatch && deviceIdMatch)) {
            return;
        }
        // 生成毫秒级时间戳
        SimpleDateFormat sdf = new SimpleDateFormat("HH:mm:ss.SSS");
        String timestamp = sdf.format(new Date());
        String formattedData = formatData(rawData, ip, port, timestamp);
        if (isCapturing) {
            // 添加远程设备到下拉框
            addRemoteDevice(ip, port, localPort);
            // 在EDT线程中更新UI
            final String finalText = sb.toString();
            SwingUtilities.invokeLater(() -> {
                txtDataView.append(formattedData + "\n");
                txtDataView.append(finalText);
                txtDataView.append("\n");
                txtDataView.setCaretPosition(txtDataView.getDocument().getLength());
            });
        }
        // 如果启用了自动保存,则保存到文件
        if (chkAutoSave.isSelected()) {
            saveToFile(formattedData);
            if (isCapturing && localPort != 0) {
                addRemoteDevice(ip, port, localPort);
            }
            if (chkAutoSave.isSelected()) {
                saveToFile(finalText);
            }
        }
    }
    // 格式化数据显示
    // 修改格式显示方法,支持混合格式
    private static String formatData(String rawData, String ip, int port, String timestamp) {
        StringBuilder formatted = new StringBuilder();
        // 使用新方法获取当前资源包
        ResourceBundle messages = Languages.getCurrentMessages();
        // 显示来源信息
        if (chkShowSource.isSelected()) {
            formatted.append("[")
            .append(timestamp)
            .append("][")
            .append(ip)
            .append(":")
            .append(port)
            .append("] ");
        }
        // 根据显示选项格式化数据
        if (chkHexDisplay.isSelected() && chkAsciiDisplay.isSelected()) {
            formatted.append(formatHexString(rawData))
            .append(" | ")
            .append(hexToAscii(rawData))
            .append(" [")
            .append(messages.getString("MESSAGE_VIEW_MIXED_FORMAT"))
            .append("]");
        } else if (chkHexDisplay.isSelected()) {
            formatted.append(formatHexString(rawData))
            .append(" [")
            .append(messages.getString("MESSAGE_VIEW_HEX_FORMAT"))
            .append("]");
        } else if (chkAsciiDisplay.isSelected()) {
            formatted.append(hexToAscii(rawData))
            .append(" [")
            .append(messages.getString("MESSAGE_VIEW_ASCII_FORMAT"))
            .append("]");
        } else {
            formatted.append(hexToAscii(rawData));
        }
        return formatted.toString();
    }
    // 修改设备ID加载方法
    private void loadDeviceIds() {
        cbDeviceId.removeAllItems();
        cbDeviceId.addItem(messages.getString("MESSAGE_VIEW_ALL_DEVICES"));
        cbDeviceId.addItem("ALL");
        List<String> tags = Dell_tag.getAlldeviceIds();
        for (String tag : tags) {
@@ -616,42 +482,54 @@
        }
    }
    // 将字符串转换为十六进制表示
    private static String toHexString(String input) {
        StringBuilder hex = new StringBuilder(); // 使用StringBuilder构建十六进制字符串
        for (char c : input.toCharArray()) { // 遍历每个字符
            hex.append(String.format("%02X ", (int) c)); // 格式化为两位十六进制
        StringBuilder hex = new StringBuilder();
        for (char c : input.toCharArray()) {
            hex.append(String.format("%02X ", (int) c));
        }
        return hex.toString().trim(); // 返回并去除末尾空格
    }
    // 格式化十六进制字符串(每两个字符加空格)
    private static String formatHexString(String hex) {
        StringBuilder formatted = new StringBuilder();
        for (int i = 0; i < hex.length(); i += 2) {
            if (i > 0) formatted.append(" ");
            formatted.append(hex.substring(i, Math.min(i + 2, hex.length())));
        }
        return formatted.toString();
        return hex.toString().trim();
    }
    // 将十六进制字符串转换为ASCII
    private static String hexToAscii(String hexStr) {
        StringBuilder output = new StringBuilder();
        for (int i = 0; i < hexStr.length(); i += 2) {
            String str = hexStr.substring(i, i + 2);
            output.append((char) Integer.parseInt(str, 16));
        }
        return output.toString();
    }
    // 保存数据到文件
    private static void saveToFile(String data) {
        SimpleDateFormat fileFormat = new SimpleDateFormat("yyyyMMdd"); // 文件日期格式
        String fileName = "systemfile/baowen/messages_" + fileFormat.format(new Date()) + ".txt"; // 文件名包含日期
        SimpleDateFormat fileFormat = new SimpleDateFormat("yyyyMMdd");
        String fileName = "systemfile/baowen/messages_" + fileFormat.format(new Date()) + ".txt";
        try (java.io.FileWriter writer = new java.io.FileWriter(fileName, true)) { // 使用追加模式
            writer.write(data + "\n"); // 写入数据并换行
        try (java.io.FileWriter writer = new java.io.FileWriter(fileName, true)) {
            writer.write(data + "\n");
        } catch (java.io.IOException ex) {
            ex.printStackTrace(); // 打印IO异常
            ex.printStackTrace();
        }
    }
    public static String getSelectedDataType() {
        return cbDataType == null ? "" : String.valueOf(cbDataType.getSelectedItem());
    }
    public static String getSelectedProtocol() {
        return cbProtocol == null ? "" : String.valueOf(cbProtocol.getSelectedItem());
    }
    public static String getSelectedDeviceId() {
        return cbDeviceId == null ? "" : String.valueOf(cbDeviceId.getSelectedItem());
    }
    private static void formatTime(StringBuilder sb) {
        long now = System.currentTimeMillis();
        long sec  = (now / 1000) % 86400;
        int  ms   = (int) (now % 1000);
        int h = (int) (sec / 3600);
        int m = (int) ((sec % 3600) / 60);
        int s = (int) (sec % 60);
        sb.append((char) ('0' + (h / 10)))
          .append((char) ('0' + (h % 10))).append(':');
        sb.append((char) ('0' + (m / 10)))
          .append((char) ('0' + (m % 10))).append(':');
        sb.append((char) ('0' + (s / 10)))
          .append((char) ('0' + (s % 10))).append('.');
        sb.append(DIGITS[ms / 100])
          .append(DIGITS[(ms / 10) % 10])
          .append(DIGITS[ms % 10]);
    }
}