张世豪
2025-12-04 3ad76f98fa8b4a9d3d95207cfb4ae4706087c964
src/zhuye/Shouye.java
@@ -9,6 +9,7 @@
import java.awt.*;
import java.awt.event.*;
import chuankou.dellmessage;
import dikuai.Dikuai;
import dikuai.Dikuaiguanli;
import dikuai.addzhangaiwu;
@@ -21,6 +22,8 @@
import java.util.List;
import java.util.Map;
import java.util.Locale;
import java.util.Objects;
import java.util.function.Consumer;
import java.awt.geom.Point2D;
/**
@@ -52,9 +55,11 @@
    private JButton areaSelectBtn;
    private JButton baseStationBtn;
    private JButton bluetoothBtn;
    private JLabel dataPacketCountLabel;
    private JLabel mowerSpeedValueLabel;
    private JLabel mowerSpeedUnitLabel;
    private JLabel mowingProgressLabel;
    private FixQualityIndicator fixQualityIndicator;
    
    // 导航按钮
    private JButton homeNavBtn;
@@ -75,6 +80,8 @@
    private BaseStationDialog baseStationDialog;
    private Sets settingsDialog;
    private BaseStation baseStation;
    private final Consumer<String> serialLineListener = line -> SwingUtilities.invokeLater(this::updateDataPacketCountLabel);
    
    // 地图渲染器
    private MapRenderer mapRenderer;
@@ -124,6 +131,7 @@
        instance = this;
        baseStation = new BaseStation();
        baseStation.load();
    dellmessage.registerLineListener(serialLineListener);
        initializeUI();
        setupEventHandlers();
    }
@@ -293,7 +301,7 @@
        
        mainContentPanel.add(visualizationPanel, BorderLayout.CENTER);
        startMowerSpeedUpdates();
    startMowerSpeedUpdates();
    }
    
    private void createControlPanel() {
@@ -681,14 +689,14 @@
            return;
        }
        startButtonShowingPause = !startButtonShowingPause;
        if (startButtonShowingPause) {
        if (!startButtonShowingPause) {
            statusLabel.setText("作业中");
            if (stopButtonActive) {
                stopButtonActive = false;
                updateStopButtonIcon();
            }
            if (!beginMowingSession()) {
                startButtonShowingPause = false;
                startButtonShowingPause = true;
                statusLabel.setText("待机");
                updateStartButtonAppearance();
                return;
@@ -767,10 +775,14 @@
    }
    private JPanel createSpeedIndicatorPanel() {
        JPanel panel = new JPanel(new FlowLayout(FlowLayout.RIGHT, 10, 0));
        JPanel panel = new JPanel(new BorderLayout());
        panel.setOpaque(false);
        panel.setBorder(BorderFactory.createEmptyBorder(10, 20, 5, 20));
        JPanel rightPanel = new JPanel(new FlowLayout(FlowLayout.RIGHT, 10, 0));
        rightPanel.setOpaque(false);
        fixQualityIndicator = new FixQualityIndicator();
        mowingProgressLabel = new JLabel("--%");
        mowingProgressLabel.setFont(new Font("微软雅黑", Font.BOLD, 12));
        mowingProgressLabel.setForeground(THEME_COLOR);
@@ -783,9 +795,32 @@
        mowerSpeedUnitLabel.setFont(new Font("微软雅黑", Font.BOLD, 9));
        mowerSpeedUnitLabel.setForeground(THEME_COLOR);
        panel.add(mowingProgressLabel);
        panel.add(mowerSpeedValueLabel);
        panel.add(mowerSpeedUnitLabel);
        dataPacketCountLabel = new JLabel("--");
        dataPacketCountLabel.setFont(new Font("微软雅黑", Font.BOLD, 12));
        dataPacketCountLabel.setForeground(THEME_COLOR);
        rightPanel.add(fixQualityIndicator);
        JSeparator areaSeparator = new JSeparator(SwingConstants.VERTICAL);
        areaSeparator.setPreferredSize(new Dimension(1, 16));
        rightPanel.add(areaSeparator);
        rightPanel.add(mowingProgressLabel);
    JSeparator speedSeparator = new JSeparator(SwingConstants.VERTICAL);
    speedSeparator.setPreferredSize(new Dimension(1, 16));
    rightPanel.add(speedSeparator);
        rightPanel.add(mowerSpeedValueLabel);
        rightPanel.add(mowerSpeedUnitLabel);
        JSeparator separator = new JSeparator(SwingConstants.VERTICAL);
        separator.setPreferredSize(new Dimension(1, 16));
        rightPanel.add(separator);
        rightPanel.add(dataPacketCountLabel);
        panel.add(rightPanel, BorderLayout.EAST);
        updateFixQualityIndicator();
        updateDataPacketCountLabel();
        return panel;
    }
@@ -817,6 +852,89 @@
            mowerSpeedUnitLabel.setText("km/h");
        }
        updateMowingProgressLabel();
        updateFixQualityIndicator();
        updateDataPacketCountLabel();
    }
    private void updateDataPacketCountLabel() {
        if (dataPacketCountLabel == null) {
            return;
        }
        int udpCount = UDPServer.getReceivedPacketCount();
        int serialCount = dellmessage.getProcessedLineCount();
        int displayCount = Math.max(udpCount, serialCount);
        if (displayCount <= 0) {
            dataPacketCountLabel.setText("--");
            dataPacketCountLabel.setToolTipText(null);
        } else {
            dataPacketCountLabel.setText(String.valueOf(displayCount));
            dataPacketCountLabel.setToolTipText(String.format("串口: %d  UDP: %d", serialCount, udpCount));
        }
    }
    private void updateFixQualityIndicator() {
        if (fixQualityIndicator == null) {
            return;
        }
        Device device = Device.getGecaoji();
        String code = null;
        if (device != null) {
            code = sanitizeDeviceValue(device.getPositioningStatus());
        }
        fixQualityIndicator.setQuality(code);
    }
    private Color resolveFixQualityColor(String code) {
        if (code == null) {
            return new Color(160, 160, 160);
        }
        switch (code) {
            case "0":
                return new Color(160, 160, 160);
            case "1":
                return new Color(52, 152, 219);
            case "2":
                return new Color(26, 188, 156);
            case "3":
                return new Color(155, 89, 182);
            case "4":
                return THEME_COLOR;
            case "5":
                return new Color(241, 196, 15);
            case "6":
                return new Color(231, 76, 60);
            case "7":
                return new Color(230, 126, 34);
            default:
                return new Color(95, 95, 95);
        }
    }
    private String resolveFixQualityDescription(String code) {
        if (code == null) {
            return "未知";
        }
        switch (code) {
            case "0":
                return "未定位";
            case "1":
                return "单点定位";
            case "2":
                return "码差分";
            case "3":
                return "无效PPS";
            case "4":
                return "固定解";
            case "5":
                return "浮点解";
            case "6":
                return "正在估算";
            case "7":
                return "人工输入固定值";
            default:
                return "其他";
        }
    }
    private String sanitizeSpeedValue(String raw) {
@@ -833,6 +951,17 @@
        return trimmed;
    }
    private String sanitizeDeviceValue(String raw) {
        if (raw == null) {
            return null;
        }
        String trimmed = raw.trim();
        if (trimmed.isEmpty() || "-1".equals(trimmed) || "null".equalsIgnoreCase(trimmed)) {
            return null;
        }
        return trimmed;
    }
    private void updateMowingProgressLabel() {
        if (mowingProgressLabel == null) {
            return;
@@ -1621,6 +1750,7 @@
            return;
        }
        circleGuidanceStep = step;
        if (step == 1) {
            circleGuidanceLabel.setText("采集第1个点");
            circleGuidancePrimaryButton.setText("确认第1点");
@@ -2267,6 +2397,48 @@
        return !"未选择地块".equals(trimmed);
    }
    private final class FixQualityIndicator extends JComponent {
        private static final long serialVersionUID = 1L;
        private static final int DIAMETER = 16;
        private String currentCode;
        private Color currentColor = new Color(160, 160, 160);
        private FixQualityIndicator() {
            setPreferredSize(new Dimension(DIAMETER, DIAMETER));
            setMinimumSize(new Dimension(DIAMETER, DIAMETER));
            setMaximumSize(new Dimension(DIAMETER, DIAMETER));
            setToolTipText("未知");
        }
        private void setQuality(String code) {
            if (Objects.equals(currentCode, code)) {
                return;
            }
            currentCode = code;
            currentColor = resolveFixQualityColor(code);
            setToolTipText(resolveFixQualityDescription(code));
            repaint();
        }
        @Override
        protected void paintComponent(Graphics g) {
            super.paintComponent(g);
            Graphics2D g2 = (Graphics2D) g.create();
            try {
                g2.setRenderingHint(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON);
                int diameter = Math.min(getWidth(), getHeight()) - 2;
                int x = (getWidth() - diameter) / 2;
                int y = (getHeight() - diameter) / 2;
                g2.setColor(currentColor);
                g2.fillOval(x, y, diameter, diameter);
                g2.setColor(new Color(255, 255, 255, 128));
                g2.drawOval(x, y, diameter, diameter);
            } finally {
                g2.dispose();
            }
        }
    }
    // 测试方法
    public static void main(String[] args) {
        JFrame frame = new JFrame("AutoMow - 首页");