JavaFX позволяет пользователю редактировать только определенные области текста

Я разрабатываю собственное представление XML с помощью javafx. Представьте себе следующий 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 и не предоставлять пользователю диалоговое окно ввода.

Есть идеи, как я могу этого добиться?

какой компонент JavaFX вы используете для представления xml?

helloworld 13.04.2018 11:51

Я использую TextArea.

user9483860 13.04.2018 11:52
Пользовательский скаляр GraphQL
Пользовательский скаляр GraphQL
Листовые узлы системы типов GraphQL называются скалярами. Достигнув скалярного типа, невозможно спуститься дальше по иерархии типов. Скалярный тип...
Как вычислять биты и понимать побитовые операторы в Java - объяснение с примерами
Как вычислять биты и понимать побитовые операторы в Java - объяснение с примерами
В компьютерном программировании биты играют важнейшую роль в представлении и манипулировании данными на двоичном уровне. Побитовые операции...
Поднятие тревоги для долго выполняющихся методов в Spring Boot
Поднятие тревоги для долго выполняющихся методов в Spring Boot
Приходилось ли вам сталкиваться с требованиями, в которых вас могли попросить поднять тревогу или выдать ошибку, когда метод Java занимает больше...
Полный курс Java для разработчиков веб-сайтов и приложений
Полный курс Java для разработчиков веб-сайтов и приложений
Получите сертификат Java Web и Application Developer, используя наш курс.
2
2
206
3
Перейти к ответу Данный вопрос помечен как решенный

Ответы 3

Вы можете использовать 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));

Вы можете добиться этого, используя компонент TextFlow.

Он работает, передавая объекты на ваш TextFlow, такие как TextField, Text и т. д.

Вы можете добавить индивидуальный стиль к каждому из этих объектов.

Теперь ваши заголовки XML могут быть, например, объектами Text, а ваши значения - объектами TextField.

Затем вы можете выбрать, можно ли редактировать объект TextField, который вы добавляете в TextFlow. Например:

Text field = new Text("one");
TextField value = new TextField("two");
value.setPrefWidth(value.getText().length()*12); // customize if needed
value.setStyle("-fx-fill: RED;-fx-font-weight:normal;"); // adding css
value.setEditable(false); // this field cannot be edited
textFlow.getChildren().addAll(field,value);
Ответ принят как подходящий

Вы можете самостоятельно создать макет для xml, который использует узлы 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");

Таблица стилей CSS

.xml-editor .text-field,
.xml-editor .text-field:focused {
    /* remove TextField border & background */
    -fx-focus-color: transparent;
    -fx-control-inner-background: transparent;
    -fx-faint-focus-color: transparent;
    -fx-text-box-border: transparent;
    -fx-text-fill: black;
    -fx-padding: 0;
    -fx-font-family: 'monospaced';
}

.xml-editor Text {
    -fx-font-family: 'monospaced';
}

Потрясающие! Прекрасно работает. Могу ли я использовать это в моем коде? Под какой лицензией находится ваш код? знак равно

user9483860 16.04.2018 08:02

Другие вопросы по теме