zsh_root
2025-12-10 8d662de2fd262b3a485f16e197cb4d0ca2a61cdf
src/home/QuickCalculationPanel.java
@@ -21,7 +21,7 @@
    private JTextField result1TextField;
    private JTextField result2TextField;
    // 构造函数
    // 构造函数
    public QuickCalculationPanel(ResourceBundle messages) {
        this.messages = messages;
        setLayout(new BorderLayout());
@@ -30,14 +30,14 @@
        initUI();
    }
    // 初始化用户界面
    // 初始化用户界面
    private void initUI() {
        JPanel mainPanel = new JPanel();
        mainPanel.setLayout(new BoxLayout(mainPanel, BoxLayout.Y_AXIS));
        mainPanel.setBorder(BorderFactory.createEmptyBorder(10, 10, 10, 10));
        mainPanel.setBackground(Color.WHITE);
        
        // 创建带标题边框的面板
        // 创建带标题边框的面板
        mainPanel.add(createPointInputPanel());
        mainPanel.add(Box.createVerticalStrut(10));
        mainPanel.add(createCoordinateConversionPanel());
@@ -52,121 +52,121 @@
    }
    /**
     * 创建点输入面板
     * 创建点输入面板
     */
    private JPanel createPointInputPanel() {
        JPanel panel = createTitledPanel(getMessage("POINT_INPUT_SECTION", "点输入区域"));
        JPanel panel = createTitledPanel(getMessage("POINT_INPUT_SECTION", "点输入区域"));
        panel.setLayout(new GridBagLayout());
        GridBagConstraints gbc = new GridBagConstraints();
        gbc.fill = GridBagConstraints.HORIZONTAL;
        gbc.insets = new Insets(5, 5, 5, 5); // 设置组件间距为5像素
        gbc.insets = new Insets(5, 5, 5, 5); // 设置组件间距为5像素
        
        // 点A输入
        // 点A输入
        gbc.gridx = 0;
        gbc.gridy = 0;
        gbc.weightx = 0;
        JLabel pointALabel = new JLabel(getMessage("POINT_A", "点A") + ":");
        JLabel pointALabel = new JLabel(getMessage("POINT_A", "点A") + ":");
        panel.add(pointALabel, gbc);
        
        gbc.gridx = 1;
        gbc.weightx = 1.0;
        pointATextField = new JTextField();
        pointATextField.setPreferredSize(new Dimension(200, 25)); // 设置文本框长度为300像素
        pointATextField.setToolTipText(getMessage("POINT_A1", "格式: 经度,纬度,本地X,本地Y"));
        pointATextField.setPreferredSize(new Dimension(200, 25)); // 设置文本框长度为300像素
        pointATextField.setToolTipText(getMessage("POINT_A1", "格式: 经度,纬度,本地X,本地Y"));
        panel.add(pointATextField, gbc);
        
        // 点B输入
        // 点B输入
        gbc.gridx = 0;
        gbc.gridy = 1;
        gbc.weightx = 0;
        JLabel pointBLabel = new JLabel(getMessage("POINT_B", "点B") + ":");
        JLabel pointBLabel = new JLabel(getMessage("POINT_B", "点B") + ":");
        panel.add(pointBLabel, gbc);
        
        gbc.gridx = 1;
        gbc.weightx = 1.0;
        pointBTextField = new JTextField();
        pointBTextField.setPreferredSize(new Dimension(200, 25)); // 设置文本框长度为300像素
        pointBTextField.setToolTipText(getMessage("POINT_B1", "格式: 经度,纬度,本地X,本地Y"));
        pointBTextField.setPreferredSize(new Dimension(200, 25)); // 设置文本框长度为300像素
        pointBTextField.setToolTipText(getMessage("POINT_B1", "格式: 经度,纬度,本地X,本地Y"));
        panel.add(pointBTextField, gbc);
        
        return panel;
    }
    /**
     * 创建坐标转换面板
     * 创建坐标转换面板
     */
    private JPanel createCoordinateConversionPanel() {
        JPanel panel = createTitledPanel(getMessage("COORDINATE_CONVERSION", "坐标转换"));
        JPanel panel = createTitledPanel(getMessage("COORDINATE_CONVERSION", "坐标转换"));
        panel.setLayout(new GridBagLayout());
        GridBagConstraints gbc = new GridBagConstraints();
        gbc.fill = GridBagConstraints.HORIZONTAL;
        gbc.insets = new Insets(5, 5, 5, 5); // 设置组件间距为5像素
        gbc.insets = new Insets(5, 5, 5, 5); // 设置组件间距为5像素
        
        // XY转经纬度
        // XY转经纬度
        gbc.gridx = 0;
        gbc.gridy = 0;
        gbc.weightx = 0;
        JLabel xyToLonLatLabel = new JLabel(getMessage("XY_TO_LONLAT", "XY转经纬度") + ":");
        JLabel xyToLonLatLabel = new JLabel(getMessage("XY_TO_LONLAT", "XY转经纬度") + ":");
        panel.add(xyToLonLatLabel, gbc);
        
        gbc.gridx = 1;
        gbc.weightx = 1.0;
        xyToLonLatTextField = new JTextField();
        xyToLonLatTextField.setPreferredSize(new Dimension(200, 25)); // 设置文本框长度为300像素
        xyToLonLatTextField.setToolTipText(getMessage("XY_TO_LONLAT1", "输入X,Y坐标"));
        xyToLonLatTextField.setPreferredSize(new Dimension(200, 25)); // 设置文本框长度为300像素
        xyToLonLatTextField.setToolTipText(getMessage("XY_TO_LONLAT1", "输入X,Y坐标"));
        panel.add(xyToLonLatTextField, gbc);
        
        gbc.gridx = 2;
        gbc.weightx = 0;
        JButton convertXYButton = createStyledButton(getMessage("CONVERT", "转换"));
        JButton convertXYButton = createStyledButton(getMessage("CONVERT", "转换"));
        convertXYButton.addActionListener(e -> convertXYToLonLat());
        panel.add(convertXYButton, gbc);
        
        // 转换结果1
        // 转换结果1
        gbc.gridx = 0;
        gbc.gridy = 1;
        gbc.weightx = 0;
        JLabel result1Label = new JLabel(getMessage("RESULT", "结果") + ":");
        JLabel result1Label = new JLabel(getMessage("RESULT", "结果") + ":");
        panel.add(result1Label, gbc);
        
        gbc.gridx = 1;
        gbc.weightx = 1.0;
        result1TextField = new JTextField();
        result1TextField.setPreferredSize(new Dimension(200, 25)); // 设置文本框长度为300像素
        result1TextField.setPreferredSize(new Dimension(200, 25)); // 设置文本框长度为300像素
        result1TextField.setEditable(false);
        panel.add(result1TextField, gbc);
        
        // 经纬度转XY
        // 经纬度转XY
        gbc.gridx = 0;
        gbc.gridy = 2;
        gbc.weightx = 0;
        JLabel lonLatToXYLabel = new JLabel(getMessage("LONLAT_TO_XY", "经纬度转XY") + ":");
        JLabel lonLatToXYLabel = new JLabel(getMessage("LONLAT_TO_XY", "经纬度转XY") + ":");
        panel.add(lonLatToXYLabel, gbc);
        
        gbc.gridx = 1;
        gbc.weightx = 1.0;
        lonLatToXYTextField = new JTextField();
        lonLatToXYTextField.setPreferredSize(new Dimension(200, 25)); // 设置文本框长度为300像素
        lonLatToXYTextField.setToolTipText(getMessage("LONLAT_TO_XY1", "输入经度,纬度"));
        lonLatToXYTextField.setPreferredSize(new Dimension(200, 25)); // 设置文本框长度为300像素
        lonLatToXYTextField.setToolTipText(getMessage("LONLAT_TO_XY1", "输入经度,纬度"));
        panel.add(lonLatToXYTextField, gbc);
        
        gbc.gridx = 2;
        gbc.weightx = 0;
        JButton convertLonLatButton = createStyledButton(getMessage("CONVERT", "转换"));
        JButton convertLonLatButton = createStyledButton(getMessage("CONVERT", "转换"));
        convertLonLatButton.addActionListener(e -> convertLonLatToXY());
        panel.add(convertLonLatButton, gbc);
        
        // 转换结果2
        // 转换结果2
        gbc.gridx = 0;
        gbc.gridy = 3;
        gbc.weightx = 0;
        JLabel result2Label = new JLabel(getMessage("RESULT", "结果") + ":");
        JLabel result2Label = new JLabel(getMessage("RESULT", "结果") + ":");
        panel.add(result2Label, gbc);
        
        gbc.gridx = 1;
        gbc.weightx = 1.0;
        result2TextField = new JTextField();
        result2TextField.setPreferredSize(new Dimension(200, 25)); // 设置文本框长度为300像素
        result2TextField.setPreferredSize(new Dimension(200, 25)); // 设置文本框长度为300像素
        result2TextField.setEditable(false);
        panel.add(result2TextField, gbc);
        
@@ -174,53 +174,53 @@
    }
    /**
     * 创建距离计算面板
     * 创建距离计算面板
     */
    private JPanel createDistanceCalculationPanel() {
        JPanel panel = createTitledPanel(getMessage("DISTANCE_CALCULATION", "距离计算"));
        JPanel panel = createTitledPanel(getMessage("DISTANCE_CALCULATION", "距离计算"));
        panel.setLayout(new GridBagLayout());
        GridBagConstraints gbc = new GridBagConstraints();
        gbc.fill = GridBagConstraints.HORIZONTAL;
        gbc.insets = new Insets(5, 5, 5, 5); // 设置组件间距为5像素
        gbc.insets = new Insets(5, 5, 5, 5); // 设置组件间距为5像素
        
        // 原始点1输入
        // 原始点1输入
        gbc.gridx = 0;
        gbc.gridy = 0;
        gbc.weightx = 0;
        JLabel point1Label = new JLabel(getMessage("POINT1_RAW", "原始点1") + ":");
        JLabel point1Label = new JLabel(getMessage("POINT1_RAW", "原始点1") + ":");
        panel.add(point1Label, gbc);
        
        gbc.gridx = 1;
        gbc.weightx = 1.0;
        point1RawTextField = new JTextField();
        point1RawTextField.setPreferredSize(new Dimension(200, 25)); // 设置文本框长度为300像素
        point1RawTextField.setPreferredSize(new Dimension(200, 25)); // 设置文本框长度为300像素
        panel.add(point1RawTextField, gbc);
        
        // 原始点2输入
        // 原始点2输入
        gbc.gridx = 0;
        gbc.gridy = 1;
        gbc.weightx = 0;
        JLabel point2Label = new JLabel(getMessage("POINT2_RAW", "原始点2") + ":");
        JLabel point2Label = new JLabel(getMessage("POINT2_RAW", "原始点2") + ":");
        panel.add(point2Label, gbc);
        
        gbc.gridx = 1;
        gbc.weightx = 1.0;
        point2RawTextField = new JTextField();
        point2RawTextField.setPreferredSize(new Dimension(200, 25)); // 设置文本框长度为300像素
        point2RawTextField.setPreferredSize(new Dimension(200, 25)); // 设置文本框长度为300像素
        panel.add(point2RawTextField, gbc);
        
        // 计算按钮和结果
        // 计算按钮和结果
        gbc.gridx = 0;
        gbc.gridy = 2;
        gbc.weightx = 0;
        JButton calculateButton = createStyledButton(getMessage("CALCULATE_DISTANCE", "计算距离"));
        JButton calculateButton = createStyledButton(getMessage("CALCULATE_DISTANCE", "计算距离"));
        calculateButton.addActionListener(e -> calculateDistance());
        panel.add(calculateButton, gbc);
        
        gbc.gridx = 1;
        gbc.weightx = 1.0;
        distanceResultTextField = new JTextField();
        distanceResultTextField.setPreferredSize(new Dimension(200, 25)); // 设置文本框长度为300像素
        distanceResultTextField.setPreferredSize(new Dimension(200, 25)); // 设置文本框长度为300像素
        distanceResultTextField.setEditable(false);
        panel.add(distanceResultTextField, gbc);
        
@@ -228,52 +228,52 @@
    }
    /**
     * 创建NMEA表格面板
     * 创建NMEA表格面板
     */
    private JPanel createNMEATablePanel() {
        JPanel panel = createTitledPanel(getMessage("NMEA_DATA_TABLE", "NMEA数据表"));
        JPanel panel = createTitledPanel(getMessage("NMEA_DATA_TABLE", "NMEA数据表"));
        panel.setLayout(new BorderLayout());
        
        // 创建表格列标题
        // 创建表格列标题
        String[] columns = {
            getMessage("FIELD_NAME", "字段名"),
            getMessage("POINT1", "点1"),
            getMessage("POINT2", "点2")
            getMessage("FIELD_NAME", "字段名"),
            getMessage("POINT1", "点1"),
            getMessage("POINT2", "点2")
        };
        
        // 定义表格行名称
        // 定义表格行名称
        String[] rowNames = {
            getMessage("MSG_ID", "消息ID"),
            getMessage("UTC_TIME", "UTC时间"),
            getMessage("LATITUDE", "纬度"),
            getMessage("LAT_HEMISPHERE", "纬度半球"),
            getMessage("LONGITUDE", "经度"),
            getMessage("LON_HEMISPHERE", "经度半球"),
            getMessage("QUALITY", "质量"),
            getMessage("NUM_SATELLITES", "卫星数量"),
            getMessage("MSG_ID", "消息ID"),
            getMessage("UTC_TIME", "UTC时间"),
            getMessage("LATITUDE", "纬度"),
            getMessage("LAT_HEMISPHERE", "纬度半球"),
            getMessage("LONGITUDE", "经度"),
            getMessage("LON_HEMISPHERE", "经度半球"),
            getMessage("QUALITY", "质量"),
            getMessage("NUM_SATELLITES", "卫星数量"),
            getMessage("HDOP", "HDOP"),
            getMessage("ALTITUDE", "海拔"),
            getMessage("ALTITUDE_UNIT", "海拔单位"),
            getMessage("GEOID_HEIGHT", "大地水准面高度"),
            getMessage("GEOID_HEIGHT_UNIT", "大地水准面高度单位"),
            getMessage("DIFF_TIME", "差分时间"),
            getMessage("CHECKSUM", "校验和"),
            getMessage("DEVICE_ID", "设备ID"),
            getMessage("DEVICE_POWER", "设备功率"),
            getMessage("SIGNAL_STRENGTH", "信号强度"),
            getMessage("RESERVED1", "保留1"),
            getMessage("RESERVED2", "保留2"),
            getMessage("RESERVED3", "保留3")
            getMessage("ALTITUDE", "海拔"),
            getMessage("ALTITUDE_UNIT", "海拔单位"),
            getMessage("GEOID_HEIGHT", "大地水准面高度"),
            getMessage("GEOID_HEIGHT_UNIT", "大地水准面高度单位"),
            getMessage("DIFF_TIME", "差分时间"),
            getMessage("CHECKSUM", "校验和"),
            getMessage("DEVICE_ID", "设备ID"),
            getMessage("DEVICE_POWER", "设备功率"),
            getMessage("SIGNAL_STRENGTH", "信号强度"),
            getMessage("RESERVED1", "保留1"),
            getMessage("RESERVED2", "保留2"),
            getMessage("RESERVED3", "保留3")
        };
        
        // 初始化表格模型
        // 初始化表格模型
        tableModel = new DefaultTableModel(columns, 0);
        // 添加行数据
        // 添加行数据
        for (String rowName : rowNames) {
            tableModel.addRow(new Object[]{rowName, "", ""});
        }
        
        // 创建表格并禁用编辑
        // 创建表格并禁用编辑
        nmeaTable = new JTable(tableModel);
        nmeaTable.setEnabled(false);
        nmeaTable.setRowHeight(25);
@@ -287,7 +287,7 @@
    }
    /**
     * 创建带标题边框的面板
     * 创建带标题边框的面板
     */
    private JPanel createTitledPanel(String title) {
        JPanel panel = new JPanel();
@@ -298,43 +298,43 @@
    }
    /**
     * 创建样式按钮(参考ExtensionPanel的按钮样式)
     * 创建样式按钮(参考ExtensionPanel的按钮样式)
     */
    private JButton createStyledButton(String text) {
        JButton button = new JButton(text);
        
        // 设置按钮大小为80×25(宽×高)
        // 设置按钮大小为80×25(宽×高)
        button.setPreferredSize(new Dimension(80, 25));
        button.setMinimumSize(new Dimension(80, 25));
        button.setMaximumSize(new Dimension(100, 25));
        
        // 设置按钮样式(参考ExtensionPanel)
        // 设置按钮样式(参考ExtensionPanel)
        button.setBackground(new Color(0, 120, 215));
        button.setForeground(Color.WHITE);
        button.setFocusPainted(false);
        button.setBorderPainted(false);
        button.setFont(button.getFont().deriveFont(Font.BOLD, 12f));
        
        // 添加鼠标交互效果(参考ExtensionPanel)
        // 添加鼠标交互效果(参考ExtensionPanel)
        button.addMouseListener(new java.awt.event.MouseAdapter() {
            public void mouseEntered(java.awt.event.MouseEvent evt) {
                button.setBackground(new Color(0, 150, 255)); // 悬停时变亮
                button.setBackground(new Color(0, 150, 255)); // 悬停时变亮
                button.setCursor(Cursor.getPredefinedCursor(Cursor.HAND_CURSOR));
            }
            
            public void mouseExited(java.awt.event.MouseEvent evt) {
                button.setBackground(new Color(0, 120, 215)); // 恢复正常颜色
                button.setBackground(new Color(0, 120, 215)); // 恢复正常颜色
                button.setCursor(Cursor.getDefaultCursor());
            }
            
            public void mousePressed(java.awt.event.MouseEvent evt) {
                // 点击效果 - 颜色变深并有轻微缩小效果
                // 点击效果 - 颜色变深并有轻微缩小效果
                button.setBackground(new Color(0, 80, 160));
                button.setBounds(button.getX() + 1, button.getY() + 1, 78, 23);
            }
            
            public void mouseReleased(java.awt.event.MouseEvent evt) {
                // 恢复原状
                // 恢复原状
                button.setBackground(new Color(0, 150, 255));
                button.setBounds(button.getX() - 1, button.getY() - 1, 80, 25);
            }
@@ -344,7 +344,7 @@
    }
    /**
     * 获取消息文本,如果资源束中没有则使用默认值
     * 获取消息文本,如果资源束中没有则使用默认值
     */
    private String getMessage(String key, String defaultValue) {
        try {
@@ -354,35 +354,35 @@
        }
    }
    // XY坐标转经纬度
    // XY坐标转经纬度
    private void convertXYToLonLat() {
        String xy = xyToLonLatTextField.getText().trim();
        if (xy.isEmpty()) {
            JOptionPane.showMessageDialog(this, getMessage("FIELD_REQUIRED", "此字段为必填项"),
                                         getMessage("VALIDATION_ERROR", "验证错误"), JOptionPane.ERROR_MESSAGE);
            JOptionPane.showMessageDialog(this, getMessage("FIELD_REQUIRED", "此字段为必填项"),
                                         getMessage("VALIDATION_ERROR", "验证错误"), JOptionPane.ERROR_MESSAGE);
            return;
        }
        
        // 获取A点数据
        String[] pointA = pointATextField.getText().split(",|,");
        // 获取A点数据
        String[] pointA = pointATextField.getText().split(",|,");
        if (pointA.length < 4) {
            JOptionPane.showMessageDialog(this, 
                String.format(getMessage("INVALID_POINT_FORMAT2", "点A格式无效"), getMessage("POINT_A", "点A")),
                getMessage("VALIDATION_ERROR", "验证错误"), JOptionPane.ERROR_MESSAGE);
                String.format(getMessage("INVALID_POINT_FORMAT2", "点A格式无效"), getMessage("POINT_A", "点A")),
                getMessage("VALIDATION_ERROR", "验证错误"), JOptionPane.ERROR_MESSAGE);
            return;
        }
        
        // 获取B点数据
        String[] pointB = pointBTextField.getText().split(",|,");
        // 获取B点数据
        String[] pointB = pointBTextField.getText().split(",|,");
        if (pointB.length < 4) {
            JOptionPane.showMessageDialog(this, 
                String.format(getMessage("INVALID_POINT_FORMAT3", "点B格式无效"), getMessage("POINT_B", "点B")),
                getMessage("VALIDATION_ERROR", "验证错误"), JOptionPane.ERROR_MESSAGE);
                String.format(getMessage("INVALID_POINT_FORMAT3", "点B格式无效"), getMessage("POINT_B", "点B")),
                getMessage("VALIDATION_ERROR", "验证错误"), JOptionPane.ERROR_MESSAGE);
            return;
        }
        
        try {
            // 解析输入数据
            // 解析输入数据
            double latA = Double.parseDouble(pointA[1]);
            double lonA = Double.parseDouble(pointA[0]);
            double localXA = Double.parseDouble(pointA[2]);
@@ -393,69 +393,69 @@
            double localXB = Double.parseDouble(pointB[2]);
            double localYB = Double.parseDouble(pointB[3]);
            
            // 检查经纬度是否为零
            // 检查经纬度是否为零
            if (latA == 0 || lonA == 0 || latB == 0 || lonB == 0) {
                JOptionPane.showMessageDialog(this, 
                    String.format(getMessage("ZERO_LATLON", "经纬度不能为零"), getMessage("POINT_A", "点A") + "/" + getMessage("POINT_B", "点B")),
                    getMessage("VALIDATION_ERROR", "验证错误"), JOptionPane.ERROR_MESSAGE);
                    String.format(getMessage("ZERO_LATLON", "经纬度不能为零"), getMessage("POINT_A", "点A") + "/" + getMessage("POINT_B", "点B")),
                    getMessage("VALIDATION_ERROR", "验证错误"), JOptionPane.ERROR_MESSAGE);
                return;
            }
            
            String[] xyParts = xy.split(",|,");
            String[] xyParts = xy.split(",|,");
            if (xyParts.length < 2) {
                JOptionPane.showMessageDialog(this, getMessage("XY_TO_LONLAT12", "请输入X,Y坐标"),
                                             getMessage("VALIDATION_ERROR", "验证错误"), JOptionPane.ERROR_MESSAGE);
                JOptionPane.showMessageDialog(this, getMessage("XY_TO_LONLAT12", "请输入X,Y坐标"),
                                             getMessage("VALIDATION_ERROR", "验证错误"), JOptionPane.ERROR_MESSAGE);
                return;
            }
            String localX = xyParts[0];
            String localY = xyParts[1];
            
            // 调用转换方法
            // 调用转换方法
            String[] result = XyToLatLngConverter.convertLocalToGlobalCoordinates(
                localX, localY,
                latA, lonA, latB, lonB,
                localXA, localYA, localXB, localYB
            );
            
            // 显示转换结果(十进制经纬度)
            // 显示转换结果(十进制经纬度)
            result1TextField.setText(result[3] + "," + result[2]);
            
        } catch (NumberFormatException e) {
            JOptionPane.showMessageDialog(this, getMessage("INVALID_NUMBER", "无效数字格式"),
                                         getMessage("VALIDATION_ERROR", "验证错误"), JOptionPane.ERROR_MESSAGE);
            JOptionPane.showMessageDialog(this, getMessage("INVALID_NUMBER", "无效数字格式"),
                                         getMessage("VALIDATION_ERROR", "验证错误"), JOptionPane.ERROR_MESSAGE);
        } catch (Exception e) {
            JOptionPane.showMessageDialog(this, 
                String.format(getMessage("SAVE_FENCE_ERROR", "保存围栏错误: %s"), e.getMessage()),
                getMessage("ERROR", "错误"), JOptionPane.ERROR_MESSAGE);
                String.format(getMessage("SAVE_FENCE_ERROR", "保存围栏错误: %s"), e.getMessage()),
                getMessage("ERROR", "错误"), JOptionPane.ERROR_MESSAGE);
        }
    }
    // 经纬度转XY坐标
    // 经纬度转XY坐标
    private void convertLonLatToXY() {
        String lonlat = lonLatToXYTextField.getText().trim();
        if (lonlat.isEmpty()) {
            JOptionPane.showMessageDialog(this, getMessage("FIELD_REQUIRED", "此字段为必填项"),
                                         getMessage("VALIDATION_ERROR", "验证错误"), JOptionPane.ERROR_MESSAGE);
            JOptionPane.showMessageDialog(this, getMessage("FIELD_REQUIRED", "此字段为必填项"),
                                         getMessage("VALIDATION_ERROR", "验证错误"), JOptionPane.ERROR_MESSAGE);
            return;
        }
        
        try {
            // 解析当前点的经纬度
            String[] lonLatParts = lonlat.split("[,,]");
            // 解析当前点的经纬度
            String[] lonLatParts = lonlat.split("[,,]");
            if (lonLatParts.length < 2) {
                JOptionPane.showMessageDialog(this, getMessage("INVALID_LONLAT_FORMAT", "经纬度格式无效"),
                                             getMessage("VALIDATION_ERROR", "验证错误"), JOptionPane.ERROR_MESSAGE);
                JOptionPane.showMessageDialog(this, getMessage("INVALID_LONLAT_FORMAT", "经纬度格式无效"),
                                             getMessage("VALIDATION_ERROR", "验证错误"), JOptionPane.ERROR_MESSAGE);
                return;
            }
            String jd1 = lonLatParts[0].trim();
            String wd1 = lonLatParts[1].trim();
            
            // 解析A点数据
            String[] pointA = pointATextField.getText().split("[,,]");
            // 解析A点数据
            String[] pointA = pointATextField.getText().split("[,,]");
            if (pointA.length < 4) {
                JOptionPane.showMessageDialog(this, 
                    String.format(getMessage("INVALID_POINT_FORMAT", "点格式无效"), getMessage("POINT_A", "点A")),
                    getMessage("VALIDATION_ERROR", "验证错误"), JOptionPane.ERROR_MESSAGE);
                    String.format(getMessage("INVALID_POINT_FORMAT", "点格式无效"), getMessage("POINT_A", "点A")),
                    getMessage("VALIDATION_ERROR", "验证错误"), JOptionPane.ERROR_MESSAGE);
                return;
            }
            double latA = Double.parseDouble(pointA[1].trim());
@@ -463,12 +463,12 @@
            double localXA = Double.parseDouble(pointA[2].trim());
            double localYA = Double.parseDouble(pointA[3].trim());
            
            // 解析B点数据
            String[] pointB = pointBTextField.getText().split("[,,]");
            // 解析B点数据
            String[] pointB = pointBTextField.getText().split("[,,]");
            if (pointB.length < 4) {
                JOptionPane.showMessageDialog(this, 
                    String.format(getMessage("INVALID_POINT_FORMAT", "点格式无效"), getMessage("POINT_B", "点B")),
                    getMessage("VALIDATION_ERROR", "验证错误"), JOptionPane.ERROR_MESSAGE);
                    String.format(getMessage("INVALID_POINT_FORMAT", "点格式无效"), getMessage("POINT_B", "点B")),
                    getMessage("VALIDATION_ERROR", "验证错误"), JOptionPane.ERROR_MESSAGE);
                return;
            }
            double latB = Double.parseDouble(pointB[1].trim());
