package dikuai;
|
|
import javax.swing.*;
|
import java.awt.*;
|
import java.awt.event.*;
|
import java.util.HashMap;
|
import java.util.Map;
|
import java.util.List;
|
|
import set.Setsys;
|
import ui.UIConfig;
|
import zhuye.Coordinate;
|
import lujing.WangfanpathJisuan;
|
import publicway.buttonset;
|
|
/**
|
* 绘制往返路径页面
|
* 参考新增地块步骤2,用于绘制往返点路径
|
*/
|
public class Huizhiwanfanpath extends JDialog {
|
private static final long serialVersionUID = 1L;
|
|
// 主题颜色 - 优化配色方案
|
private final Color PRIMARY_COLOR = new Color(46, 139, 87);
|
private final Color PRIMARY_LIGHT = new Color(232, 245, 233);
|
private final Color PRIMARY_DARK = new Color(30, 107, 69);
|
private final Color WHITE = Color.WHITE;
|
private final Color LIGHT_GRAY = new Color(248, 249, 250);
|
private final Color TEXT_COLOR = new Color(33, 37, 41);
|
private final Color LIGHT_TEXT = new Color(108, 117, 125);
|
private final Color BORDER_COLOR = new Color(222, 226, 230);
|
private final Color ERROR_COLOR = new Color(220, 53, 69);
|
|
// 主面板
|
private JPanel mainPanel;
|
private Map<String, JPanel> drawingOptionPanels = new HashMap<>();
|
|
// 选项状态
|
private JPanel selectedOptionPanel = null;
|
private JButton startEndDrawingBtn;
|
private boolean isDrawing = false;
|
private boolean hasDrawnPath = false; // 是否已经绘制过路径
|
private JLabel pathCountLabel;
|
private JLabel drawingMethodHintLabel; // 绘制方式提示标签
|
private JButton generatePathBtn; // 生成路径按钮
|
private JButton previewBtn; // 预览按钮
|
private JButton saveBtn; // 保存按钮
|
private JPanel actionButtonsPanel; // 操作按钮面板
|
|
// 地块信息
|
private Dikuai currentDikuai;
|
private boolean isRefreshMode = false; // 是否重新绘制模式
|
private String optimizedPathCoordinates = null; // 优化后的路径坐标
|
private JTextArea rawCoordinatesArea; // 原始坐标文本域
|
private JTextArea optimizedCoordinatesArea; // 计算后坐标文本域
|
private JLabel rawCoordinatesLabel; // 原始坐标标题
|
private JLabel optimizedCoordinatesLabel; // 优化后坐标标题
|
|
public Huizhiwanfanpath(Window parent, Dikuai dikuai) {
|
this(parent, dikuai, false);
|
}
|
|
public Huizhiwanfanpath(Window parent, Dikuai dikuai, boolean isRefresh) {
|
super(parent, "绘制往返路径", Dialog.ModalityType.APPLICATION_MODAL);
|
this.currentDikuai = dikuai;
|
this.isRefreshMode = isRefresh;
|
initializeUI();
|
}
|
|
private void initializeUI() {
|
setLayout(new BorderLayout());
|
setBackground(WHITE);
|
|
// 统一使用 6.5 寸竖屏适配尺寸
|
setSize(UIConfig.DIALOG_WIDTH, UIConfig.DIALOG_HEIGHT);
|
setLocationRelativeTo(getParent());
|
setResizable(false);
|
|
createMainPanel();
|
add(mainPanel, BorderLayout.CENTER);
|
}
|
|
private void createMainPanel() {
|
mainPanel = new JPanel();
|
mainPanel.setLayout(new BoxLayout(mainPanel, BoxLayout.Y_AXIS));
|
mainPanel.setBackground(WHITE);
|
mainPanel.setBorder(BorderFactory.createEmptyBorder(20, 20, 20, 20));
|
|
// 步骤标题 - 左对齐(去掉"绘制边界"文字)
|
// JLabel stepTitle = new JLabel("步骤1:");
|
// stepTitle.setFont(new Font("微软雅黑", Font.BOLD, 20));
|
// stepTitle.setForeground(TEXT_COLOR);
|
// stepTitle.setAlignmentX(Component.LEFT_ALIGNMENT);
|
// mainPanel.add(stepTitle);
|
// mainPanel.add(Box.createRigidArea(new Dimension(0, 20)));
|
|
// 步骤说明
|
JPanel instructionPanel = createInstructionPanel(
|
"请选择绘制往返路径的方式。割草机绘制需要驾驶割草机沿路径行驶," +
|
"手持设备绘制则使用便携设备标记路径点。"
|
);
|
instructionPanel.setAlignmentX(Component.LEFT_ALIGNMENT);
|
mainPanel.add(instructionPanel);
|
mainPanel.add(Box.createRigidArea(new Dimension(0, 25)));
|
|
// 绘制方式选择
|
JLabel methodLabel = new JLabel("选择绘制方式");
|
methodLabel.setFont(new Font("微软雅黑", Font.BOLD, 16));
|
methodLabel.setForeground(TEXT_COLOR);
|
methodLabel.setAlignmentX(Component.LEFT_ALIGNMENT);
|
|
mainPanel.add(methodLabel);
|
mainPanel.add(Box.createRigidArea(new Dimension(0, 15)));
|
|
// 绘制选项面板 - 垂直布局以完整显示图标
|
JPanel optionsPanel = new JPanel();
|
optionsPanel.setLayout(new BoxLayout(optionsPanel, BoxLayout.Y_AXIS));
|
optionsPanel.setBackground(WHITE);
|
optionsPanel.setAlignmentX(Component.LEFT_ALIGNMENT);
|
|
// 割草机绘制选项
|
JPanel mowerOption = createDrawingOption("🚜", "割草机绘制",
|
"", "mower");
|
mowerOption.setAlignmentX(Component.LEFT_ALIGNMENT);
|
mowerOption.setBorder(BorderFactory.createLineBorder(BORDER_COLOR, 2));
|
|
// 手持设备绘制选项
|
JPanel handheldOption = createDrawingOption("📱", "手持设备绘制",
|
"", "handheld");
|
handheldOption.setAlignmentX(Component.LEFT_ALIGNMENT);
|
handheldOption.setBorder(BorderFactory.createLineBorder(BORDER_COLOR, 2));
|
|
optionsPanel.add(mowerOption);
|
optionsPanel.add(Box.createRigidArea(new Dimension(0, 15)));
|
optionsPanel.add(handheldOption);
|
|
mainPanel.add(optionsPanel);
|
mainPanel.add(Box.createRigidArea(new Dimension(0, 30)));
|
|
// 绘制方式提示标签(如果没有选择绘制方式时显示)
|
// 提示文本:提醒先选择绘制方式再开始
|
drawingMethodHintLabel = new JLabel("请先选择绘制方式再点击开始绘制");
|
drawingMethodHintLabel.setFont(new Font("微软雅黑", Font.PLAIN, 14));
|
drawingMethodHintLabel.setForeground(ERROR_COLOR);
|
drawingMethodHintLabel.setAlignmentX(Component.LEFT_ALIGNMENT);
|
drawingMethodHintLabel.setBorder(BorderFactory.createEmptyBorder(0, 0, 10, 0));
|
drawingMethodHintLabel.setVisible(false);
|
mainPanel.add(drawingMethodHintLabel);
|
|
// 开始/结束绘制按钮
|
startEndDrawingBtn = createPrimaryButton("开始绘制", 16);
|
startEndDrawingBtn.setAlignmentX(Component.LEFT_ALIGNMENT);
|
startEndDrawingBtn.setMaximumSize(new Dimension(400, 55));
|
startEndDrawingBtn.setEnabled(true); // 初始启用,以便点击时检查是否选择了绘制方式
|
|
startEndDrawingBtn.addActionListener(e -> toggleDrawing());
|
|
mainPanel.add(startEndDrawingBtn);
|
|
// 原始坐标显示区域(重新绘制按钮下方)
|
rawCoordinatesLabel = new JLabel("路径原始坐标");
|
rawCoordinatesLabel.setFont(new Font("微软雅黑", Font.BOLD, 14));
|
rawCoordinatesLabel.setAlignmentX(Component.LEFT_ALIGNMENT);
|
rawCoordinatesLabel.setBorder(BorderFactory.createEmptyBorder(20, 0, 5, 0));
|
rawCoordinatesLabel.setVisible(false);
|
mainPanel.add(rawCoordinatesLabel);
|
|
rawCoordinatesArea = new JTextArea(3, 20);
|
rawCoordinatesArea.setFont(new Font("Consolas", Font.PLAIN, 12));
|
rawCoordinatesArea.setLineWrap(true);
|
rawCoordinatesArea.setWrapStyleWord(true);
|
rawCoordinatesArea.setEditable(false);
|
rawCoordinatesArea.setBorder(BorderFactory.createLineBorder(BORDER_COLOR));
|
|
JScrollPane rawScrollPane = new JScrollPane(rawCoordinatesArea);
|
rawScrollPane.setAlignmentX(Component.LEFT_ALIGNMENT);
|
rawScrollPane.setMaximumSize(new Dimension(400, 60)); // 限制高度
|
rawScrollPane.setBorder(BorderFactory.createEmptyBorder(0, 0, 0, 0)); // 去掉顶部间隔,由标签提供
|
rawScrollPane.setVisible(false); // 初始隐藏
|
mainPanel.add(rawScrollPane);
|
|
// 操作按钮面板(生成路径、预览、保存)
|
actionButtonsPanel = createActionButtonsPanel();
|
actionButtonsPanel.setAlignmentX(Component.LEFT_ALIGNMENT);
|
actionButtonsPanel.setVisible(false);
|
mainPanel.add(actionButtonsPanel);
|
|
// 计算后坐标显示区域(保存按钮下方)
|
optimizedCoordinatesLabel = new JLabel("优化后路径坐标");
|
optimizedCoordinatesLabel.setFont(new Font("微软雅黑", Font.BOLD, 14));
|
optimizedCoordinatesLabel.setAlignmentX(Component.LEFT_ALIGNMENT);
|
optimizedCoordinatesLabel.setBorder(BorderFactory.createEmptyBorder(20, 0, 5, 0));
|
optimizedCoordinatesLabel.setVisible(false);
|
mainPanel.add(optimizedCoordinatesLabel);
|
|
optimizedCoordinatesArea = new JTextArea(3, 20);
|
optimizedCoordinatesArea.setFont(new Font("Consolas", Font.PLAIN, 12));
|
optimizedCoordinatesArea.setLineWrap(true);
|
optimizedCoordinatesArea.setWrapStyleWord(true);
|
optimizedCoordinatesArea.setEditable(false);
|
optimizedCoordinatesArea.setBorder(BorderFactory.createLineBorder(BORDER_COLOR));
|
|
JScrollPane optimizedScrollPane = new JScrollPane(optimizedCoordinatesArea);
|
optimizedScrollPane.setAlignmentX(Component.LEFT_ALIGNMENT);
|
optimizedScrollPane.setMaximumSize(new Dimension(400, 60)); // 限制高度
|
optimizedScrollPane.setBorder(BorderFactory.createEmptyBorder(0, 0, 0, 0)); // 去掉顶部间隔,由标签提供
|
optimizedScrollPane.setVisible(false); // 初始隐藏
|
mainPanel.add(optimizedScrollPane);
|
|
mainPanel.add(Box.createVerticalGlue());
|
}
|
|
private JPanel createDrawingOption(String icon, String text, String description, String type) {
|
JPanel optionPanel = new JPanel(new BorderLayout(15, 0));
|
optionPanel.setBackground(WHITE);
|
optionPanel.setCursor(new Cursor(Cursor.HAND_CURSOR));
|
optionPanel.setBorder(BorderFactory.createEmptyBorder(20, 20, 20, 20));
|
optionPanel.setMaximumSize(new Dimension(500, 120));
|
|
// 图标区域
|
JLabel iconLabel;
|
if ("handheld".equals(type) || "mower".equals(type)) {
|
iconLabel = new JLabel();
|
iconLabel.setHorizontalAlignment(SwingConstants.CENTER);
|
iconLabel.setPreferredSize(new Dimension(80, 80));
|
String iconPath = "handheld".equals(type) ? "image/URT.png" : "image/mow.png";
|
ImageIcon rawIcon = new ImageIcon(iconPath);
|
if (rawIcon.getIconWidth() > 0 && rawIcon.getIconHeight() > 0) {
|
Image scaled = rawIcon.getImage().getScaledInstance(64, 64, Image.SCALE_SMOOTH);
|
iconLabel.setIcon(new ImageIcon(scaled));
|
} else {
|
iconLabel.setText(icon);
|
iconLabel.setFont(new Font("Segoe UI Emoji", Font.PLAIN, 48));
|
}
|
} else {
|
iconLabel = new JLabel(icon, JLabel.CENTER);
|
iconLabel.setFont(new Font("Segoe UI Emoji", Font.PLAIN, 48));
|
iconLabel.setPreferredSize(new Dimension(80, 80));
|
}
|
|
// 文本区域
|
JPanel textPanel = new JPanel(new GridBagLayout());
|
textPanel.setBackground(WHITE);
|
|
JLabel textLabel = new JLabel(text);
|
textLabel.setFont(new Font("微软雅黑", Font.BOLD, 16));
|
textLabel.setHorizontalAlignment(SwingConstants.CENTER);
|
textLabel.setVerticalAlignment(SwingConstants.CENTER);
|
|
GridBagConstraints gbc = new GridBagConstraints();
|
gbc.gridx = 0;
|
gbc.gridy = 0;
|
gbc.weightx = 1;
|
gbc.weighty = description == null || description.trim().isEmpty() ? 1 : 0;
|
gbc.fill = GridBagConstraints.HORIZONTAL;
|
gbc.anchor = GridBagConstraints.CENTER;
|
textPanel.add(textLabel, gbc);
|
|
if (description != null && !description.trim().isEmpty()) {
|
JLabel descLabel = new JLabel(description);
|
descLabel.setFont(new Font("微软雅黑", Font.PLAIN, 13));
|
descLabel.setForeground(LIGHT_TEXT);
|
descLabel.setHorizontalAlignment(SwingConstants.CENTER);
|
|
GridBagConstraints descGbc = new GridBagConstraints();
|
descGbc.gridx = 0;
|
descGbc.gridy = 1;
|
descGbc.weightx = 1;
|
descGbc.weighty = 1;
|
descGbc.fill = GridBagConstraints.HORIZONTAL;
|
descGbc.anchor = GridBagConstraints.CENTER;
|
textPanel.add(descLabel, descGbc);
|
}
|
|
optionPanel.putClientProperty("titleLabel", textLabel);
|
|
optionPanel.add(iconLabel, BorderLayout.WEST);
|
optionPanel.add(textPanel, BorderLayout.CENTER);
|
|
// 添加点击事件
|
optionPanel.addMouseListener(new MouseAdapter() {
|
@Override
|
public void mouseClicked(MouseEvent e) {
|
if (!optionPanel.isEnabled()) {
|
return;
|
}
|
if (selectDrawingOption(optionPanel, type, true)) {
|
startEndDrawingBtn.setEnabled(true); // 选择后启用按钮
|
// 隐藏提示文字
|
if (drawingMethodHintLabel != null) {
|
drawingMethodHintLabel.setVisible(false);
|
}
|
}
|
}
|
|
@Override
|
public void mouseEntered(MouseEvent e) {
|
if (optionPanel != selectedOptionPanel) {
|
optionPanel.setBackground(new Color(245, 245, 245));
|
}
|
}
|
|
@Override
|
public void mouseExited(MouseEvent e) {
|
if (optionPanel != selectedOptionPanel) {
|
optionPanel.setBackground(WHITE);
|
}
|
}
|
});
|
|
drawingOptionPanels.put(type, optionPanel);
|
return optionPanel;
|
}
|
|
private boolean selectDrawingOption(JPanel optionPanel, String type, boolean userTriggered) {
|
if (optionPanel == null) {
|
return false;
|
}
|
if (userTriggered && "handheld".equalsIgnoreCase(type) && !hasConfiguredHandheldMarker()) {
|
JOptionPane.showMessageDialog(this, "请先去系统设置添加便携打点器编号", "提示", JOptionPane.WARNING_MESSAGE);
|
return false;
|
}
|
|
// 重置之前选中的选项
|
if (selectedOptionPanel != null) {
|
selectedOptionPanel.setBorder(BorderFactory.createLineBorder(BORDER_COLOR, 2));
|
selectedOptionPanel.setBackground(WHITE);
|
Object oldTitle = selectedOptionPanel.getClientProperty("titleLabel");
|
if (oldTitle instanceof JLabel) {
|
((JLabel) oldTitle).setForeground(TEXT_COLOR);
|
}
|
}
|
|
// 设置新的选中状态
|
optionPanel.setBorder(BorderFactory.createLineBorder(PRIMARY_COLOR, 3));
|
optionPanel.setBackground(PRIMARY_LIGHT);
|
Object titleObj = optionPanel.getClientProperty("titleLabel");
|
if (titleObj instanceof JLabel) {
|
((JLabel) titleObj).setForeground(PRIMARY_COLOR);
|
}
|
selectedOptionPanel = optionPanel;
|
|
return true;
|
}
|
|
private boolean hasConfiguredHandheldMarker() {
|
String handheldId = Setsys.getPropertyValue("handheldMarkerId");
|
return handheldId != null && !handheldId.trim().isEmpty();
|
}
|
|
private void toggleDrawing() {
|
if (!isDrawing) {
|
// 检查是否选择了绘制方式
|
if (selectedOptionPanel == null) {
|
// 显示提示文字
|
if (drawingMethodHintLabel != null) {
|
drawingMethodHintLabel.setVisible(true);
|
}
|
return;
|
} else {
|
// 隐藏提示文字
|
if (drawingMethodHintLabel != null) {
|
drawingMethodHintLabel.setVisible(false);
|
}
|
}
|
|
// 如果是重新绘制,清空之前的路径点
|
if (hasDrawnPath || isRefreshMode) {
|
int confirm = JOptionPane.showConfirmDialog(this,
|
"重新绘制将清空之前的路径点,是否继续?",
|
"确认",
|
JOptionPane.YES_NO_OPTION);
|
if (confirm != JOptionPane.YES_OPTION) {
|
return;
|
}
|
// 清空之前的坐标
|
Coordinate.coordinates.clear();
|
lujing.SavaXyZuobiao.clearCoordinates(); // 清空工具类坐标
|
hasDrawnPath = false;
|
isRefreshMode = false;
|
optimizedPathCoordinates = null;
|
// 隐藏操作按钮
|
if (actionButtonsPanel != null) {
|
actionButtonsPanel.setVisible(false);
|
}
|
// 隐藏原始坐标和计算后坐标
|
if (rawCoordinatesArea != null && rawCoordinatesArea.getParent() instanceof JViewport) {
|
rawCoordinatesArea.getParent().getParent().setVisible(false);
|
rawCoordinatesArea.setText("");
|
}
|
if (optimizedCoordinatesArea != null && optimizedCoordinatesArea.getParent() instanceof JViewport) {
|
optimizedCoordinatesArea.getParent().getParent().setVisible(false);
|
optimizedCoordinatesArea.setText("");
|
}
|
// 重置保存按钮状态
|
if (saveBtn != null) {
|
saveBtn.setEnabled(false);
|
}
|
hidePathPointSummary();
|
}
|
|
if (!prepareDrawingSession()) {
|
return;
|
}
|
isDrawing = true;
|
// hidePathPointSummary();
|
Coordinate.setStartSaveGngga(true);
|
lujing.SavaXyZuobiao.startSaving(); // 开始保存坐标
|
startEndDrawingBtn.setText("结束绘制");
|
startEndDrawingBtn.setBackground(ERROR_COLOR);
|
updateOtherOptionsState(true);
|
|
if (!startDrawingPath()) {
|
Coordinate.setStartSaveGngga(false);
|
resetDrawingState();
|
}
|
} else {
|
// 用户在对话框内主动结束
|
isDrawing = false;
|
Coordinate.setStartSaveGngga(false);
|
startEndDrawingBtn.setText(hasDrawnPath ? "重新绘制" : "开始绘制");
|
startEndDrawingBtn.setBackground(PRIMARY_COLOR);
|
updateOtherOptionsState(false);
|
JOptionPane.showMessageDialog(this, "往返路径绘制已完成", "提示", JOptionPane.INFORMATION_MESSAGE);
|
// showPathPointSummary();
|
// 显示操作按钮
|
if (actionButtonsPanel != null) {
|
actionButtonsPanel.setVisible(true);
|
}
|
// 重置保存按钮状态(需要生成路径后才能保存)
|
if (saveBtn != null) {
|
saveBtn.setEnabled(false);
|
}
|
optimizedPathCoordinates = null; // 清空优化路径
|
hasDrawnPath = true;
|
}
|
}
|
|
private boolean prepareDrawingSession() {
|
if (currentDikuai == null) {
|
JOptionPane.showMessageDialog(this, "地块信息不存在", "提示", JOptionPane.WARNING_MESSAGE);
|
return false;
|
}
|
if (selectedOptionPanel == null) {
|
JOptionPane.showMessageDialog(this, "请选择绘制方式", "提示", JOptionPane.WARNING_MESSAGE);
|
return false;
|
}
|
// 清空之前的坐标
|
Coordinate.coordinates.clear();
|
return true;
|
}
|
|
private void updateOtherOptionsState(boolean disable) {
|
if (selectedOptionPanel == null) {
|
return;
|
}
|
Component[] components = selectedOptionPanel.getParent().getComponents();
|
for (Component comp : components) {
|
if (comp instanceof JPanel && comp != selectedOptionPanel) {
|
comp.setEnabled(!disable);
|
((JPanel) comp).setBackground(disable ? LIGHT_GRAY : WHITE);
|
}
|
}
|
}
|
|
private void resetDrawingState() {
|
isDrawing = false;
|
Coordinate.setStartSaveGngga(false);
|
startEndDrawingBtn.setText("开始绘制");
|
startEndDrawingBtn.setBackground(PRIMARY_COLOR);
|
updateOtherOptionsState(false);
|
// hidePathPointSummary();
|
}
|
|
private boolean startDrawingPath() {
|
// 获取选中的绘制方式
|
String method = null;
|
for (Map.Entry<String, JPanel> entry : drawingOptionPanels.entrySet()) {
|
if (entry.getValue() == selectedOptionPanel) {
|
method = entry.getKey();
|
break;
|
}
|
}
|
|
if ("mower".equals(method) || "handheld".equals(method)) {
|
zhuye.Shouye shouye = zhuye.Shouye.getInstance();
|
if (shouye == null) {
|
JOptionPane.showMessageDialog(this, "无法进入主页面,请稍后重试", "提示", JOptionPane.WARNING_MESSAGE);
|
return false;
|
}
|
|
// 创建完成绘制回调,返回到绘制页面
|
Runnable finishCallback = () -> {
|
SwingUtilities.invokeLater(() -> {
|
// 停止保存坐标
|
lujing.SavaXyZuobiao.pauseSaving();
|
|
// 恢复首页默认的暂停和结束按钮
|
// 这个在 stopReturnPathDrawing 中已经处理了
|
|
// 显示绘制页面
|
Window owner = SwingUtilities.getWindowAncestor(this);
|
if (owner == null) {
|
owner = (Window) SwingUtilities.getWindowAncestor(shouye);
|
}
|
if (owner != null) {
|
setLocationRelativeTo(owner);
|
}
|
|
// 重置绘制状态
|
isDrawing = false;
|
hasDrawnPath = true; // 标记已绘制过路径
|
startEndDrawingBtn.setText("重新绘制");
|
startEndDrawingBtn.setBackground(PRIMARY_COLOR);
|
startEndDrawingBtn.setEnabled(true); // 保持启用状态
|
updateOtherOptionsState(false);
|
|
// 显示原始坐标
|
if (rawCoordinatesArea != null) {
|
String rawCoords = lujing.SavaXyZuobiao.getCoordinatesString();
|
rawCoordinatesArea.setText(rawCoords);
|
if (rawCoordinatesArea.getParent() instanceof JViewport) {
|
rawCoordinatesArea.getParent().getParent().setVisible(true);
|
}
|
if (rawCoordinatesLabel != null) {
|
int count = 0;
|
if (rawCoords != null && !rawCoords.trim().isEmpty()) {
|
count = rawCoords.split(";").length;
|
}
|
rawCoordinatesLabel.setText("路径原始坐标 (共" + count + "个点)");
|
rawCoordinatesLabel.setVisible(true);
|
}
|
}
|
|
// 显示操作按钮
|
if (actionButtonsPanel != null) {
|
actionButtonsPanel.setVisible(true);
|
}
|
// 重置保存按钮状态(需要生成路径后才能保存)
|
if (saveBtn != null) {
|
saveBtn.setEnabled(false);
|
}
|
optimizedPathCoordinates = null; // 清空优化路径
|
|
// 强制刷新布局
|
if (mainPanel != null) {
|
mainPanel.revalidate();
|
mainPanel.repaint();
|
}
|
|
setVisible(true);
|
|
// 更新路径点计数
|
// showPathPointSummary();
|
|
// JOptionPane.showMessageDialog(this, "往返路径绘制已完成", "提示", JOptionPane.INFORMATION_MESSAGE);
|
});
|
};
|
|
// 启动往返路径绘制,传递是否为手持设备模式
|
boolean isHandheld = "handheld".equals(method);
|
if (!shouye.startReturnPathDrawing(finishCallback, isHandheld)) {
|
JOptionPane.showMessageDialog(this, "未能开始绘制,请确认设备状态和基准站设置后重试", "提示", JOptionPane.WARNING_MESSAGE);
|
return false;
|
}
|
|
// 显示首页的“结束绘制”悬浮按钮,并绑定结束逻辑
|
shouye.showEndDrawingButton(() -> {
|
// 停止绘制并执行完成回调(恢复到本页面并显示保存/预览等)
|
shouye.stopReturnPathDrawing();
|
zhuye.WangfanDraw drawer = shouye.getReturnPathDrawer();
|
if (drawer != null) {
|
drawer.executeFinishCallback();
|
}
|
// 关闭悬浮控制
|
shouye.hideEndDrawingButton();
|
});
|
|
setVisible(false);
|
return true;
|
}
|
return false;
|
}
|
|
/**
|
* 保存路径坐标(保存优化后的坐标,如果没有优化则保存原始坐标)
|
*/
|
private void savePathCoordinates() {
|
if (currentDikuai == null) {
|
return;
|
}
|
|
// 如果已经生成优化路径,使用优化后的坐标
|
String pathCoordinates = optimizedPathCoordinates;
|
if (pathCoordinates == null || pathCoordinates.trim().isEmpty()) {
|
// 如果没有优化路径,使用原始坐标点(X,Y格式,单位米)
|
pathCoordinates = buildXYCoordinatesString();
|
}
|
|
if (pathCoordinates == null || pathCoordinates.trim().isEmpty() || "-1".equals(pathCoordinates.trim())) {
|
JOptionPane.showMessageDialog(this, "没有可保存的路径坐标", "提示", JOptionPane.WARNING_MESSAGE);
|
return;
|
}
|
|
// 保存到地块
|
if (Dikuai.updateField(currentDikuai.getLandNumber(), "returnPathCoordinates", pathCoordinates)) {
|
// 同时保存原始坐标
|
String rawCoords = rawCoordinatesArea != null ? rawCoordinatesArea.getText() : "";
|
if (rawCoords != null && !rawCoords.trim().isEmpty()) {
|
Dikuai.updateField(currentDikuai.getLandNumber(), "returnPathRawCoordinates", rawCoords);
|
}
|
|
Dikuai.updateField(currentDikuai.getLandNumber(), "updateTime", getCurrentTime());
|
Dikuai.saveToProperties();
|
|
// 清空工具类坐标
|
lujing.SavaXyZuobiao.clearCoordinates();
|
|
JOptionPane.showMessageDialog(this, "路径已保存", "成功", JOptionPane.INFORMATION_MESSAGE);
|
} else {
|
JOptionPane.showMessageDialog(this, "保存失败", "错误", JOptionPane.ERROR_MESSAGE);
|
}
|
}
|
|
/**
|
* 构建X,Y坐标字符串(单位米,精确到小数点后2位)
|
*/
|
private String buildXYCoordinatesString() {
|
// 从 WangfanDraw 获取路径点(已经是X,Y坐标,单位米)
|
zhuye.Shouye shouye = zhuye.Shouye.getInstance();
|
if (shouye == null || shouye.getReturnPathDrawer() == null) {
|
return "-1";
|
}
|
|
List<java.awt.geom.Point2D.Double> points = shouye.getReturnPathDrawer().getPointsSnapshot();
|
if (points == null || points.isEmpty()) {
|
return "-1";
|
}
|
|
StringBuilder sb = new StringBuilder();
|
java.text.DecimalFormat xyFormat = new java.text.DecimalFormat("0.00");
|
|
for (java.awt.geom.Point2D.Double point : points) {
|
if (point == null) continue;
|
|
if (sb.length() > 0) {
|
sb.append(";");
|
}
|
sb.append(xyFormat.format(point.x)).append(",")
|
.append(xyFormat.format(point.y));
|
}
|
|
return sb.length() > 0 ? sb.toString() : "-1";
|
}
|
|
private double convertToDecimalDegree(String dmm, String direction) {
|
if (dmm == null || dmm.isEmpty()) {
|
return 0.0;
|
}
|
try {
|
int dotIndex = dmm.indexOf('.');
|
if (dotIndex == -1) {
|
return 0.0;
|
}
|
int degrees = Integer.parseInt(dmm.substring(0, dotIndex - 2));
|
double minutes = Double.parseDouble(dmm.substring(dotIndex - 2));
|
double decimal = degrees + minutes / 60.0;
|
if ("S".equals(direction) || "W".equals(direction)) {
|
decimal = -decimal;
|
}
|
return decimal;
|
} catch (Exception e) {
|
return 0.0;
|
}
|
}
|
|
private String getCurrentTime() {
|
java.text.SimpleDateFormat sdf = new java.text.SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
|
return sdf.format(new java.util.Date());
|
}
|
|
private JPanel createInstructionPanel(String text) {
|
JPanel instructionPanel = new JPanel(new BorderLayout());
|
instructionPanel.setBackground(PRIMARY_LIGHT);
|
instructionPanel.setBorder(BorderFactory.createCompoundBorder(
|
BorderFactory.createMatteBorder(0, 5, 0, 0, PRIMARY_COLOR),
|
BorderFactory.createEmptyBorder(12, 12, 12, 12)
|
));
|
instructionPanel.setMaximumSize(new Dimension(Integer.MAX_VALUE, 70));
|
|
JLabel iconLabel = new JLabel("💡");
|
iconLabel.setFont(new Font("Segoe UI Emoji", Font.PLAIN, 16));
|
iconLabel.setBorder(BorderFactory.createEmptyBorder(0, 0, 0, 10));
|
|
JTextArea instructionText = new JTextArea(text);
|
instructionText.setFont(new Font("微软雅黑", Font.PLAIN, 13));
|
instructionText.setForeground(TEXT_COLOR);
|
instructionText.setBackground(PRIMARY_LIGHT);
|
instructionText.setLineWrap(true);
|
instructionText.setWrapStyleWord(true);
|
instructionText.setEditable(false);
|
|
instructionPanel.add(iconLabel, BorderLayout.WEST);
|
instructionPanel.add(instructionText, BorderLayout.CENTER);
|
|
return instructionPanel;
|
}
|
|
private JButton createPrimaryButton(String text, int fontSize) {
|
JButton button = buttonset.createStyledButton(text, PRIMARY_COLOR);
|
button.setFont(new Font("微软雅黑", Font.BOLD, fontSize));
|
button.setBorder(BorderFactory.createCompoundBorder(
|
BorderFactory.createLineBorder(PRIMARY_DARK, 2),
|
BorderFactory.createEmptyBorder(12, 25, 12, 25)
|
));
|
button.setCursor(new Cursor(Cursor.HAND_CURSOR));
|
|
button.addMouseListener(new MouseAdapter() {
|
@Override
|
public void mouseEntered(MouseEvent e) {
|
if (button.isEnabled()) {
|
button.setBackground(PRIMARY_DARK);
|
}
|
}
|
|
@Override
|
public void mouseExited(MouseEvent e) {
|
if (button.isEnabled()) {
|
button.setBackground(PRIMARY_COLOR);
|
}
|
}
|
});
|
|
return button;
|
}
|
|
private void showPathPointSummary() {
|
if (pathCountLabel == null) {
|
return;
|
}
|
int count = Coordinate.coordinates != null ? Coordinate.coordinates.size() : 0;
|
pathCountLabel.setText("已采集到有效坐标点" + count + "个");
|
// pathCountLabel.setVisible(true);
|
}
|
|
private void hidePathPointSummary() {
|
if (pathCountLabel != null) {
|
// pathCountLabel.setVisible(false);
|
}
|
}
|
|
/**
|
* 创建操作按钮面板(生成路径、预览、保存)
|
*/
|
private JPanel createActionButtonsPanel() {
|
JPanel panel = new JPanel();
|
panel.setLayout(new BoxLayout(panel, BoxLayout.X_AXIS));
|
panel.setBackground(WHITE);
|
panel.setBorder(BorderFactory.createEmptyBorder(15, 0, 0, 0));
|
panel.setAlignmentX(Component.LEFT_ALIGNMENT);
|
|
// 生成路径按钮
|
generatePathBtn = createPrimaryButton("生成路径", 16);
|
generatePathBtn.setAlignmentX(Component.LEFT_ALIGNMENT);
|
generatePathBtn.addActionListener(e -> generatePath());
|
|
// 预览按钮
|
previewBtn = createPrimaryButton("预览", 16);
|
previewBtn.setAlignmentX(Component.LEFT_ALIGNMENT);
|
previewBtn.addActionListener(e -> previewPath());
|
|
// 保存按钮(初始不可用)
|
saveBtn = createPrimaryButton("保存", 16);
|
saveBtn.setAlignmentX(Component.LEFT_ALIGNMENT);
|
saveBtn.setEnabled(false); // 初始不可用,生成路径后才可点击
|
saveBtn.addActionListener(e -> savePath());
|
|
panel.add(generatePathBtn);
|
panel.add(Box.createHorizontalStrut(15));
|
panel.add(previewBtn);
|
panel.add(Box.createHorizontalStrut(15));
|
panel.add(saveBtn);
|
|
return panel;
|
}
|
|
/**
|
* 生成路径
|
*/
|
private void generatePath() {
|
// 获取路径点(从原始坐标文本域获取)
|
String pathStr = rawCoordinatesArea != null ? rawCoordinatesArea.getText() : "";
|
if (pathStr == null || pathStr.trim().isEmpty()) {
|
JOptionPane.showMessageDialog(this, "没有可用的路径点,请先完成绘制", "提示", JOptionPane.WARNING_MESSAGE);
|
return;
|
}
|
|
try {
|
// 调用 WangfanpathJisuan 优化路径
|
lujing.WangfanpathJisuan calculator = new lujing.WangfanpathJisuan();
|
// 设置输出精度为2位小数
|
lujing.WangfanpathJisuan.OptimizationConfig config = new lujing.WangfanpathJisuan.OptimizationConfig();
|
config.setOutputPrecision(2);
|
|
String optimizedPath = calculator.optimizePath(pathStr, config);
|
|
if (optimizedPath == null || optimizedPath.trim().isEmpty()) {
|
JOptionPane.showMessageDialog(this, "路径优化失败", "错误", JOptionPane.ERROR_MESSAGE);
|
return;
|
}
|
|
// 保存优化后的路径坐标
|
optimizedPathCoordinates = optimizedPath;
|
|
// 显示计算后坐标
|
if (optimizedCoordinatesArea != null) {
|
optimizedCoordinatesArea.setText(optimizedPath);
|
if (optimizedCoordinatesArea.getParent() instanceof JViewport) {
|
optimizedCoordinatesArea.getParent().getParent().setVisible(true);
|
}
|
if (optimizedCoordinatesLabel != null) {
|
int count = 0;
|
if (optimizedPath != null && !optimizedPath.trim().isEmpty()) {
|
count = optimizedPath.split(";").length;
|
}
|
optimizedCoordinatesLabel.setText("优化后路径坐标 (共" + count + "个点)");
|
optimizedCoordinatesLabel.setVisible(true);
|
}
|
}
|
|
// 启用保存按钮
|
if (saveBtn != null) {
|
saveBtn.setEnabled(true);
|
}
|
|
// 刷新界面
|
if (mainPanel != null) {
|
mainPanel.revalidate();
|
mainPanel.repaint();
|
}
|
} catch (Exception e) {
|
JOptionPane.showMessageDialog(this, "路径生成失败: " + e.getMessage(), "错误", JOptionPane.ERROR_MESSAGE);
|
}
|
}
|
|
/**
|
* 预览路径
|
*/
|
private void previewPath() {
|
if (optimizedPathCoordinates == null || optimizedPathCoordinates.trim().isEmpty()) {
|
JOptionPane.showMessageDialog(this, "请先生成路径", "提示", JOptionPane.WARNING_MESSAGE);
|
return;
|
}
|
|
zhuye.Shouye shouye = zhuye.Shouye.getInstance();
|
if (shouye != null) {
|
// 隐藏当前窗口
|
setVisible(false);
|
|
// 启动预览
|
shouye.startReturnPathPreview(optimizedPathCoordinates, () -> {
|
// 返回回调:显示当前窗口
|
setVisible(true);
|
});
|
}
|
}
|
|
/**
|
* 保存路径
|
*/
|
private void savePath() {
|
if (optimizedPathCoordinates == null || optimizedPathCoordinates.trim().isEmpty()) {
|
JOptionPane.showMessageDialog(this, "请先生成路径", "提示", JOptionPane.WARNING_MESSAGE);
|
return;
|
}
|
savePathCoordinates();
|
}
|
|
/**
|
* 显示绘制往返路径对话框
|
*/
|
public static void showDrawReturnPathDialog(Window parent, Dikuai dikuai) {
|
showDrawReturnPathDialog(parent, dikuai, false);
|
}
|
|
/**
|
* 显示绘制往返路径对话框
|
* @param parent 父窗口
|
* @param dikuai 地块信息
|
* @param isRefresh 是否重新绘制(如果已有坐标)
|
*/
|
public static void showDrawReturnPathDialog(Window parent, Dikuai dikuai, boolean isRefresh) {
|
Huizhiwanfanpath dialog = new Huizhiwanfanpath(parent, dikuai, isRefresh);
|
dialog.setVisible(true);
|
}
|
}
|