我正在使用javafx设计自定义XML视图。 想象一下以下的XML。
<CD>
<TITLE>Empire Burlesque</TITLE>
<ARTIST>Bob Dylan</ARTIST>
<COUNTRY>USA</COUNTRY>
<COMPANY>Columbia</COMPANY>
<PRICE>10.90</PRICE>
<YEAR>1985</YEAR>
</CD>
现在我希望用户能够编辑标题,艺术家等,而无需他能够更改XML的其余部分。 请注意,我的目标是使用XML样式实现此目的,并且不要向用户显示输入,对话框。
我是如何实现这一目标的?
答案 0 :(得分:2)
您可以使用带有正则表达式过滤器的TextFormatter
来确保格式:
这只是一个小例子:(您应该根据需要调整正则表达式)
TextArea ta = new TextArea();
ta.setText("<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>");
UnaryOperator<Change> filter = c -> {
if(c.getControlNewText().matches("<CD>\\n <TITLE>.*</TITLE>\\n <ARTIST>.*</ARTIST>\\n <COUNTRY>.*</COUNTRY>\\n <COMPANY>.*</COMPANY>\\n <PRICE>[0-9]*\\.?[0-9]*</PRICE>\\n <YEAR>[0-9]{0,4}</YEAR>\\n</CD>")) {
return c;
}
// The new input doesn't match the regex and gets discarded
return null;
};
ta.setTextFormatter(new TextFormatter<String>(filter));
答案 1 :(得分:1)
您可以使用TextFlow组件来实现此目的。
它的工作原理是将对象传递给TextFlow
,例如TextField
,Text
等。
您可以为每个对象添加自定义样式。
现在,您的XML标题可以是Text
个对象,例如TextField
个。
然后,您可以选择要添加到TextField
的{{1}}对象是否可编辑。例如:
TextFlow
答案 2 :(得分:1)
您可以自行为xml布局,其中{/ 1}}节点用于开始/结束标记,Text
用于文本内容:
TextField
String input = "<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>";
XMLInputFactory inputFactory = XMLInputFactory.newInstance();
inputFactory.setProperty(XMLInputFactory.IS_COALESCING, Boolean.TRUE);
XMLStreamReader reader = inputFactory.createXMLStreamReader(new ByteArrayInputStream(input.getBytes()));
List<List<Node>> currentChildren = new ArrayList<>();
currentChildren.add(new ArrayList<>(1));
String text = null;
int depth = 0;
final Insets insets = new Insets(0, 0, 0, 20);
boolean hasChildren = false;
while (reader.hasNext()) {
switch (reader.next()) {
case XMLStreamConstants.START_ELEMENT:
depth++;
hasChildren = false;
currentChildren.add(new ArrayList<>());
break;
case XMLStreamConstants.CHARACTERS:
text = reader.getText();
break;
case XMLStreamConstants.END_ELEMENT:
String suffix = reader.getName().getLocalPart() + ">";
if (hasChildren) {
// element group
VBox vbox = new VBox(new Text("<" + suffix));
for (Node n : currentChildren.get(depth)) {
VBox.setMargin(n, insets);
}
vbox.getChildren().addAll(currentChildren.get(depth));
vbox.getChildren().add(new Text("</" + suffix));
currentChildren.get(depth - 1).add(vbox);
} else {
// text element
TextField textField = new TextField(text);
textField.setMinWidth(Region.USE_PREF_SIZE);
textField.setMaxWidth(Region.USE_PREF_SIZE);
// keep size of TextField large enough to contain all the text
ChangeListener<String> listener = new ChangeListener<String>() {
private final Text measureElement = new Text();
{
measureElement.setFont(Font.font("monospaced"));
}
@Override
public void changed(ObservableValue<? extends String> observable, String oldValue, String newValue) {
measureElement.setText(newValue);
textField.setPrefWidth(measureElement.getLayoutBounds().getWidth() + 2);
}
};
listener.changed(null, null, text);
textField.textProperty().addListener(listener);
HBox hbox = new HBox(new Text('<' + suffix), textField, new Text("</" + suffix));
currentChildren.get(depth - 1).add(hbox);
hasChildren = true;
text = null;
}
currentChildren.remove(depth);
depth--;
break;
}
}
VBox root = (VBox) currentChildren.get(0).get(0);
root.getStyleClass().add("xml-editor");