@@ -476,15 +476,15 @@
            double localXB = Double.parseDouble(pointB[2].trim());
            double localYB = Double.parseDouble(pointB[3].trim());
            
            // 检查经纬度是否为零
            // 检查经纬度是否为零
            if (latA == 0 || lonA == 0 || latB == 0 || lonB == 0) {
                JOptionPane.showMessageDialog(this, 
                    String.format(getMessage("ZERO_LATLON", "经纬度不能为零"), getMessage("POINT_A", "点A") + "/" + getMessage("POINT_B", "点B")),
                    getMessage("VALIDATION_ERROR", "验证错误"), JOptionPane.ERROR_MESSAGE);
                    String.format(getMessage("ZERO_LATLON", "经纬度不能为零"), getMessage("POINT_A", "点A") + "/" + getMessage("POINT_B", "点B")),
                    getMessage("VALIDATION_ERROR", "验证错误"), JOptionPane.ERROR_MESSAGE);
                return;
            }
            
            // 调用转换方法
            // 调用转换方法
            int[] xyResult = CoordinateTranslator.gps_xy(
                new String[]{String.valueOf(lonA), String.valueOf(latA), String.valueOf(localXA), String.valueOf(localYA)},
                new String[]{String.valueOf(lonB), String.valueOf(latB), String.valueOf(localXB), String.valueOf(localYB)},
@@ -492,29 +492,29 @@
                wd1
            );
            
            // 显示转换结果 (X, Y)
            // 显示转换结果 (X, Y)
            result2TextField.setText(xyResult[1] + ", " + xyResult[0]);
            
        } catch (NumberFormatException e) {
            JOptionPane.showMessageDialog(this, getMessage("INVALID_NUMBER", "无效数字格式"),
                                         getMessage("VALIDATION_ERROR", "验证错误"), JOptionPane.ERROR_MESSAGE);
            JOptionPane.showMessageDialog(this, getMessage("INVALID_NUMBER", "无效数字格式"),
                                         getMessage("VALIDATION_ERROR", "验证错误"), JOptionPane.ERROR_MESSAGE);
        } catch (Exception e) {
            JOptionPane.showMessageDialog(this, 
                String.format(getMessage("CONVERSION_ERROR", "转换错误: %s"), e.getMessage()),
                getMessage("ERROR", "错误"), JOptionPane.ERROR_MESSAGE);
                String.format(getMessage("CONVERSION_ERROR", "转换错误: %s"), e.getMessage()),
                getMessage("ERROR", "错误"), JOptionPane.ERROR_MESSAGE);
        }
    }
    /**
     * 计算两点间距离
     * 计算两点间距离
     */
    private void calculateDistance() {
        String point1 = point1RawTextField.getText().trim();
        String point2 = point2RawTextField.getText().trim();
        
        if (point1.isEmpty() || point2.isEmpty()) {
            JOptionPane.showMessageDialog(this, getMessage("FIELD_REQUIRED", "此字段为必填项"),
                                         getMessage("VALIDATION_ERROR", "验证错误"), JOptionPane.ERROR_MESSAGE);
            JOptionPane.showMessageDialog(this, getMessage("FIELD_REQUIRED", "此字段为必填项"),
                                         getMessage("VALIDATION_ERROR", "验证错误"), JOptionPane.ERROR_MESSAGE);
            return;
        }
        
@@ -522,53 +522,53 @@
        parseNMEAData(point2, 2);
        
        try {
            // 解析NMEA数据获取经纬度
            // 解析NMEA数据获取经纬度
            String[] fields1 = point1.split(",");
            String[] fields2 = point2.split(",");
            
            // 确保有足够字段 (纬度在索引2,经度在索引4)
            // 确保有足够字段 (纬度在索引2,经度在索引4)
            if (fields1.length < 6 || fields2.length < 6) {
                JOptionPane.showMessageDialog(this, getMessage("INVALID_NMEA_FORMAT", "NMEA数据格式无效"),
                                             getMessage("VALIDATION_ERROR", "验证错误"), JOptionPane.ERROR_MESSAGE);
                JOptionPane.showMessageDialog(this, getMessage("INVALID_NMEA_FORMAT", "NMEA数据格式无效"),
                                             getMessage("VALIDATION_ERROR", "验证错误"), JOptionPane.ERROR_MESSAGE);
                return;
            }
            
            // 提取点1的经纬度
            // 提取点1的经纬度
            double lat1 = Double.parseDouble(fields1[2]);
            double lon1 = Double.parseDouble(fields1[4]);
            
            // 提取点2的经纬度
            // 提取点2的经纬度
            double lat2 = Double.parseDouble(fields2[2]);
            double lon2 = Double.parseDouble(fields2[4]);
            
            // 使用CoordinateTranslator计算距离 (厘米)
            // 使用CoordinateTranslator计算距离 (厘米)
            int distanceCm = CoordinateTranslator.distance2(lon1, lat1, lon2, lat2);
            
            // 转换为米并保留两位小数
            // 转换为米并保留两位小数
            double distanceMeters = distanceCm / 100.0;
            String formattedDistance = String.format(Locale.US, "%.2f %s", distanceMeters, getMessage("METERS", "米"));
            String formattedDistance = String.format(Locale.US, "%.2f %s", distanceMeters, getMessage("METERS", "米"));
            
            // 显示计算结果
            // 显示计算结果
            distanceResultTextField.setText(formattedDistance);
            
        } catch (NumberFormatException e) {
            JOptionPane.showMessageDialog(this, getMessage("INVALID_NUMBER", "无效数字格式"),
                                         getMessage("VALIDATION_ERROR", "验证错误"), JOptionPane.ERROR_MESSAGE);
            JOptionPane.showMessageDialog(this, getMessage("INVALID_NUMBER", "无效数字格式"),
                                         getMessage("VALIDATION_ERROR", "验证错误"), JOptionPane.ERROR_MESSAGE);
        } catch (Exception e) {
            JOptionPane.showMessageDialog(this, 
                String.format(getMessage("CALCULATION_ERROR", "计算错误: %s"), e.getMessage()),
                getMessage("ERROR", "错误"), JOptionPane.ERROR_MESSAGE);
                String.format(getMessage("CALCULATION_ERROR", "计算错误: %s"), e.getMessage()),
                getMessage("ERROR", "错误"), JOptionPane.ERROR_MESSAGE);
        }
    }
    /**
     * 解析NMEA数据到表格
     * 解析NMEA数据到表格
     */
    private void parseNMEAData(String nmea, int pointIndex) {
        String[] fields = nmea.split(",");
        int column = pointIndex;
        
        // 填充表格数据
        // 填充表格数据
        for (int i = 0; i < Math.min(fields.length, tableModel.getRowCount()); i++) {
            tableModel.setValueAt(fields[i], i, column);
        }