You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Java游戏XML关卡编辑器:实现用户自定义文件路径的问题

解决Java XML编辑器的文件路径自定义问题

当前代码的核心问题是XML文档在程序启动时就通过硬编码路径加载,无法响应后续用户选择的新文件。以下是重构后的完整实现,支持用户自定义XML文件路径:

import javax.swing.*;
import javax.xml.parsers.DocumentBuilder;
import javax.xml.parsers.DocumentBuilderFactory;
import javax.xml.transform.OutputKeys;
import javax.xml.transform.Transformer;
import javax.xml.transform.TransformerFactory;
import javax.xml.transform.dom.DOMSource;
import javax.xml.transform.stream.StreamResult;
import java.awt.*;
import java.io.File;
import org.w3c.dom.Document;
import org.w3c.dom.Element;

public class MapEdit {
    // 类成员变量,存储当前选中的文件和XML文档
    private File selectedFile;
    private Document xmlDoc;
    private Element xmlRoot;

    public static void main(String[] args) {
        // 在事件调度线程中启动UI,符合Swing规范
        SwingUtilities.invokeLater(MapEdit::new);
    }

    private MapEdit() {
        JFrame frame = new JFrame("Map Size Editor");
        frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
        frame.setMinimumSize(new Dimension(500, 250));

        // 文件选择面板
        JPanel filePanel = new JPanel(new BorderLayout(5, 5));
        JTextField filePathField = new JTextField();
        filePathField.setEditable(false);
        JButton browseBtn = new JButton("Browse XML File");
        filePanel.add(new JLabel("Target XML File: "), BorderLayout.WEST);
        filePanel.add(filePathField, BorderLayout.CENTER);
        filePanel.add(browseBtn, BorderLayout.EAST);

        // 高度设置面板
        JPanel heightPanel = new JPanel(new FlowLayout(FlowLayout.LEFT));
        heightPanel.add(new JLabel("Rows of tiles to add (height): "));
        JTextField heightInput = new JTextField(10);
        heightPanel.add(heightInput);

        // 宽度设置面板
        JPanel widthPanel = new JPanel(new FlowLayout(FlowLayout.LEFT));
        widthPanel.add(new JLabel("Rows of tiles to add (width): "));
        JTextField widthInput = new JTextField(10);
        widthPanel.add(widthInput);

        // 操作按钮面板
        JPanel buttonPanel = new JPanel(new FlowLayout(FlowLayout.CENTER));
        JButton setSizeButton = new JButton("Set Size");
        buttonPanel.add(setSizeButton);

        // 文件选择按钮监听
        browseBtn.addActionListener(e -> {
            JFileChooser fileChooser = new JFileChooser();
            fileChooser.setFileFilter(new javax.swing.filechooser.FileNameExtensionFilter("XML Files", "xml"));
            int result = fileChooser.showOpenDialog(frame);
            if (result == JFileChooser.APPROVE_OPTION) {
                selectedFile = fileChooser.getSelectedFile();
                filePathField.setText(selectedFile.getAbsolutePath());
                // 加载XML文档
                loadXmlDocument();
            }
        });

        // 设置尺寸按钮监听
        setSizeButton.addActionListener(e -> {
            // 校验文件是否已加载
            if (xmlDoc == null || xmlRoot == null) {
                JOptionPane.showMessageDialog(frame, "Please select an XML file first!", "Error", JOptionPane.ERROR_MESSAGE);
                return;
            }

            // 校验输入是否合法
            String heightText = heightInput.getText().trim();
            String widthText = widthInput.getText().trim();
            if (heightText.isEmpty() || widthText.isEmpty()) {
                JOptionPane.showMessageDialog(frame, "Please enter valid numbers for height and width!", "Error", JOptionPane.ERROR_MESSAGE);
                return;
            }

            try {
                int addHeight = Integer.parseInt(heightText);
                int addWidth = Integer.parseInt(widthText);

                // 更新XML属性
                float currentHeight = Float.parseFloat(xmlRoot.getAttribute("height"));
                float newHeight = currentHeight + (addHeight * 256);
                xmlRoot.setAttribute("height", String.valueOf(newHeight));

                float currentWidth = Float.parseFloat(xmlRoot.getAttribute("width"));
                float newWidth = currentWidth + (addWidth * 256);
                xmlRoot.setAttribute("width", String.valueOf(newWidth));

                // 保存修改后的XML
                TransformerFactory transformerFactory = TransformerFactory.newInstance();
                Transformer transformer = transformerFactory.newTransformer();
                transformer.setOutputProperty(OutputKeys.INDENT, "yes");
                DOMSource source = new DOMSource(xmlDoc);
                StreamResult result = new StreamResult(selectedFile);
                transformer.transform(source, result);

                JOptionPane.showMessageDialog(frame, "Changes saved successfully!", "Success", JOptionPane.INFORMATION_MESSAGE);
            } catch (NumberFormatException ex) {
                JOptionPane.showMessageDialog(frame, "Please enter valid integers!", "Error", JOptionPane.ERROR_MESSAGE);
            } catch (Exception ex) {
                JOptionPane.showMessageDialog(frame, "Failed to save changes: " + ex.getMessage(), "Error", JOptionPane.ERROR_MESSAGE);
                ex.printStackTrace();
            }
        });

        // 组装主面板
        JPanel contentPanel = new JPanel();
        contentPanel.setLayout(new BoxLayout(contentPanel, BoxLayout.Y_AXIS));
        contentPanel.setBorder(BorderFactory.createEmptyBorder(10, 10, 10, 10));
        contentPanel.add(filePanel);
        contentPanel.add(Box.createVerticalStrut(15));
        contentPanel.add(heightPanel);
        contentPanel.add(widthPanel);
        contentPanel.add(Box.createVerticalStrut(15));
        contentPanel.add(buttonPanel);

        frame.setContentPane(contentPanel);
        frame.pack();
        frame.setVisible(true);
    }

    // 加载XML文档的工具方法
    private void loadXmlDocument() {
        try {
            DocumentBuilderFactory dbf = DocumentBuilderFactory.newInstance();
            DocumentBuilder db = dbf.newDocumentBuilder();
            xmlDoc = db.parse(selectedFile);
            xmlRoot = xmlDoc.getDocumentElement();
            JOptionPane.showMessageDialog(null, "XML file loaded successfully!", "Success", JOptionPane.INFORMATION_MESSAGE);
        } catch (Exception ex) {
            JOptionPane.showMessageDialog(null, "Failed to load XML file: " + ex.getMessage(), "Error", JOptionPane.ERROR_MESSAGE);
            ex.printStackTrace();
            // 加载失败后重置变量
            xmlDoc = null;
            xmlRoot = null;
            selectedFile = null;
        }
    }
}

关键改动说明

  1. UI组件新增:添加文件选择文本框和浏览按钮,使用JFileChooser限制仅选择XML文件,提升操作准确性
  2. 变量作用域调整:将XML相关变量改为类成员,确保文件选择和编辑操作能共享状态
  3. XML延迟加载:仅在用户选择文件后才执行XML解析,彻底摆脱硬编码路径的限制
  4. 输入校验增强:添加文件加载状态校验、输入空值校验和数字格式校验,避免运行时异常
  5. 用户体验优化:使用JOptionPane提供直观的成功/错误提示,替代控制台输出
  6. Swing规范遵循:在事件调度线程中启动UI,避免线程安全问题

内容的提问来源于stack exchange,提问作者Remag Minecraft

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.31 23:15:33