| | |
| | | import zhuye.MapRenderer; |
| | | import zhuye.Shouye; |
| | | import zhuye.buttonset; |
| | | import set.Setsys; |
| | | |
| | | import javax.swing.*; |
| | | import javax.swing.filechooser.FileNameExtensionFilter; |
| | | |
| | | import java.awt.*; |
| | | import java.awt.event.*; |
| | | import java.awt.geom.RoundRectangle2D; |
| | | import java.io.File; |
| | | import java.util.ArrayList; |
| | | import java.util.List; |
| | |
| | | */ |
| | | public class Sets extends JDialog { |
| | | private static final long serialVersionUID = 1L; |
| | | private static final int ROW_HEIGHT = 40; |
| | | private static final int ROW_SPACING = 25; |
| | | private static final int ROW_HEIGHT = 50; // 增加行高以适应分割线 |
| | | private static final int ITEM_PADDING = 16; // 列表项内边距 |
| | | |
| | | // 主题颜色 |
| | | private final Color THEME_COLOR; |
| | | private final Color BACKGROUND_COLOR = new Color(250, 250, 250); |
| | | private final Color PANEL_BACKGROUND = new Color(255, 255, 255); |
| | | private final Color BORDER_COLOR = new Color(220, 220, 220); |
| | | private final Color BACKGROUND_COLOR = new Color(245, 247, 250); // 更柔和的浅灰色背景 |
| | | private final Color PANEL_BACKGROUND = new Color(255, 255, 255); // 白色面板 |
| | | private final Color BORDER_COLOR = new Color(233, 236, 239); // 浅边框色 |
| | | private final Color DIVIDER_COLOR = new Color(233, 236, 239); // 分割线颜色 |
| | | |
| | | // 设置项组件 |
| | | private JLabel mowerIdLabel; |
| | |
| | | private JLabel firmwareVersionLabel; |
| | | private JLabel appVersionLabel; |
| | | private JLabel idleTrailDurationLabel; |
| | | private JLabel boundaryLengthVisibleLabel; |
| | | |
| | | private JButton mowerIdEditBtn; |
| | | private JButton baseStationIdEditBtn; |
| | | private JButton handheldEditBtn; |
| | | private JButton checkUpdateBtn; |
| | | private JButton systemDebugButton; |
| | | private JButton feedbackButton; |
| | | private JButton idleTrailEditBtn; |
| | | |
| | |
| | | setLocationRelativeTo(getParent()); |
| | | setResizable(false); |
| | | |
| | | // 创建主内容面板 |
| | | // 创建主内容面板(使用更柔和的浅灰色背景) |
| | | JPanel mainPanel = new JPanel(); |
| | | mainPanel.setLayout(new BoxLayout(mainPanel, BoxLayout.Y_AXIS)); |
| | | mainPanel.setLayout(new BorderLayout()); |
| | | mainPanel.setBackground(BACKGROUND_COLOR); |
| | | mainPanel.setBorder(BorderFactory.createEmptyBorder(20, 20, 20, 20)); |
| | | |
| | | // 创建设置项面板 |
| | | // 创建设置项面板(圆角白色面板) |
| | | JPanel settingsPanel = createSettingsPanel(); |
| | | |
| | | // 添加组件到主面板 |
| | | mainPanel.add(settingsPanel); |
| | | mainPanel.add(Box.createVerticalGlue()); |
| | | mainPanel.add(settingsPanel, BorderLayout.CENTER); |
| | | |
| | | add(mainPanel, BorderLayout.CENTER); |
| | | } |
| | | |
| | | private JPanel createSettingsPanel() { |
| | | // 创建圆角白色面板容器 |
| | | JPanel container = new JPanel() { |
| | | @Override |
| | | protected void paintComponent(Graphics g) { |
| | | Graphics2D g2d = (Graphics2D) g.create(); |
| | | g2d.setRenderingHint(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON); |
| | | g2d.setColor(PANEL_BACKGROUND); |
| | | // 绘制圆角矩形背景 |
| | | g2d.fillRoundRect(0, 0, getWidth(), getHeight(), 16, 16); |
| | | g2d.dispose(); |
| | | } |
| | | }; |
| | | container.setLayout(new BorderLayout()); |
| | | container.setOpaque(false); |
| | | |
| | | // 内容面板 |
| | | JPanel panel = new JPanel(); |
| | | panel.setLayout(new BoxLayout(panel, BoxLayout.Y_AXIS)); |
| | | panel.setBackground(PANEL_BACKGROUND); |
| | | panel.setBorder(BorderFactory.createCompoundBorder( |
| | | BorderFactory.createLineBorder(BORDER_COLOR), |
| | | BorderFactory.createEmptyBorder(20, 20, 20, 20) |
| | | )); |
| | | panel.setOpaque(false); |
| | | panel.setBorder(BorderFactory.createEmptyBorder(8, 0, 8, 0)); |
| | | |
| | | // 割草机编号 |
| | | JPanel mowerIdPanel = createSettingItemPanel("割草机编号", |
| | |
| | | formatIdleTrailDurationValue(), true); |
| | | idleTrailDurationLabel = (JLabel) idleTrailPanel.getClientProperty("valueLabel"); |
| | | idleTrailEditBtn = (JButton) idleTrailPanel.getClientProperty("editButton"); |
| | | |
| | | // 显示边界距离设置项 |
| | | JPanel boundaryLengthPanel = createBoundaryLengthPanel(); |
| | | boundaryLengthVisibleLabel = (JLabel) boundaryLengthPanel.getClientProperty("valueLabel"); |
| | | |
| | | JPanel feedbackPanel = createFeedbackPanel(); |
| | | |
| | | // APP版本 |
| | | JPanel appVersionPanel = createAppVersionPanel(); |
| | | |
| | | addRowWithSpacing(panel, mowerIdPanel); |
| | | addRowWithSpacing(panel, baseStationIdPanel); |
| | | addRowWithSpacing(panel, handheldPanel); |
| | | addRowWithSpacing(panel, simCardPanel); |
| | | addRowWithSpacing(panel, baseStationSimPanel); |
| | | addRowWithSpacing(panel, firmwarePanel); |
| | | addRowWithSpacing(panel, idleTrailPanel); |
| | | addRowWithSpacing(panel, feedbackPanel); |
| | | addRowWithSpacing(panel, appVersionPanel); |
| | | panel.add(createDebugPanel()); |
| | | // 添加设置项,使用分割线分隔 |
| | | addSettingItem(panel, mowerIdPanel, true); |
| | | addSettingItem(panel, baseStationIdPanel, true); |
| | | addSettingItem(panel, handheldPanel, true); |
| | | addSettingItem(panel, simCardPanel, true); |
| | | addSettingItem(panel, baseStationSimPanel, true); |
| | | addSettingItem(panel, firmwarePanel, true); |
| | | addSettingItem(panel, idleTrailPanel, true); |
| | | addSettingItem(panel, boundaryLengthPanel, true); |
| | | addSettingItem(panel, feedbackPanel, true); |
| | | addSettingItem(panel, appVersionPanel, false); // 最后一项不加分割线 |
| | | |
| | | return panel; |
| | | container.add(panel, BorderLayout.CENTER); |
| | | return container; |
| | | } |
| | | |
| | | /** |
| | | * 添加设置项(带分割线) |
| | | */ |
| | | private void addSettingItem(JPanel container, JPanel itemPanel, boolean showDivider) { |
| | | container.add(itemPanel); |
| | | if (showDivider) { |
| | | // 添加分割线 |
| | | JSeparator divider = new JSeparator(); |
| | | divider.setForeground(DIVIDER_COLOR); |
| | | divider.setMaximumSize(new Dimension(Integer.MAX_VALUE, 1)); |
| | | divider.setAlignmentX(Component.LEFT_ALIGNMENT); |
| | | container.add(divider); |
| | | } |
| | | } |
| | | |
| | | private String formatIdleTrailDurationValue() { |
| | |
| | | return seconds + "秒"; |
| | | } |
| | | |
| | | private void addRowWithSpacing(JPanel container, JPanel row) { |
| | | container.add(row); |
| | | container.add(Box.createRigidArea(new Dimension(0, ROW_SPACING))); |
| | | } |
| | | |
| | | private JPanel createSettingItemPanel(String title, String value, boolean editable) { |
| | | JPanel panel = new JPanel(new GridBagLayout()); |
| | | panel.setBackground(PANEL_BACKGROUND); |
| | | 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(); |
| | | |
| | |
| | | |
| | | private JPanel createAppVersionPanel() { |
| | | JPanel panel = new JPanel(new GridBagLayout()); |
| | | panel.setBackground(PANEL_BACKGROUND); |
| | | 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(); |
| | | |
| | |
| | | return panel; |
| | | } |
| | | |
| | | private JPanel createDebugPanel() { |
| | | JPanel panel = new JPanel(new GridBagLayout()); |
| | | panel.setBackground(PANEL_BACKGROUND); |
| | | 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)); |
| | | |
| | | GridBagConstraints gbc = new GridBagConstraints(); |
| | | |
| | | JLabel titleLabel = new JLabel("系统调试"); |
| | | titleLabel.setFont(new Font("微软雅黑", Font.BOLD, 14)); |
| | | titleLabel.setForeground(Color.BLACK); |
| | | titleLabel.setHorizontalAlignment(SwingConstants.RIGHT); |
| | | 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); |
| | | |
| | | Color darkerTheme = new Color( |
| | | Math.max(THEME_COLOR.getRed() - 20, 0), |
| | | Math.max(THEME_COLOR.getGreen() - 20, 0), |
| | | Math.max(THEME_COLOR.getBlue() - 20, 0)); |
| | | systemDebugButton = buttonset.createStyledButton("系统调试", darkerTheme); |
| | | systemDebugButton.setFont(new Font("微软雅黑", Font.PLAIN, 12)); |
| | | |
| | | gbc = new GridBagConstraints(); |
| | | gbc.gridx = 1; |
| | | gbc.gridy = 0; |
| | | gbc.weightx = 1.0; |
| | | gbc.anchor = GridBagConstraints.EAST; |
| | | panel.add(systemDebugButton, gbc); |
| | | |
| | | return panel; |
| | | } |
| | | |
| | | private JPanel createFeedbackPanel() { |
| | | JPanel panel = new JPanel(new GridBagLayout()); |
| | | panel.setBackground(PANEL_BACKGROUND); |
| | | 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(); |
| | | |
| | |
| | | return panel; |
| | | } |
| | | |
| | | /** |
| | | * 创建显示边界距离设置面板 |
| | | */ |
| | | private JPanel createBoundaryLengthPanel() { |
| | | 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); |
| | | 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); |
| | | |
| | | boundaryLengthVisibleLabel = new JLabel(setData.isBoundaryLengthVisible() ? "已开启" : "已关闭"); |
| | | boundaryLengthVisibleLabel.setFont(new Font("微软雅黑", Font.PLAIN, 14)); |
| | | boundaryLengthVisibleLabel.setForeground(Color.DARK_GRAY); |
| | | gbc = new GridBagConstraints(); |
| | | gbc.gridx = 1; |
| | | gbc.gridy = 0; |
| | | gbc.weightx = 1.0; |
| | | gbc.anchor = GridBagConstraints.EAST; |
| | | panel.add(boundaryLengthVisibleLabel, gbc); |
| | | |
| | | panel.putClientProperty("valueLabel", boundaryLengthVisibleLabel); |
| | | |
| | | // 创建切换按钮(使用图标) |
| | | JButton toggleBtn = createBoundaryLengthToggleButton(); |
| | | 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 createBoundaryLengthToggleButton() { |
| | | 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)); |
| | | |
| | | updateBoundaryLengthToggleButton(button); |
| | | |
| | | button.addActionListener(e -> toggleBoundaryLengthVisible(button)); |
| | | |
| | | return button; |
| | | } |
| | | |
| | | /** |
| | | * 更新边界距离切换按钮图标 |
| | | */ |
| | | private void updateBoundaryLengthToggleButton(JButton button) { |
| | | boolean isVisible = setData.isBoundaryLengthVisible(); |
| | | try { |
| | | String iconPath = isVisible ? "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(isVisible ? "开" : "关"); |
| | | } |
| | | } catch (Exception e) { |
| | | button.setIcon(null); |
| | | button.setText(isVisible ? "开" : "关"); |
| | | System.err.println("无法加载边界距离图标: " + e.getMessage()); |
| | | } |
| | | } |
| | | |
| | | /** |
| | | * 切换边界距离显示状态 |
| | | */ |
| | | private void toggleBoundaryLengthVisible(JButton button) { |
| | | boolean newValue = !setData.isBoundaryLengthVisible(); |
| | | setData.setBoundaryLengthVisible(newValue); |
| | | |
| | | // 保存到配置文件 |
| | | setData.updateProperty("boundaryLengthVisible", String.valueOf(newValue)); |
| | | |
| | | // 更新UI |
| | | if (boundaryLengthVisibleLabel != null) { |
| | | boundaryLengthVisibleLabel.setText(newValue ? "已开启" : "已关闭"); |
| | | } |
| | | updateBoundaryLengthToggleButton(button); |
| | | |
| | | // 通知MapRenderer更新 |
| | | Shouye shouye = Shouye.getInstance(); |
| | | if (shouye != null) { |
| | | MapRenderer renderer = shouye.getMapRenderer(); |
| | | if (renderer != null) { |
| | | renderer.setBoundaryLengthVisible(newValue); |
| | | } |
| | | } |
| | | } |
| | | |
| | | private JButton createEditButton() { |
| | | JButton button = new JButton(); |
| | | try { |
| | |
| | | setData.initializeFromProperties(); |
| | | baseStation.load(); |
| | | updateDisplay(); |
| | | // 加载并应用上次保存的视图中心坐标 |
| | | loadViewCenterFromProperties(); |
| | | } |
| | | |
| | | /** |
| | | * 从配置文件加载视图中心坐标并应用到MapRenderer |
| | | */ |
| | | private void loadViewCenterFromProperties() { |
| | | Shouye shouye = Shouye.getInstance(); |
| | | if (shouye == null) { |
| | | return; |
| | | } |
| | | MapRenderer renderer = shouye.getMapRenderer(); |
| | | if (renderer == null) { |
| | | return; |
| | | } |
| | | |
| | | // 从配置文件读取视图中心坐标 |
| | | String viewCenterXValue = Setsys.getPropertyValue("viewCenterX"); |
| | | String viewCenterYValue = Setsys.getPropertyValue("viewCenterY"); |
| | | |
| | | double savedTranslateX = 0.0; |
| | | double savedTranslateY = 0.0; |
| | | |
| | | if (viewCenterXValue != null && !viewCenterXValue.trim().isEmpty()) { |
| | | try { |
| | | savedTranslateX = Double.parseDouble(viewCenterXValue.trim()); |
| | | } catch (NumberFormatException e) { |
| | | savedTranslateX = 0.0; |
| | | } |
| | | } |
| | | if (viewCenterYValue != null && !viewCenterYValue.trim().isEmpty()) { |
| | | try { |
| | | savedTranslateY = Double.parseDouble(viewCenterYValue.trim()); |
| | | } catch (NumberFormatException e) { |
| | | savedTranslateY = 0.0; |
| | | } |
| | | } |
| | | |
| | | // 应用视图中心坐标(保持当前缩放比例) |
| | | double currentScale = renderer.getScale(); |
| | | renderer.setViewTransform(currentScale, savedTranslateX, savedTranslateY); |
| | | } |
| | | |
| | | private void updateDisplay() { |
| | |
| | | idleTrailDurationLabel.setText(formatIdleTrailDurationValue()); |
| | | } |
| | | |
| | | // 更新显示边界距离状态 |
| | | if (boundaryLengthVisibleLabel != null) { |
| | | boundaryLengthVisibleLabel.setText(setData.isBoundaryLengthVisible() ? "已开启" : "已关闭"); |
| | | } |
| | | // 更新切换按钮图标 |
| | | JPanel boundaryLengthPanel = (JPanel) boundaryLengthVisibleLabel.getParent(); |
| | | if (boundaryLengthPanel != null) { |
| | | JButton toggleBtn = (JButton) boundaryLengthPanel.getClientProperty("toggleButton"); |
| | | if (toggleBtn != null) { |
| | | updateBoundaryLengthToggleButton(toggleBtn); |
| | | } |
| | | } |
| | | |
| | | // 更新APP版本显示 |
| | | if (appVersionLabel != null) { |
| | | appVersionLabel.setText(setData.getAppVersion() != null ? |
| | |
| | | feedbackButton.addActionListener(e -> showFeedbackDialog()); |
| | | } |
| | | |
| | | if (systemDebugButton != null) { |
| | | systemDebugButton.addActionListener(e -> openSystemDebugDialog()); |
| | | } |
| | | |
| | | if (idleTrailEditBtn != null) { |
| | | idleTrailEditBtn.addActionListener(e -> editIdleTrailDuration()); |
| | | } |
| | |
| | | timer.setRepeats(false); |
| | | timer.start(); |
| | | } |
| | | |
| | | private void openSystemDebugDialog() { |
| | | debug dialog = new debug(this, THEME_COLOR); |
| | | dialog.setLocationRelativeTo(this); |
| | | dialog.setVisible(true); |
| | | } |
| | | |
| | | @Override |
| | | public void setVisible(boolean visible) { |