| | |
| | | |
| | | import java.awt.*; |
| | | import java.awt.event.*; |
| | | import java.awt.geom.Point2D; |
| | | import java.io.File; |
| | | import java.util.ArrayList; |
| | | import java.util.List; |
| | | import java.util.Locale; |
| | | |
| | | /** |
| | | * 设置对话框 - 参考Shouye.java样式 |
| | |
| | | private JLabel idleTrailDurationLabel; |
| | | private JLabel boundaryLengthVisibleLabel; |
| | | private JLabel measurementModeEnabledLabel; |
| | | private JLabel manualBoundaryDrawingModeLabel; |
| | | |
| | | private JButton mowerIdEditBtn; |
| | | private JButton mowerSizeEditBtn; |
| | |
| | | // 开启测量模式设置项 |
| | | JPanel measurementModePanel = createMeasurementModePanel(); |
| | | measurementModeEnabledLabel = (JLabel) measurementModePanel.getClientProperty("valueLabel"); |
| | | |
| | | // 手动绘制边界模式设置项 |
| | | JPanel manualBoundaryDrawingPanel = createManualBoundaryDrawingPanel(); |
| | | manualBoundaryDrawingModeLabel = (JLabel) manualBoundaryDrawingPanel.getClientProperty("valueLabel"); |
| | | |
| | | JPanel feedbackPanel = createFeedbackPanel(); |
| | | |
| | |
| | | addSettingItem(panel, idleTrailPanel, true); |
| | | addSettingItem(panel, boundaryLengthPanel, true); |
| | | addSettingItem(panel, measurementModePanel, true); |
| | | addSettingItem(panel, manualBoundaryDrawingPanel, true); |
| | | addSettingItem(panel, feedbackPanel, true); |
| | | addSettingItem(panel, appVersionPanel, false); // 最后一项不加分割线 |
| | | |
| | |
| | | } |
| | | |
| | | /** |
| | | * 创建手动绘制边界模式设置面板 |
| | | */ |
| | | private JPanel createManualBoundaryDrawingPanel() { |
| | | JPanel panel = new JPanel(new GridBagLayout()); |
| | | panel.setOpaque(false); // 透明背景 |
| | | panel.setAlignmentX(Component.LEFT_ALIGNMENT); |
| | | panel.setMaximumSize(new Dimension(Integer.MAX_VALUE, ROW_HEIGHT)); |
| | | panel.setPreferredSize(new Dimension(Integer.MAX_VALUE, ROW_HEIGHT)); |
| | | panel.setMinimumSize(new Dimension(0, ROW_HEIGHT)); |
| | | panel.setBorder(BorderFactory.createEmptyBorder(ITEM_PADDING, ITEM_PADDING, ITEM_PADDING, ITEM_PADDING)); |
| | | |
| | | GridBagConstraints gbc = new GridBagConstraints(); |
| | | |
| | | JLabel titleLabel = new JLabel("手动绘制边界模式"); |
| | | titleLabel.setFont(new Font("微软雅黑", Font.BOLD, 14)); |
| | | titleLabel.setForeground(Color.BLACK); |
| | | titleLabel.setHorizontalAlignment(SwingConstants.RIGHT); |
| | | titleLabel.setCursor(new Cursor(Cursor.HAND_CURSOR)); |
| | | // 添加点击事件,显示坐标对话框 |
| | | titleLabel.addMouseListener(new MouseAdapter() { |
| | | @Override |
| | | public void mouseClicked(MouseEvent e) { |
| | | showManualBoundaryCoordinatesDialog(); |
| | | } |
| | | |
| | | @Override |
| | | public void mouseEntered(MouseEvent e) { |
| | | titleLabel.setForeground(THEME_COLOR); |
| | | } |
| | | |
| | | @Override |
| | | public void mouseExited(MouseEvent e) { |
| | | titleLabel.setForeground(Color.BLACK); |
| | | } |
| | | }); |
| | | gbc.gridx = 0; |
| | | gbc.gridy = 0; |
| | | gbc.weightx = 0; |
| | | gbc.anchor = GridBagConstraints.EAST; |
| | | gbc.insets = new Insets(0, 0, 0, 12); |
| | | panel.add(titleLabel, gbc); |
| | | |
| | | manualBoundaryDrawingModeLabel = new JLabel(setData.isManualBoundaryDrawingMode() ? "已开启" : "已关闭"); |
| | | manualBoundaryDrawingModeLabel.setFont(new Font("微软雅黑", Font.PLAIN, 14)); |
| | | manualBoundaryDrawingModeLabel.setForeground(Color.DARK_GRAY); |
| | | gbc = new GridBagConstraints(); |
| | | gbc.gridx = 1; |
| | | gbc.gridy = 0; |
| | | gbc.weightx = 1.0; |
| | | gbc.anchor = GridBagConstraints.EAST; |
| | | panel.add(manualBoundaryDrawingModeLabel, gbc); |
| | | |
| | | panel.putClientProperty("valueLabel", manualBoundaryDrawingModeLabel); |
| | | |
| | | // 创建切换按钮(使用图标) |
| | | JButton toggleBtn = createManualBoundaryDrawingToggleButton(); |
| | | gbc = new GridBagConstraints(); |
| | | gbc.gridx = 2; |
| | | gbc.gridy = 0; |
| | | gbc.weightx = 0; |
| | | gbc.anchor = GridBagConstraints.EAST; |
| | | panel.add(toggleBtn, gbc); |
| | | panel.putClientProperty("toggleButton", toggleBtn); |
| | | |
| | | return panel; |
| | | } |
| | | |
| | | /** |
| | | * 创建手动绘制边界模式切换按钮 |
| | | */ |
| | | private JButton createManualBoundaryDrawingToggleButton() { |
| | | JButton button = new JButton(); |
| | | button.setContentAreaFilled(false); |
| | | button.setBorder(null); |
| | | button.setFocusPainted(false); |
| | | button.setCursor(new Cursor(Cursor.HAND_CURSOR)); |
| | | button.setPreferredSize(new Dimension(32, 32)); |
| | | button.setMinimumSize(new Dimension(32, 32)); |
| | | button.setMaximumSize(new Dimension(32, 32)); |
| | | |
| | | updateManualBoundaryDrawingToggleButton(button); |
| | | |
| | | button.addActionListener(e -> toggleManualBoundaryDrawingMode(button)); |
| | | |
| | | return button; |
| | | } |
| | | |
| | | /** |
| | | * 更新手动绘制边界模式切换按钮图标 |
| | | */ |
| | | private void updateManualBoundaryDrawingToggleButton(JButton button) { |
| | | boolean isEnabled = setData.isManualBoundaryDrawingMode(); |
| | | try { |
| | | String iconPath = isEnabled ? "image/open.png" : "image/close.png"; |
| | | ImageIcon icon = new ImageIcon(iconPath); |
| | | if (icon.getIconWidth() > 0) { |
| | | Image scaledImage = icon.getImage().getScaledInstance(32, 32, Image.SCALE_SMOOTH); |
| | | button.setIcon(new ImageIcon(scaledImage)); |
| | | button.setText(null); |
| | | } else { |
| | | button.setIcon(null); |
| | | button.setText(isEnabled ? "开" : "关"); |
| | | } |
| | | } catch (Exception e) { |
| | | button.setIcon(null); |
| | | button.setText(isEnabled ? "开" : "关"); |
| | | System.err.println("无法加载手动绘制边界模式图标: " + e.getMessage()); |
| | | } |
| | | } |
| | | |
| | | /** |
| | | * 切换手动绘制边界模式状态 |
| | | */ |
| | | private void toggleManualBoundaryDrawingMode(JButton button) { |
| | | boolean newValue = !setData.isManualBoundaryDrawingMode(); |
| | | setData.setManualBoundaryDrawingMode(newValue); |
| | | |
| | | // 保存到配置文件 |
| | | setData.updateProperty("manualBoundaryDrawingMode", String.valueOf(newValue)); |
| | | |
| | | // 更新UI |
| | | if (manualBoundaryDrawingModeLabel != null) { |
| | | manualBoundaryDrawingModeLabel.setText(newValue ? "已开启" : "已关闭"); |
| | | } |
| | | updateManualBoundaryDrawingToggleButton(button); |
| | | |
| | | // 通知MapRenderer更新手动绘制边界模式状态 |
| | | Shouye shouye = Shouye.getInstance(); |
| | | if (shouye != null) { |
| | | MapRenderer renderer = shouye.getMapRenderer(); |
| | | if (renderer != null) { |
| | | renderer.setManualBoundaryDrawingMode(newValue); |
| | | if (!newValue) { |
| | | // 如果关闭模式,清空已绘制的点 |
| | | renderer.clearManualBoundaryPoints(); |
| | | } |
| | | } |
| | | // 通知首页更新悬浮返回按钮显示状态 |
| | | shouye.updateSettingsReturnButtonVisibility(); |
| | | } |
| | | |
| | | // 如果开启,关闭系统设置页面并返回首页 |
| | | if (newValue) { |
| | | SwingUtilities.invokeLater(() -> { |
| | | setVisible(false); |
| | | dispose(); |
| | | }); |
| | | } |
| | | } |
| | | |
| | | /** |
| | | * 创建开启测量模式设置面板 |
| | | */ |
| | | private JPanel createMeasurementModePanel() { |
| | |
| | | if (renderer != null) { |
| | | renderer.repaint(); |
| | | } |
| | | // 通知首页更新悬浮返回按钮显示状态 |
| | | shouye.updateSettingsReturnButtonVisibility(); |
| | | } |
| | | |
| | | // 如果开启,关闭系统设置页面并返回首页 |
| | | if (newValue) { |
| | | SwingUtilities.invokeLater(() -> { |
| | | setVisible(false); |
| | | dispose(); |
| | | }); |
| | | } |
| | | } |
| | | |
| | |
| | | if (renderer != null) { |
| | | renderer.setBoundaryLengthVisible(newValue); |
| | | } |
| | | // 通知首页更新悬浮返回按钮显示状态 |
| | | shouye.updateSettingsReturnButtonVisibility(); |
| | | } |
| | | |
| | | // 如果开启,关闭系统设置页面并返回首页 |
| | | if (newValue) { |
| | | SwingUtilities.invokeLater(() -> { |
| | | setVisible(false); |
| | | dispose(); |
| | | }); |
| | | } |
| | | } |
| | | |
| | |
| | | } |
| | | } |
| | | |
| | | // 更新手动绘制边界模式状态 |
| | | if (manualBoundaryDrawingModeLabel != null) { |
| | | manualBoundaryDrawingModeLabel.setText(setData.isManualBoundaryDrawingMode() ? "已开启" : "已关闭"); |
| | | } |
| | | // 更新手动绘制边界模式切换按钮图标 |
| | | JPanel manualBoundaryDrawingPanel = (JPanel) manualBoundaryDrawingModeLabel.getParent(); |
| | | if (manualBoundaryDrawingPanel != null) { |
| | | JButton toggleBtn = (JButton) manualBoundaryDrawingPanel.getClientProperty("toggleButton"); |
| | | if (toggleBtn != null) { |
| | | updateManualBoundaryDrawingToggleButton(toggleBtn); |
| | | } |
| | | } |
| | | |
| | | // 更新APP版本显示 |
| | | if (appVersionLabel != null) { |
| | | appVersionLabel.setText(setData.getAppVersion() != null ? |
| | |
| | | } |
| | | } |
| | | |
| | | /** |
| | | * 显示手动绘制边界坐标对话框 |
| | | */ |
| | | private void showManualBoundaryCoordinatesDialog() { |
| | | // 从 shoudongbianjie.properties 文件读取坐标 |
| | | String coordinates = null; |
| | | int pointCount = 0; |
| | | |
| | | try { |
| | | java.util.Properties props = new java.util.Properties(); |
| | | java.io.File file = new java.io.File("shoudongbianjie.properties"); |
| | | |
| | | if (file.exists()) { |
| | | try (java.io.FileInputStream input = new java.io.FileInputStream(file)) { |
| | | props.load(input); |
| | | coordinates = props.getProperty("boundaryCoordinates"); |
| | | String pointCountStr = props.getProperty("pointCount"); |
| | | if (pointCountStr != null && !pointCountStr.trim().isEmpty()) { |
| | | try { |
| | | pointCount = Integer.parseInt(pointCountStr.trim()); |
| | | } catch (NumberFormatException e) { |
| | | // 如果无法解析,从坐标字符串计算点数 |
| | | if (coordinates != null && !coordinates.trim().isEmpty()) { |
| | | pointCount = coordinates.split(";").length; |
| | | } |
| | | } |
| | | } else if (coordinates != null && !coordinates.trim().isEmpty()) { |
| | | // 如果没有点数量,从坐标字符串计算 |
| | | pointCount = coordinates.split(";").length; |
| | | } |
| | | } |
| | | } |
| | | } catch (Exception ex) { |
| | | ex.printStackTrace(); |
| | | JOptionPane.showMessageDialog(this, |
| | | "读取坐标文件失败: " + ex.getMessage(), |
| | | "错误", |
| | | JOptionPane.ERROR_MESSAGE); |
| | | return; |
| | | } |
| | | |
| | | // 如果没有坐标数据,显示提示 |
| | | if (coordinates == null || coordinates.trim().isEmpty()) { |
| | | JOptionPane.showMessageDialog(this, |
| | | "当前没有保存的边界坐标", |
| | | "提示", |
| | | JOptionPane.INFORMATION_MESSAGE); |
| | | return; |
| | | } |
| | | |
| | | // 创建对话框 - 宽度和系统设置页面一样(400) |
| | | JDialog dialog = new JDialog(this, "手动绘制边界坐标", true); |
| | | dialog.setLayout(new BorderLayout(0, 12)); |
| | | dialog.setResizable(true); |
| | | dialog.setPreferredSize(new Dimension(400, 400)); |
| | | dialog.setSize(new Dimension(400, 400)); |
| | | dialog.setMinimumSize(new Dimension(400, 300)); |
| | | |
| | | JPanel content = new JPanel(); |
| | | content.setLayout(new BoxLayout(content, BoxLayout.Y_AXIS)); |
| | | content.setBorder(BorderFactory.createEmptyBorder(20, 24, 20, 24)); |
| | | dialog.add(content, BorderLayout.CENTER); |
| | | |
| | | // 标题 |
| | | String titleText = pointCount > 0 |
| | | ? "坐标点列表(共 " + pointCount + " 个点):" |
| | | : "坐标点列表:"; |
| | | JLabel titleLabel = new JLabel(titleText); |
| | | titleLabel.setFont(new Font("微软雅黑", Font.BOLD, 14)); |
| | | titleLabel.setAlignmentX(Component.LEFT_ALIGNMENT); |
| | | content.add(titleLabel); |
| | | |
| | | content.add(Box.createRigidArea(new Dimension(0, 10))); |
| | | |
| | | // 坐标文本区域 |
| | | JTextArea coordinatesArea = new JTextArea(coordinates); |
| | | coordinatesArea.setFont(new Font("微软雅黑", Font.PLAIN, 12)); |
| | | coordinatesArea.setLineWrap(true); |
| | | coordinatesArea.setWrapStyleWord(false); |
| | | coordinatesArea.setEditable(false); |
| | | coordinatesArea.setBackground(Color.WHITE); |
| | | JScrollPane scrollPane = new JScrollPane(coordinatesArea); |
| | | scrollPane.setAlignmentX(Component.LEFT_ALIGNMENT); |
| | | scrollPane.setPreferredSize(new Dimension(0, 200)); |
| | | content.add(scrollPane); |
| | | |
| | | content.add(Box.createRigidArea(new Dimension(0, 16))); |
| | | |
| | | // 按钮面板 |
| | | JPanel buttonPanel = new JPanel(new FlowLayout(FlowLayout.RIGHT, 10, 0)); |
| | | buttonPanel.setAlignmentX(Component.LEFT_ALIGNMENT); |
| | | |
| | | // 创建复制按钮,使用图标 |
| | | JButton copyButton = new JButton(); |
| | | try { |
| | | ImageIcon copyIcon = new ImageIcon("image/fuzhi.png"); |
| | | if (copyIcon.getIconWidth() > 0) { |
| | | // 调整图标大小 |
| | | Image scaledImage = copyIcon.getImage().getScaledInstance(32, 32, Image.SCALE_SMOOTH); |
| | | copyButton.setIcon(new ImageIcon(scaledImage)); |
| | | } else { |
| | | copyButton.setText("复制坐标"); |
| | | } |
| | | } catch (Exception ex) { |
| | | copyButton.setText("复制坐标"); |
| | | System.err.println("无法加载复制图标: " + ex.getMessage()); |
| | | } |
| | | copyButton.setContentAreaFilled(false); |
| | | copyButton.setBorder(null); |
| | | copyButton.setFocusPainted(false); |
| | | copyButton.setCursor(new Cursor(Cursor.HAND_CURSOR)); |
| | | copyButton.setToolTipText("复制坐标"); |
| | | |
| | | // 加载成功图标 |
| | | ImageIcon successIcon = null; |
| | | try { |
| | | ImageIcon originalSuccessIcon = new ImageIcon("image/fuzhisucc.png"); |
| | | if (originalSuccessIcon.getIconWidth() > 0) { |
| | | Image scaledSuccessImage = originalSuccessIcon.getImage().getScaledInstance(32, 32, Image.SCALE_SMOOTH); |
| | | successIcon = new ImageIcon(scaledSuccessImage); |
| | | } |
| | | } catch (Exception ex) { |
| | | System.err.println("无法加载成功图标: " + ex.getMessage()); |
| | | } |
| | | |
| | | final ImageIcon finalSuccessIcon = successIcon; |
| | | final ImageIcon originalCopyIcon = (ImageIcon) copyButton.getIcon(); |
| | | |
| | | copyButton.addActionListener(e -> { |
| | | String text = coordinatesArea.getText(); |
| | | if (text != null && !text.trim().isEmpty()) { |
| | | java.awt.Toolkit.getDefaultToolkit().getSystemClipboard().setContents( |
| | | new java.awt.datatransfer.StringSelection(text), null); |
| | | |
| | | // 切换为成功图标 |
| | | if (finalSuccessIcon != null) { |
| | | copyButton.setIcon(finalSuccessIcon); |
| | | } |
| | | |
| | | // 2秒后恢复为原始图标 |
| | | Timer restoreTimer = new Timer(2000, evt -> { |
| | | if (originalCopyIcon != null) { |
| | | copyButton.setIcon(originalCopyIcon); |
| | | } |
| | | }); |
| | | restoreTimer.setRepeats(false); |
| | | restoreTimer.start(); |
| | | } |
| | | }); |
| | | |
| | | // 创建关闭按钮,使用图标 |
| | | JButton closeButton = new JButton(); |
| | | try { |
| | | ImageIcon closeIcon = new ImageIcon("image/closepage.png"); |
| | | if (closeIcon.getIconWidth() > 0) { |
| | | // 调整图标大小 |
| | | Image scaledImage = closeIcon.getImage().getScaledInstance(32, 32, Image.SCALE_SMOOTH); |
| | | closeButton.setIcon(new ImageIcon(scaledImage)); |
| | | } else { |
| | | closeButton.setText("关闭"); |
| | | } |
| | | } catch (Exception ex) { |
| | | closeButton.setText("关闭"); |
| | | System.err.println("无法加载关闭图标: " + ex.getMessage()); |
| | | } |
| | | closeButton.setContentAreaFilled(false); |
| | | closeButton.setBorder(null); |
| | | closeButton.setFocusPainted(false); |
| | | closeButton.setCursor(new Cursor(Cursor.HAND_CURSOR)); |
| | | closeButton.setToolTipText("关闭"); |
| | | closeButton.addActionListener(e -> dialog.dispose()); |
| | | |
| | | buttonPanel.add(copyButton); |
| | | buttonPanel.add(closeButton); |
| | | content.add(buttonPanel); |
| | | |
| | | dialog.pack(); |
| | | dialog.setLocationRelativeTo(this); |
| | | dialog.setVisible(true); |
| | | } |
| | | |
| | | private void checkForUpdates() { |
| | | // 模拟检查更新过程 |
| | | checkUpdateBtn.setEnabled(false); |