package dikuai; import javax.swing.*; import java.awt.*; import java.awt.event.ActionEvent; import java.awt.event.ActionListener; import java.io.FileInputStream; import java.util.Properties; import zhuye.MowerLocationData; import zhuye.buttonset; import java.text.DecimalFormat; import java.awt.GridBagLayout; import java.awt.GridBagConstraints; import java.awt.Insets; /** * 返回点设置对话框 - 将当前车辆位置设置为地块返回点 */ public class FanhuiDialog extends JDialog { private static final long serialVersionUID = 1L; private Dikuai dikuai; private boolean updated = false; public FanhuiDialog(Window parent, Dikuai dikuai) { super(parent instanceof Frame ? (Frame) parent : null, "设置返回点", ModalityType.APPLICATION_MODAL); this.dikuai = dikuai; initialize(); } private void initialize() { // 适配 6.5 寸竖屏,宽窄高布局 setSize(360, 640); setResizable(false); setLocationRelativeTo(getOwner()); setDefaultCloseOperation(DISPOSE_ON_CLOSE); // 主面板 JPanel panel = new JPanel(new GridBagLayout()); panel.setBorder(BorderFactory.createEmptyBorder(15, 15, 15, 15)); panel.setBackground(new Color(248, 248, 248)); GridBagConstraints c = new GridBagConstraints(); c.insets = new Insets(8, 10, 8, 10); c.anchor = GridBagConstraints.NORTHWEST; c.fill = GridBagConstraints.HORIZONTAL; c.weightx = 1.0; // 标题 JLabel title = new JLabel("设置返回点"); title.setFont(new Font("Microsoft YaHei", Font.BOLD, 18)); title.setForeground(new Color(0, 100, 200)); c.gridx = 0; c.gridy = 0; c.gridwidth = 2; c.weighty = 0; panel.add(title, c); // 提示信息 JLabel hintLabel = new JLabel("
返回点坐标为割草机完成任务后返回的位置。
"); hintLabel.setFont(new Font("Microsoft YaHei", Font.PLAIN, 13)); hintLabel.setForeground(new Color(100, 100, 100)); hintLabel.setBorder(BorderFactory.createEmptyBorder(5, 0, 5, 0)); c.gridx = 0; c.gridy = 1; c.gridwidth = 2; c.insets = new Insets(5, 10, 15, 10); panel.add(hintLabel, c); // 分隔线 JSeparator separator = new JSeparator(); c.gridx = 0; c.gridy = 2; c.gridwidth = 2; c.insets = new Insets(5, 0, 15, 0); panel.add(separator, c); // 检测到的坐标 c.insets = new Insets(12, 10, 12, 10); final String[] detectedHolder = new String[1]; try { detectedHolder[0] = getCurrentVehicleCoordinates(); } catch (Throwable ignored) { detectedHolder[0] = null; } JLabel detectedLabel = new JLabel("检测到坐标:"); detectedLabel.setFont(new Font("Microsoft YaHei", Font.BOLD, 14)); detectedLabel.setForeground(Color.DARK_GRAY); c.gridx = 0; c.gridy = 3; c.gridwidth = 2; c.weighty = 0; panel.add(detectedLabel, c); // 坐标显示区域 JTextArea coordArea = new JTextArea(detectedHolder[0] == null ? "未检测到车辆坐标" : detectedHolder[0]); coordArea.setFont(new Font("Microsoft YaHei", Font.PLAIN, 14)); coordArea.setForeground(detectedHolder[0] == null ? Color.GRAY : new Color(0, 120, 0)); coordArea.setEditable(false); coordArea.setBackground(new Color(255, 255, 255)); coordArea.setBorder(BorderFactory.createCompoundBorder( BorderFactory.createLineBorder(new Color(220, 220, 220)), BorderFactory.createEmptyBorder(8, 8, 8, 8) )); coordArea.setLineWrap(true); coordArea.setWrapStyleWord(true); c.gridx = 0; c.gridy = 4; c.gridwidth = 2; c.ipady = 50; c.weighty = 0; panel.add(coordArea, c); c.ipady = 0; // 添加一个弹性空间,将按钮推到底部 c.gridx = 0; c.gridy = 5; c.gridwidth = 2; c.weighty = 1.0; c.fill = GridBagConstraints.BOTH; panel.add(Box.createGlue(), c); // 按钮面板 JPanel btnPanel = new JPanel(new FlowLayout(FlowLayout.RIGHT, 10, 0)); btnPanel.setBackground(new Color(248, 248, 248)); btnPanel.setBorder(BorderFactory.createEmptyBorder(10, 0, 0, 0)); JButton cancelBtn = buttonset.createStyledButton("取消", new Color(250, 250, 250)); cancelBtn.setFont(new Font("Microsoft YaHei", Font.PLAIN, 14)); cancelBtn.setForeground(new Color(80, 80, 80)); cancelBtn.setBorder(BorderFactory.createCompoundBorder( BorderFactory.createLineBorder(new Color(200, 200, 200)), BorderFactory.createEmptyBorder(5, 15, 5, 15) )); cancelBtn.setCursor(new Cursor(Cursor.HAND_CURSOR)); JButton okBtn = buttonset.createStyledButton("确定", new Color(70, 130, 220)); okBtn.setFont(new Font("Microsoft YaHei", Font.BOLD, 14)); okBtn.setBorder(BorderFactory.createCompoundBorder( BorderFactory.createLineBorder(new Color(60, 120, 210)), BorderFactory.createEmptyBorder(5, 15, 5, 15) )); okBtn.setCursor(new Cursor(Cursor.HAND_CURSOR)); // 添加按钮悬停效果 cancelBtn.addMouseListener(new java.awt.event.MouseAdapter() { public void mouseEntered(java.awt.event.MouseEvent evt) { cancelBtn.setBackground(new Color(240, 240, 240)); } public void mouseExited(java.awt.event.MouseEvent evt) { cancelBtn.setBackground(new Color(250, 250, 250)); } }); okBtn.addMouseListener(new java.awt.event.MouseAdapter() { public void mouseEntered(java.awt.event.MouseEvent evt) { okBtn.setBackground(new Color(80, 140, 230)); } public void mouseExited(java.awt.event.MouseEvent evt) { okBtn.setBackground(new Color(70, 130, 220)); } }); btnPanel.add(cancelBtn); btnPanel.add(okBtn); c.gridx = 0; c.gridy = 6; c.gridwidth = 2; c.anchor = GridBagConstraints.NORTHEAST; c.insets = new Insets(10, 10, 0, 10); c.weighty = 0; c.fill = GridBagConstraints.HORIZONTAL; panel.add(btnPanel, c); // 按钮事件 okBtn.addActionListener(new ActionListener() { @Override public void actionPerformed(ActionEvent e) { // 仅使用检测到的实时坐标 if (detectedHolder[0] == null) { JOptionPane.showMessageDialog(FanhuiDialog.this, "未能获取到当前车辆坐标,无法设置返回点", "错误", JOptionPane.ERROR_MESSAGE); return; } String normalized = normalizeCoordinates(detectedHolder[0]); if (normalized == null) { JOptionPane.showMessageDialog(FanhuiDialog.this, "检测到的坐标格式异常,无法保存", "错误", JOptionPane.ERROR_MESSAGE); return; } Dikuai.updateField(dikuai.getLandNumber(), "returnPointCoordinates", normalized); Dikuai.updateField(dikuai.getLandNumber(), "updateTime", new java.text.SimpleDateFormat("yyyy-MM-dd HH:mm:ss").format(new java.util.Date())); Dikuai.saveToProperties(); JOptionPane.showMessageDialog(FanhuiDialog.this, "返回点坐标已更新!", "成功", JOptionPane.INFORMATION_MESSAGE); updated = true; dispose(); } }); // 取消按钮立即退出对话框 cancelBtn.addActionListener(e -> { dispose(); }); setContentPane(panel); setVisible(true); } /** * 尝试读取当前车辆位置的简易实现 */ private String getCurrentVehicleCoordinates() { // 1) 优先尝试从内存中的 MowerLocationData 获取实时位置 try { double latDm = MowerLocationData.getLatitude(); double lonDm = MowerLocationData.getLongitude(); String latHem = MowerLocationData.getLatitudeHemisphere(); String lonHem = MowerLocationData.getLongitudeHemisphere(); if ((latDm != 0.0 || lonDm != 0.0)) { double lat = dmToDecimal(latDm); double lon = dmToDecimal(lonDm); if (latHem != null && latHem.equalsIgnoreCase("S")) lat = -Math.abs(lat); if (lonHem != null && lonHem.equalsIgnoreCase("W")) lon = -Math.abs(lon); DecimalFormat df = new DecimalFormat("0.######"); return df.format(lat) + "," + df.format(lon); } } catch (Throwable ignored) {} // 2) 尝试从配置文件获取 try (FileInputStream fis = new FileInputStream("current_position.properties")) { Properties p = new Properties(); p.load(fis); String v = p.getProperty("currentPosition"); if (v != null && !v.trim().isEmpty()) return v.trim(); String lat = p.getProperty("latitude"); String lon = p.getProperty("longitude"); if (lat != null && lon != null) return lat.trim() + "," + lon.trim(); } catch (Exception ignored) {} try (FileInputStream fis = new FileInputStream("device.properties")) { Properties dp = new Properties(); dp.load(new java.io.InputStreamReader(fis, java.nio.charset.StandardCharsets.UTF_8)); String coords = dp.getProperty("mowerCoordinates"); if (coords != null && !coords.trim().isEmpty()) return coords.trim(); coords = dp.getProperty("mowerPosition"); if (coords != null && !coords.trim().isEmpty()) return coords.trim(); } catch (Exception ignored) {} return null; } public boolean isUpdated() { return updated; } /** * 将度分格式转换为十进制度 */ private static double dmToDecimal(double dm) { double sign = dm < 0 ? -1.0 : 1.0; double abs = Math.abs(dm); int degrees = (int) (abs / 100); double minutes = abs - (degrees * 100); return sign * (degrees + minutes / 60.0); } /** * 规范化坐标字符串 */ private String normalizeCoordinates(String input) { if (input == null) return null; String s = input.trim(); if (s.isEmpty()) return null; String[] parts = s.split("\\s*,\\s*"); if (parts.length != 2) return null; try { double lat = Double.parseDouble(parts[0]); double lon = Double.parseDouble(parts[1]); // 如果看起来像十进制度,直接格式化返回 if (Math.abs(lat) <= 90.0 && Math.abs(lon) <= 180.0) { DecimalFormat df = new DecimalFormat("0.######"); return df.format(lat) + "," + df.format(lon); } // 否则尝试按度分格式转换 double latDec = dmToDecimal(lat); double lonDec = dmToDecimal(lon); DecimalFormat df = new DecimalFormat("0.######"); return df.format(latDec) + "," + df.format(lonDec); } catch (NumberFormatException ex) { return null; } } }