JavaFX实现XML视图指定文本区域可编辑的技术咨询
Got it, let's figure out how to build this JavaFX XML view where users can only edit the text inside specific tags like <TITLE> and <ARTIST>, without touching the XML tags themselves. The key here is to keep the XML structure intact visually while restricting edit access—no splitting the content into separate fields. Here's a practical approach:
We'll use JavaFX's TextFlow component combined with editable TextField controls to mimic the XML structure. Fixed XML tags will be rendered as non-editable Text nodes, while the editable content inside specified tags will live in stylized TextFields that blend seamlessly with the rest of the XML text. This way, the whole thing looks like a single XML block, but only the intended parts are editable.
- 1. Parse the XML: Use Java's DOM parser to split the XML into its constituent parts—opening tags, editable text content, closing tags, and whitespace/indentation. This avoids error-prone manual string splitting.
- 2. Build the TextFlow Layout: Traverse the parsed XML nodes, adding non-editable
Textnodes for tags and indentation, andTextFields for the editable content. - 3. Style for XML Authenticity: Apply syntax-highlighting styles (like blue for tags) and tweak the
TextFields to look like regular text (transparent background, no borders) so they don't break the XML visual flow. - 4. Reconstruct the XML: When you need to save the changes, concatenate all the
Textnode content andTextFieldvalues to rebuild the complete XML string.
import javafx.application.Application; import javafx.scene.Scene; import javafx.scene.control.TextField; import javafx.scene.layout.TextFlow; import javafx.scene.text.Text; import javafx.stage.Stage; import org.w3c.dom.Document; import org.w3c.dom.Element; import org.w3c.dom.Node; import org.w3c.dom.NodeList; import javax.xml.parsers.DocumentBuilder; import javax.xml.parsers.DocumentBuilderFactory; import java.io.ByteArrayInputStream; public class EditableXmlView extends Application { @Override public void start(Stage stage) { // Your sample XML content String xmlContent = "<CD>\n" + " <TITLE>Empire Burlesque</TITLE>\n" + " <ARTIST>Bob Dylan</ARTIST>\n" + " <COUNTRY>USA</COUNTRY>\n" + " <COMPANY>Columbia</COMPANY>\n" + " <PRICE>10.90</PRICE>\n" + " <YEAR>1985</YEAR>\n" + "</CD>"; TextFlow xmlDisplay = new TextFlow(); xmlDisplay.setStyle("-fx-padding: 12; -fx-font-family: monospace; -fx-font-size: 14px;"); try { // Parse the XML to extract tags and content DocumentBuilderFactory factory = DocumentBuilderFactory.newInstance(); DocumentBuilder builder = factory.newDocumentBuilder(); Document doc = builder.parse(new ByteArrayInputStream(xmlContent.getBytes())); doc.getDocumentElement().normalize(); // Process the root node and its children processXmlElement(doc.getDocumentElement(), xmlDisplay, 2); } catch (Exception e) { e.printStackTrace(); } Scene scene = new Scene(xmlDisplay, 450, 350); stage.setTitle("Editable XML View"); stage.setScene(scene); stage.show(); } private void processXmlElement(Element element, TextFlow textFlow, int indent) { // Add indentation for readability textFlow.getChildren().add(new Text(" ".repeat(indent))); // Add opening tag (non-editable) Text openingTag = new Text("<" + element.getTagName() + ">"); openingTag.setStyle("-fx-fill: #0066cc;"); // Blue color for tags textFlow.getChildren().add(openingTag); // Add editable content for the tag NodeList childNodes = element.getChildNodes(); for (int i = 0; i < childNodes.getLength(); i++) { Node child = childNodes.item(i); if (child.getNodeType() == Node.TEXT_NODE) { String content = child.getTextContent().trim(); if (!content.isEmpty()) { TextField editableField = new TextField(content); // Style the text field to blend with XML text editableField.setStyle("-fx-background-color: transparent; -fx-border-width: 0; " + "-fx-font-family: monospace; -fx-font-size: 14px;"); textFlow.getChildren().add(editableField); } } } // Add closing tag (non-editable) Text closingTag = new Text("</" + element.getTagName() + ">"); closingTag.setStyle("-fx-fill: #0066cc;"); textFlow.getChildren().add(closingTag); // Add line break after each element textFlow.getChildren().add(new Text("\n")); // Recursively process child elements NodeList childElements = element.getElementsByTagName("*"); for (int i = 0; i < childElements.getLength(); i++) { processXmlElement((Element) childElements.item(i), textFlow, indent + 2); } } public static void main(String[] args) { launch(args); } }
- XML Parsing: Using DOM ensures we accurately identify tags and their content, avoiding bugs from manual string manipulation.
- Seamless Styling: The
TextFields are styled to look like regular text, so users perceive the entire block as a single XML document. - Indentation Handling: We add space
Textnodes to maintain XML's indentation structure, keeping the content readable. - Edit Restriction: Only the text inside tags is placed in editable controls—tags themselves are non-editable
Textnodes, so users can't modify them accidentally.
内容的提问来源于stack exchange,提问作者user9483860

