| | |
| | | private JTextField result1TextField; |
| | | private JTextField result2TextField; |
| | | |
| | | // 构造函数 |
| | | // 构造函数 |
| | | public QuickCalculationPanel(ResourceBundle messages) { |
| | | this.messages = messages; |
| | | setLayout(new BorderLayout()); |
| | |
| | | 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()); |
| | |
| | | } |
| | | |
| | | /** |
| | | * 创建点输入面板 |
| | | * 创建点输入面板 |
| | | */ |
| | | 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); |
| | | |
| | |
| | | } |
| | | |
| | | /** |
| | | * 创建距离计算面板 |
| | | * 创建距离计算面板 |
| | | */ |
| | | 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); |
| | | |
| | |
| | | } |
| | | |
| | | /** |
| | | * 创建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); |
| | |
| | | } |
| | | |
| | | /** |
| | | * 创建带标题边框的面板 |
| | | * 创建带标题边框的面板 |
| | | */ |
| | | private JPanel createTitledPanel(String title) { |
| | | JPanel panel = new JPanel(); |
| | |
| | | } |
| | | |
| | | /** |
| | | * 创建样式按钮(参考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); |
| | | } |
| | |
| | | } |
| | | |
| | | /** |
| | | * 获取消息文本,如果资源束中没有则使用默认值 |
| | | * 获取消息文本,如果资源束中没有则使用默认值 |
| | | */ |
| | | private String getMessage(String key, String defaultValue) { |
| | | try { |
| | |
| | | } |
| | | } |
| | | |
| | | // 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]); |
| | |
| | | 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()); |
| | |
| | | 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()); |
| | |
| | | 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)}, |
| | |
| | | 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; |
| | | } |
| | | |
| | |
| | | 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); |
| | | } |