package zhuye; import javax.swing.*; import baseStation.BaseStation; import baseStation.BaseStationDialog; import java.awt.*; import java.awt.event.*; import dikuai.Dikuai; import dikuai.Dikuaiguanli; import dikuai.addzhangaiwu; import gecaoji.Device; import set.Sets; import udpdell.UDPServer; import java.util.Map; /** * 首页界面 - 适配6.5寸竖屏,使用独立的MapRenderer进行绘制 */ public class Shouye extends JPanel { private static final long serialVersionUID = 1L; private static Shouye instance; // 主题颜色 private final Color THEME_COLOR = new Color(46, 139, 87); private final Color THEME_HOVER_COLOR = new Color(30, 107, 69); private final Color BACKGROUND_COLOR = new Color(250, 250, 250); private final Color PANEL_BACKGROUND = new Color(255, 255, 255); // 组件 private JPanel headerPanel; private JPanel mainContentPanel; private JPanel controlPanel; private JPanel navigationPanel; private JPanel visualizationPanel; // 按钮 private JButton startBtn; private JButton pauseBtn; private JButton legendBtn; private JButton remoteBtn; private JButton areaSelectBtn; private JButton baseStationBtn; // 导航按钮 private JButton homeNavBtn; private JButton areasNavBtn; private JButton settingsNavBtn; // 状态显示 private JLabel statusLabel; private JLabel areaNameLabel; // 当前选中的导航按钮 private JButton currentNavButton; // 对话框引用 private LegendDialog legendDialog; private RemoteControlDialog remoteDialog; private AreaSelectionDialog areaDialog; private BaseStationDialog baseStationDialog; private Sets settingsDialog; private BaseStation baseStation; // 地图渲染器 private MapRenderer mapRenderer; private static final int FLOAT_ICON_SIZE = 32; private JButton endDrawingButton; private JButton drawingPauseButton; private JPanel floatingButtonPanel; private JPanel floatingButtonColumn; private Runnable endDrawingCallback; private boolean drawingPaused; private ImageIcon pauseIcon; private ImageIcon pauseActiveIcon; private ImageIcon endIcon; private JPanel circleGuidancePanel; private JLabel circleGuidanceLabel; private JButton circleGuidancePrimaryButton; private JButton circleGuidanceSecondaryButton; private int circleGuidanceStep; private JDialog circleGuidanceDialog; private boolean circleDialogMode; private ComponentAdapter circleDialogOwnerAdapter; public Shouye() { instance = this; baseStation = new BaseStation(); baseStation.load(); initializeUI(); setupEventHandlers(); } public static Shouye getInstance() { return instance; } private void initializeUI() { setLayout(new BorderLayout()); setBackground(BACKGROUND_COLOR); // 创建各个面板 createHeaderPanel(); createMainContentPanel(); createControlPanel(); createNavigationPanel(); // 添加到主面板 add(headerPanel, BorderLayout.NORTH); add(mainContentPanel, BorderLayout.CENTER); add(controlPanel, BorderLayout.SOUTH); // 初始化地图渲染器 mapRenderer = new MapRenderer(visualizationPanel); // 初始化对话框引用为null,延迟创建 legendDialog = null; remoteDialog = null; areaDialog = null; baseStationDialog = null; settingsDialog = null; // 设置默认状态 setNavigationActive(homeNavBtn); initializeDefaultAreaSelection(); refreshMapForSelectedArea(); } private void createHeaderPanel() { headerPanel = new JPanel(new BorderLayout()); headerPanel.setBackground(PANEL_BACKGROUND); headerPanel.setBorder(BorderFactory.createEmptyBorder(15, 20, 15, 20)); headerPanel.setPreferredSize(new Dimension(0, 80)); // 左侧信息区域 JPanel leftInfoPanel = new JPanel(new GridLayout(2, 1)); leftInfoPanel.setBackground(PANEL_BACKGROUND); areaNameLabel = new JLabel("未选择地块"); areaNameLabel.setFont(new Font("微软雅黑", Font.BOLD, 18)); areaNameLabel.setForeground(Color.BLACK); areaNameLabel.setCursor(Cursor.getPredefinedCursor(Cursor.HAND_CURSOR)); areaNameLabel.addMouseListener(new MouseAdapter() { @Override public void mouseClicked(MouseEvent e) { Dikuaiguanli.showDikuaiManagement(Shouye.this, null); } @Override public void mouseEntered(MouseEvent e) { areaNameLabel.setForeground(THEME_COLOR); } @Override public void mouseExited(MouseEvent e) { areaNameLabel.setForeground(Color.BLACK); } }); statusLabel = new JLabel("待机"); statusLabel.setFont(new Font("微软雅黑", Font.PLAIN, 14)); statusLabel.setForeground(Color.GRAY); leftInfoPanel.add(areaNameLabel); leftInfoPanel.add(statusLabel); // 右侧操作区域 JPanel rightActionPanel = new JPanel(new FlowLayout(FlowLayout.RIGHT)); rightActionPanel.setBackground(PANEL_BACKGROUND); JButton notificationBtn = createIconButton("🔔", 40); // 修改设置按钮:使用图片替代Unicode图标 JButton settingsBtn = new JButton(); try { ImageIcon settingsIcon = new ImageIcon("image/sets.png"); // 调整图片大小以适应按钮 Image scaledImage = settingsIcon.getImage().getScaledInstance(30, 30, Image.SCALE_SMOOTH); settingsBtn.setIcon(new ImageIcon(scaledImage)); } catch (Exception e) { // 如果图片加载失败,使用默认文本 settingsBtn.setText("设置"); System.err.println("无法加载设置图标: " + e.getMessage()); } settingsBtn.setPreferredSize(new Dimension(40, 40)); settingsBtn.setBackground(PANEL_BACKGROUND); settingsBtn.setBorder(BorderFactory.createEmptyBorder(5, 5, 5, 5)); settingsBtn.setFocusPainted(false); // 添加悬停效果 settingsBtn.addMouseListener(new MouseAdapter() { public void mouseEntered(MouseEvent e) { settingsBtn.setBackground(new Color(240, 240, 240)); } public void mouseExited(MouseEvent e) { settingsBtn.setBackground(PANEL_BACKGROUND); } }); // 添加设置按钮事件 settingsBtn.addActionListener(e -> showSettingsDialog()); rightActionPanel.add(notificationBtn); rightActionPanel.add(settingsBtn); headerPanel.add(leftInfoPanel, BorderLayout.WEST); headerPanel.add(rightActionPanel, BorderLayout.EAST); } private void createMainContentPanel() { mainContentPanel = new JPanel(new BorderLayout()); mainContentPanel.setBackground(BACKGROUND_COLOR); // 可视化区域 - 使用MapRenderer进行绘制 visualizationPanel = new JPanel() { @Override protected void paintComponent(Graphics g) { super.paintComponent(g); // 委托给MapRenderer进行绘制 if (mapRenderer != null) { mapRenderer.renderMap(g); } } }; visualizationPanel.setLayout(new BorderLayout()); // 创建功能按钮面板(放在左上角) JPanel functionButtonsPanel = new JPanel(); functionButtonsPanel.setLayout(new BoxLayout(functionButtonsPanel, BoxLayout.Y_AXIS)); functionButtonsPanel.setOpaque(false); functionButtonsPanel.setBorder(BorderFactory.createEmptyBorder(20, 5, 0, 0)); // 左边距改为5像素 legendBtn = createFunctionButton("图例", "📖"); baseStationBtn = createFunctionButton("基准站", "📡"); // 调整到第二位 areaSelectBtn = createFunctionButton("地块", "🌿"); // 调整到第三位 remoteBtn = createFunctionButton("遥控", "🎮"); // 调整到最后 functionButtonsPanel.add(legendBtn); functionButtonsPanel.add(Box.createRigidArea(new Dimension(0, 10))); functionButtonsPanel.add(baseStationBtn); functionButtonsPanel.add(Box.createRigidArea(new Dimension(0, 10))); functionButtonsPanel.add(areaSelectBtn); functionButtonsPanel.add(Box.createRigidArea(new Dimension(0, 10))); functionButtonsPanel.add(remoteBtn); visualizationPanel.add(functionButtonsPanel, BorderLayout.WEST); mainContentPanel.add(visualizationPanel, BorderLayout.CENTER); } private void createControlPanel() { controlPanel = new JPanel(new BorderLayout()); controlPanel.setBackground(PANEL_BACKGROUND); controlPanel.setBorder(BorderFactory.createEmptyBorder(15, 20, 15, 20)); controlPanel.setPreferredSize(new Dimension(0, 100)); JPanel buttonPanel = new JPanel(new GridLayout(1, 2, 20, 0)); buttonPanel.setBackground(PANEL_BACKGROUND); startBtn = createControlButton("开始", THEME_COLOR); applyButtonIcon(startBtn, "image/startzuoye.png"); pauseBtn = createControlButton("暂停", Color.ORANGE); applyButtonIcon(pauseBtn, "image/zantingzuoye.png"); pauseBtn.setEnabled(false); buttonPanel.add(startBtn); buttonPanel.add(pauseBtn); controlPanel.add(buttonPanel, BorderLayout.CENTER); } private void createNavigationPanel() { navigationPanel = new JPanel(new GridLayout(1, 3)); navigationPanel.setBackground(PANEL_BACKGROUND); navigationPanel.setBorder(BorderFactory.createEmptyBorder(0, 0, 0, 0)); navigationPanel.setPreferredSize(new Dimension(0, 70)); homeNavBtn = createNavButton("首页", "🏠"); areasNavBtn = createNavButton("地块", "🌿"); settingsNavBtn = createNavButton("设置", "⚙️"); navigationPanel.add(homeNavBtn); navigationPanel.add(areasNavBtn); navigationPanel.add(settingsNavBtn); // 添加到主界面底部 add(navigationPanel, BorderLayout.SOUTH); } private JButton createIconButton(String icon, int size) { JButton button = new JButton(icon); button.setFont(new Font("Segoe UI Emoji", Font.PLAIN, 20)); button.setPreferredSize(new Dimension(size, size)); button.setBackground(PANEL_BACKGROUND); button.setBorder(BorderFactory.createEmptyBorder(5, 5, 5, 5)); button.setFocusPainted(false); // 悬停效果 button.addMouseListener(new MouseAdapter() { public void mouseEntered(MouseEvent e) { button.setBackground(new Color(240, 240, 240)); } public void mouseExited(MouseEvent e) { button.setBackground(PANEL_BACKGROUND); } }); return button; } private JButton createFunctionButton(String text, String icon) { JButton button = new JButton("
" + icon + "
" + text + "
"); button.setFont(new Font("微软雅黑", Font.PLAIN, 12)); button.setPreferredSize(new Dimension(80, 70)); button.setBackground(new Color(0, 0, 0, 0)); // 完全透明背景 button.setBorder(BorderFactory.createEmptyBorder(5, 5, 5, 5)); // 只保留内边距 button.setFocusPainted(false); button.setOpaque(false); // 设置为不透明,确保背景透明 // 去掉悬停效果 button.addMouseListener(new MouseAdapter() { public void mouseEntered(MouseEvent e) { // 悬停时不改变任何样式 } public void mouseExited(MouseEvent e) { // 悬停时不改变任何样式 } }); return button; } private JButton createControlButton(String text, Color color) { JButton button = new JButton(text); button.setFont(new Font("微软雅黑", Font.BOLD, 16)); button.setBackground(color); button.setForeground(Color.WHITE); button.setBorder(BorderFactory.createEmptyBorder(15, 0, 15, 0)); button.setFocusPainted(false); // 悬停效果 button.addMouseListener(new MouseAdapter() { public void mouseEntered(MouseEvent e) { if (button.isEnabled()) { if (color == THEME_COLOR) { button.setBackground(THEME_HOVER_COLOR); } else { button.setBackground(new Color(255, 165, 0)); } } } public void mouseExited(MouseEvent e) { if (button.isEnabled()) { button.setBackground(color); } } }); return button; } private void applyButtonIcon(JButton button, String imagePath) { try { ImageIcon icon = new ImageIcon(imagePath); Image scaledImage = icon.getImage().getScaledInstance(28, 28, Image.SCALE_SMOOTH); button.setIcon(new ImageIcon(scaledImage)); button.setHorizontalAlignment(SwingConstants.CENTER); button.setIconTextGap(10); button.setHorizontalTextPosition(SwingConstants.RIGHT); button.setVerticalTextPosition(SwingConstants.CENTER); } catch (Exception e) { System.err.println("无法加载按钮图标: " + imagePath + " -> " + e.getMessage()); } } private JButton createNavButton(String text, String icon) { JButton button = new JButton("
" + icon + "
" + text + "
"); button.setFont(new Font("微软雅黑", Font.PLAIN, 12)); button.setBackground(PANEL_BACKGROUND); button.setBorder(BorderFactory.createEmptyBorder(10, 5, 10, 5)); button.setFocusPainted(false); // 悬停效果 button.addMouseListener(new MouseAdapter() { public void mouseEntered(MouseEvent e) { if (button != currentNavButton) { button.setBackground(new Color(240, 240, 240)); } } public void mouseExited(MouseEvent e) { if (button != currentNavButton) { button.setBackground(PANEL_BACKGROUND); } } }); return button; } private void setNavigationActive(JButton navButton) { // 重置所有导航按钮样式 for (Component comp : navigationPanel.getComponents()) { if (comp instanceof JButton) { JButton btn = (JButton) comp; btn.setBackground(PANEL_BACKGROUND); btn.setForeground(Color.BLACK); } } // 设置当前选中按钮样式 navButton.setBackground(THEME_COLOR); navButton.setForeground(Color.WHITE); currentNavButton = navButton; } private void setupEventHandlers() { // 导航按钮事件 homeNavBtn.addActionListener(e -> setNavigationActive(homeNavBtn)); areasNavBtn.addActionListener(e -> setNavigationActive(areasNavBtn)); settingsNavBtn.addActionListener(e -> setNavigationActive(settingsNavBtn)); // 功能按钮事件 legendBtn.addActionListener(e -> showLegendDialog()); remoteBtn.addActionListener(e -> showRemoteControlDialog()); areaSelectBtn.addActionListener(e -> { // 点击“地块”直接打开地块管理对话框(若需要可传入特定地块编号) Dikuaiguanli.showDikuaiManagement(this, null); }); baseStationBtn.addActionListener(e -> showBaseStationDialog()); // 控制按钮事件 startBtn.addActionListener(e -> startMowing()); pauseBtn.addActionListener(e -> pauseMowing()); } private void showSettingsDialog() { if (settingsDialog == null) { Window parentWindow = SwingUtilities.getWindowAncestor(this); if (parentWindow instanceof JFrame) { settingsDialog = new Sets((JFrame) parentWindow, THEME_COLOR); } else if (parentWindow instanceof JDialog) { settingsDialog = new Sets((JDialog) parentWindow, THEME_COLOR); } else { // Fallback to a frameless dialog when no parent is available settingsDialog = new Sets((JFrame) null, THEME_COLOR); } } settingsDialog.setVisible(true); } private void showLegendDialog() { if (legendDialog == null) { Window parentWindow = SwingUtilities.getWindowAncestor(this); if (parentWindow != null) { legendDialog = new LegendDialog(this, THEME_COLOR); } else { // 如果没有父窗口,创建无父窗口的对话框 legendDialog = new LegendDialog((JFrame) null, THEME_COLOR); } } legendDialog.setVisible(true); } private void showRemoteControlDialog() { if (remoteDialog == null) { Window parentWindow = SwingUtilities.getWindowAncestor(this); if (parentWindow != null) { remoteDialog = new RemoteControlDialog(this, THEME_COLOR); } else { remoteDialog = new RemoteControlDialog((JFrame) null, THEME_COLOR); } } remoteDialog.setVisible(true); } private void showAreaSelectionDialog() { if (areaDialog == null) { Window parentWindow = SwingUtilities.getWindowAncestor(this); if (parentWindow != null) { areaDialog = new AreaSelectionDialog(this, THEME_COLOR, areaNameLabel, statusLabel); } else { areaDialog = new AreaSelectionDialog((JFrame) null, THEME_COLOR, areaNameLabel, statusLabel); } } areaDialog.setVisible(true); } private void showBaseStationDialog() { if (baseStation == null) { baseStation = new BaseStation(); } baseStation.load(); Component dialogParent = this; if (!hasValidBaseStationId()) { boolean recorded = promptForBaseStationId(dialogParent); if (!recorded) { return; } } Device device = new Device(); device.initFromProperties(); if (baseStationDialog == null) { baseStationDialog = new BaseStationDialog(dialogParent, THEME_COLOR, device, baseStation); } else { baseStationDialog.refreshData(); } baseStationDialog.setVisible(true); } private boolean hasValidBaseStationId() { if (baseStation == null) { return false; } String deviceId = baseStation.getDeviceId(); if (deviceId == null) { return false; } String trimmed = deviceId.trim(); return !trimmed.isEmpty() && !"-1".equals(trimmed); } private boolean promptForBaseStationId(Component parentComponent) { if (baseStation == null) { baseStation = new BaseStation(); } while (true) { String input = JOptionPane.showInputDialog(parentComponent, "请输入基准站编号", "录入基准站编号", JOptionPane.PLAIN_MESSAGE); if (input == null) { return false; } String trimmed = input.trim(); if (trimmed.isEmpty()) { JOptionPane.showMessageDialog(parentComponent, "基准站编号不能为空,请重新输入。", "提示", JOptionPane.WARNING_MESSAGE); continue; } try { baseStation.updateByDeviceId(trimmed, baseStation.getInstallationCoordinates(), baseStation.getIotSimCardNumber(), baseStation.getDeviceActivationTime(), baseStation.getDataUpdateTime()); baseStation.load(); JOptionPane.showMessageDialog(parentComponent, "基准站编号已保存。", "操作成功", JOptionPane.INFORMATION_MESSAGE); return true; } catch (IllegalArgumentException ex) { JOptionPane.showMessageDialog(parentComponent, ex.getMessage(), "输入错误", JOptionPane.ERROR_MESSAGE); } } } private void startMowing() { statusLabel.setText("作业中"); startBtn.setEnabled(false); pauseBtn.setEnabled(true); } private void pauseMowing() { statusLabel.setText("暂停中"); startBtn.setEnabled(true); pauseBtn.setEnabled(false); } private JButton createFloatingIconButton() { JButton button = new JButton(); button.setContentAreaFilled(false); button.setBorder(BorderFactory.createEmptyBorder()); button.setFocusPainted(false); button.setOpaque(false); button.setCursor(Cursor.getPredefinedCursor(Cursor.HAND_CURSOR)); int size = FLOAT_ICON_SIZE + 8; button.setPreferredSize(new Dimension(size, size)); return button; } private ImageIcon loadScaledIcon(String path, int width, int height) { try { ImageIcon icon = new ImageIcon(path); if (icon.getIconWidth() <= 0 || icon.getIconHeight() <= 0) { return null; } Image scaled = icon.getImage().getScaledInstance(width, height, Image.SCALE_SMOOTH); return new ImageIcon(scaled); } catch (Exception ex) { System.err.println("加载图标失败: " + path + " - " + ex.getMessage()); return null; } } private void ensureFloatingIconsLoaded() { if (pauseIcon == null) { pauseIcon = loadScaledIcon("image/zanting.png", FLOAT_ICON_SIZE, FLOAT_ICON_SIZE); } if (pauseActiveIcon == null) { pauseActiveIcon = loadScaledIcon("image/zantingzhong.png", FLOAT_ICON_SIZE, FLOAT_ICON_SIZE); } if (endIcon == null) { endIcon = loadScaledIcon("image/end.png", FLOAT_ICON_SIZE, FLOAT_ICON_SIZE); } } private void updatePauseButtonVisual() { if (drawingPauseButton == null) { return; } if (drawingPaused) { if (pauseActiveIcon != null) { drawingPauseButton.setIcon(pauseActiveIcon); drawingPauseButton.setText(null); } else { drawingPauseButton.setText("暂停中"); drawingPauseButton.setIcon(null); } drawingPauseButton.setToolTipText("点击恢复绘制"); } else { if (pauseIcon != null) { drawingPauseButton.setIcon(pauseIcon); drawingPauseButton.setText(null); } else { drawingPauseButton.setText("暂停"); drawingPauseButton.setIcon(null); } drawingPauseButton.setToolTipText("点击暂停绘制"); } } private void applyDrawingPauseState(boolean paused, boolean notifyCoordinate) { drawingPaused = paused; updatePauseButtonVisual(); if (notifyCoordinate) { Coordinate.setStartSaveGngga(!paused); } } private void toggleDrawingPause() { applyDrawingPauseState(!drawingPaused, true); } public void showEndDrawingButton(Runnable callback) { showEndDrawingButton(callback, null); } public void showEndDrawingButton(Runnable callback, String drawingShape) { endDrawingCallback = callback; applyDrawingPauseState(false, false); circleDialogMode = drawingShape != null && "circle".equalsIgnoreCase(drawingShape); if (circleDialogMode) { hideFloatingDrawingControls(); ensureCircleGuidancePanel(); showCircleGuidanceStep(1); visualizationPanel.revalidate(); visualizationPanel.repaint(); return; } circleDialogMode = false; hideCircleGuidancePanel(); ensureFloatingIconsLoaded(); ensureFloatingButtonInfrastructure(); endDrawingButton.setVisible(true); if (drawingPauseButton != null) { drawingPauseButton.setVisible(true); } floatingButtonPanel.setVisible(true); if (floatingButtonPanel.getParent() != visualizationPanel) { visualizationPanel.add(floatingButtonPanel, BorderLayout.SOUTH); } rebuildFloatingButtonColumn(); visualizationPanel.revalidate(); visualizationPanel.repaint(); } private void ensureFloatingButtonInfrastructure() { if (endDrawingButton == null) { endDrawingButton = createFloatingIconButton(); endDrawingButton.addActionListener(e -> { if (endDrawingCallback != null) { endDrawingCallback.run(); } }); } if (endIcon != null) { endDrawingButton.setIcon(endIcon); endDrawingButton.setText(null); } else { endDrawingButton.setText("结束绘制"); } endDrawingButton.setToolTipText("结束绘制"); if (drawingPauseButton == null) { drawingPauseButton = createFloatingIconButton(); drawingPauseButton.addActionListener(e -> toggleDrawingPause()); } updatePauseButtonVisual(); if (floatingButtonPanel == null) { floatingButtonPanel = new JPanel(new BorderLayout()); floatingButtonPanel.setOpaque(false); floatingButtonPanel.setBorder(BorderFactory.createEmptyBorder(0, 0, 20, 20)); floatingButtonColumn = new JPanel(); floatingButtonColumn.setOpaque(false); floatingButtonColumn.setLayout(new BoxLayout(floatingButtonColumn, BoxLayout.Y_AXIS)); floatingButtonPanel.add(floatingButtonColumn, BorderLayout.EAST); } } private void hideFloatingDrawingControls() { if (drawingPauseButton != null) { drawingPauseButton.setVisible(false); } if (endDrawingButton != null) { endDrawingButton.setVisible(false); } if (floatingButtonPanel != null) { floatingButtonPanel.setVisible(false); } if (!circleDialogMode) { rebuildFloatingButtonColumn(); } } private void rebuildFloatingButtonColumn() { if (floatingButtonColumn == null) { return; } floatingButtonColumn.removeAll(); boolean added = false; if (!circleDialogMode && circleGuidancePanel != null && circleGuidancePanel.isVisible()) { floatingButtonColumn.add(circleGuidancePanel); added = true; } if (!circleDialogMode && drawingPauseButton != null && drawingPauseButton.isVisible()) { if (added) { floatingButtonColumn.add(Box.createRigidArea(new Dimension(0, 10))); } floatingButtonColumn.add(drawingPauseButton); added = true; } if (!circleDialogMode && endDrawingButton != null && endDrawingButton.isVisible()) { if (added) { floatingButtonColumn.add(Box.createRigidArea(new Dimension(0, 10))); } floatingButtonColumn.add(endDrawingButton); } floatingButtonColumn.revalidate(); floatingButtonColumn.repaint(); } private void showCircleGuidanceStep(int step) { ensureCircleGuidancePanel(); if (circleGuidancePanel == null) { return; } circleGuidanceStep = step; if (step == 1) { circleGuidanceLabel.setText("是否将当前点设置为圆心?"); circleGuidancePrimaryButton.setText("是"); circleGuidanceSecondaryButton.setText("返回"); circleGuidanceSecondaryButton.setVisible(true); } else if (step == 2) { circleGuidanceLabel.setText("是否将当前点设置为半径点?"); circleGuidancePrimaryButton.setText("是"); circleGuidanceSecondaryButton.setVisible(false); } else { hideCircleGuidancePanel(); return; } circleGuidancePanel.setVisible(true); if (circleDialogMode) { ensureCircleGuidanceDialog(); if (circleGuidanceDialog != null) { circleGuidanceDialog.pack(); positionCircleGuidanceDialog(); circleGuidanceDialog.setVisible(true); circleGuidanceDialog.toFront(); } } else { rebuildFloatingButtonColumn(); } } private void ensureCircleGuidancePanel() { if (circleGuidancePanel != null) { return; } circleGuidancePanel = new JPanel(); circleGuidancePanel.setLayout(new BoxLayout(circleGuidancePanel, BoxLayout.Y_AXIS)); circleGuidancePanel.setOpaque(true); circleGuidancePanel.setBackground(new Color(255, 255, 255, 235)); circleGuidancePanel.setBorder(BorderFactory.createCompoundBorder( BorderFactory.createLineBorder(THEME_COLOR, 1), BorderFactory.createEmptyBorder(10, 12, 10, 12))); circleGuidancePanel.setAlignmentX(Component.LEFT_ALIGNMENT); circleGuidanceLabel = new JLabel(); circleGuidanceLabel.setFont(new Font("微软雅黑", Font.BOLD, 13)); circleGuidanceLabel.setForeground(new Color(33, 37, 41)); circleGuidanceLabel.setAlignmentX(Component.LEFT_ALIGNMENT); JPanel buttonRow = new JPanel(); buttonRow.setLayout(new BoxLayout(buttonRow, BoxLayout.X_AXIS)); buttonRow.setOpaque(false); buttonRow.setAlignmentX(Component.LEFT_ALIGNMENT); circleGuidancePrimaryButton = createGuidanceButton("是", THEME_COLOR, Color.WHITE, true); circleGuidancePrimaryButton.addActionListener(e -> onCircleGuidancePrimary()); circleGuidanceSecondaryButton = createGuidanceButton("否", Color.WHITE, THEME_COLOR, false); circleGuidanceSecondaryButton.addActionListener(e -> onCircleGuidanceSecondary()); buttonRow.add(circleGuidancePrimaryButton); buttonRow.add(Box.createRigidArea(new Dimension(8, 0))); buttonRow.add(circleGuidanceSecondaryButton); circleGuidancePanel.add(circleGuidanceLabel); circleGuidancePanel.add(Box.createRigidArea(new Dimension(0, 8))); circleGuidancePanel.add(buttonRow); circleGuidancePanel.setVisible(false); } private void ensureCircleGuidanceDialog() { if (circleGuidancePanel == null) { return; } if (circleGuidanceDialog != null) { if (circleGuidancePanel.getParent() != circleGuidanceDialog.getContentPane()) { detachCircleGuidancePanel(); circleGuidanceDialog.getContentPane().removeAll(); circleGuidanceDialog.getContentPane().add(circleGuidancePanel, BorderLayout.CENTER); circleGuidanceDialog.pack(); } return; } Window owner = SwingUtilities.getWindowAncestor(this); circleGuidanceDialog = new JDialog(owner, "绘制提示", Dialog.ModalityType.MODELESS); circleGuidanceDialog.setDefaultCloseOperation(WindowConstants.HIDE_ON_CLOSE); circleGuidanceDialog.setResizable(false); circleGuidanceDialog.setAlwaysOnTop(true); if (owner != null && circleDialogOwnerAdapter == null) { circleDialogOwnerAdapter = new ComponentAdapter() { @Override public void componentMoved(ComponentEvent e) { positionCircleGuidanceDialog(); } @Override public void componentResized(ComponentEvent e) { positionCircleGuidanceDialog(); } }; owner.addComponentListener(circleDialogOwnerAdapter); } detachCircleGuidancePanel(); circleGuidanceDialog.getContentPane().setLayout(new BorderLayout()); circleGuidanceDialog.getContentPane().add(circleGuidancePanel, BorderLayout.CENTER); circleGuidanceDialog.pack(); } private void detachCircleGuidancePanel() { if (circleGuidancePanel == null) { return; } Container parent = circleGuidancePanel.getParent(); if (parent != null) { parent.remove(circleGuidancePanel); parent.revalidate(); parent.repaint(); } } private void positionCircleGuidanceDialog() { if (circleGuidanceDialog == null) { return; } Window owner = SwingUtilities.getWindowAncestor(this); if (owner == null || !owner.isShowing()) { return; } try { Point ownerLocation = owner.getLocationOnScreen(); int x = ownerLocation.x + owner.getWidth() - circleGuidanceDialog.getWidth() - 30; int y = ownerLocation.y + owner.getHeight() - circleGuidanceDialog.getHeight() - 40; x = Math.max(ownerLocation.x, x); y = Math.max(ownerLocation.y, y); circleGuidanceDialog.setLocation(x, y); } catch (IllegalComponentStateException ex) { // Owner not yet displayable; skip positioning } } private JButton createGuidanceButton(String text, Color bg, Color fg, boolean filled) { JButton button = new JButton(text); button.setFont(new Font("微软雅黑", Font.BOLD, 12)); button.setForeground(fg); button.setBackground(bg); button.setOpaque(true); button.setFocusPainted(false); button.setCursor(Cursor.getPredefinedCursor(Cursor.HAND_CURSOR)); button.setAlignmentX(Component.LEFT_ALIGNMENT); if (filled) { button.setBorder(BorderFactory.createEmptyBorder(6, 14, 6, 14)); } else { button.setBackground(Color.WHITE); button.setOpaque(true); button.setBorder(BorderFactory.createCompoundBorder( BorderFactory.createLineBorder(THEME_COLOR, 1), BorderFactory.createEmptyBorder(5, 12, 5, 12))); } button.addMouseListener(new MouseAdapter() { @Override public void mouseEntered(MouseEvent e) { if (filled) { button.setBackground(THEME_HOVER_COLOR); } else { button.setBackground(new Color(245, 245, 245)); } } @Override public void mouseExited(MouseEvent e) { if (filled) { button.setBackground(bg); } else { button.setBackground(Color.WHITE); } } }); return button; } private void onCircleGuidancePrimary() { if (circleGuidanceStep == 1) { showCircleGuidanceStep(2); } else { handleCircleCompletion(); } } private void onCircleGuidanceSecondary() { if (circleGuidanceStep == 1) { handleCircleAbort(null); } else if (circleGuidanceStep == 2) { handleCircleAbort(null); } else { hideCircleGuidancePanel(); } } private void hideCircleGuidancePanel() { circleGuidanceStep = 0; if (circleGuidancePanel != null) { circleGuidancePanel.setVisible(false); } if (circleGuidanceDialog != null) { circleGuidanceDialog.setVisible(false); } if (!circleDialogMode) { rebuildFloatingButtonColumn(); } } private void handleCircleAbort(String message) { // Return the wizard to step 2 without committing any captured points hideEndDrawingButton(); addzhangaiwu.abortCircleDrawingAndReturn(message); } private void handleCircleCompletion() { hideCircleGuidancePanel(); if (endDrawingCallback != null) { endDrawingCallback.run(); } else { addzhangaiwu.finishDrawingSession(); } } public void hideEndDrawingButton() { hideCircleGuidancePanel(); hideFloatingDrawingControls(); circleDialogMode = false; applyDrawingPauseState(false, false); endDrawingCallback = null; visualizationPanel.revalidate(); visualizationPanel.repaint(); } /** * 获取地图渲染器实例 */ public MapRenderer getMapRenderer() { return mapRenderer; } public void updateCurrentAreaName(String areaName) { if (areaNameLabel == null) { return; } if (areaName == null || areaName.trim().isEmpty()) { areaNameLabel.setText("未选择地块"); } else { areaNameLabel.setText(areaName); } } /** * 重置地图视图 */ public void resetMapView() { if (mapRenderer != null) { mapRenderer.resetView(); } } private void initializeDefaultAreaSelection() { Dikuai.initFromProperties(); Map all = Dikuai.getAllDikuai(); if (all.isEmpty()) { Dikuaiguanli.setCurrentWorkLand(null, null); } else if (all.size() == 1) { Dikuai only = all.values().iterator().next(); if (only != null) { Dikuaiguanli.setCurrentWorkLand(only.getLandNumber(), only.getLandName()); } } } private void refreshMapForSelectedArea() { if (mapRenderer == null) { return; } String currentLandNumber = Dikuaiguanli.getCurrentWorkLandNumber(); if (isMeaningfulValue(currentLandNumber)) { Dikuai current = Dikuai.getDikuai(currentLandNumber); String landName = current != null ? current.getLandName() : null; Dikuaiguanli.setCurrentWorkLand(currentLandNumber, landName); return; } String labelName = areaNameLabel != null ? areaNameLabel.getText() : null; if (!isMeaningfulAreaName(labelName)) { Dikuaiguanli.setCurrentWorkLand(null, null); return; } Map all = Dikuai.getAllDikuai(); for (Dikuai dikuai : all.values()) { if (dikuai == null) { continue; } String candidateName = dikuai.getLandName(); if (candidateName != null && candidateName.trim().equals(labelName.trim())) { Dikuaiguanli.setCurrentWorkLand(dikuai.getLandNumber(), candidateName); return; } } Dikuaiguanli.setCurrentWorkLand(null, null); } private boolean isMeaningfulValue(String value) { if (value == null) { return false; } String trimmed = value.trim(); return !trimmed.isEmpty() && !"-1".equals(trimmed); } private boolean isMeaningfulAreaName(String value) { if (value == null) { return false; } String trimmed = value.trim(); if (trimmed.isEmpty()) { return false; } return !"未选择地块".equals(trimmed); } // 测试方法 public static void main(String[] args) { JFrame frame = new JFrame("AutoMow - 首页"); frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); frame.setSize(400, 800); frame.setLocationRelativeTo(null); Shouye shouye = new Shouye(); frame.add(shouye); frame.setVisible(true); UDPServer.startAsync();//启动数据接收线程 } }