gpt4 book ai didi

swing - Javafx 替代 swing javax.swing.text.Document

转载 作者:行者123 更新时间:2023-12-03 07:50:42 30 4
gpt4 key购买 nike

我有一个 swing 应用程序,它覆盖 javax.swing.text.Document 以将基础文档的内容限制为某些字符和文本长度。我想将我的应用程序移植到 Javafx,但我不知道此类是否有 Javafx 等效项。有没有办法在Javafx中替换它?

我的类正在做的是包装文档以添加新功能(在我的情况下是有限的)。许多方法仅遵循我使用的底层文档,但其中一些方法增加了我的限制,这些限制是:

  • 行长度限制

  • 行数限制

  • 大写限制

  • 字符限制

    public class ConstrainedDocument implements Document {
    protected Document document = null;
    private boolean limitLength = false;
    private boolean limitLines = false;
    private int maxLength = -1;
    private int maxLines = -1;
    private boolean limitText = false;
    private String allowedText = null;
    private boolean uppercase = false;

    /**
    * Constructor.
    *
    * @param doc the document
    */
    public ConstrainedDocument(Document doc) {
    this.document = doc;
    }

    /**
    * Constructor.
    */
    public ConstrainedDocument() {
    this.document = new PlainDocument();
    }

    public Document getDocument() {
    return document;
    }

    /**
    * Limits the allowed length for each line of the document.
    *
    * @param maxLength the maximum line length
    */
    public void setMaximumLength(int maxLength) {
    this.maxLength = maxLength;
    this.limitLength = true;
    }

    /**
    * Limits the allowed number of lines for the document.
    *
    * @param maxLines the maximum number of lines
    */
    public void setMaximumLines(int maxLines) {
    this.maxLines = maxLines;
    this.limitLines = true;
    }

    /**
    * Limits the characters allowed to compose the document.
    *
    * @param allowedText the String defining the allowed characters
    */
    public void setAllowedText(String allowedText) {
    this.allowedText = allowedText;
    this.limitText = true;
    }

    /**
    * Forces only upper case.
    *
    * @param uppercase true if only upper case are forced
    */
    public void setUpperCase(boolean uppercase) {
    this.uppercase = uppercase;
    }

    /**
    * Resets all the limitations and settings for this document.
    */
    public void resetLimitations() {
    this.limitText = false;
    this.limitLength = false;
    this.limitLines = false;
    }

    /**
    * Returns the allowed length for each line of the document.
    *
    * @return the maximum line length
    */
    public int getMaximumLineLength() {
    return maxLength;
    }

    /**
    * Returns the allowed number of lines for the document.
    *
    * @return the maximum number of lines
    */
    public int getMaximumLines() {
    return maxLines;
    }

    /**
    * Returns true if the maximum length of the text is set.
    *
    * @return true if the maximum length of the text is set
    *
    * @see #getMaximumLineLength()
    */
    public boolean isLineLengthLimited() {
    return limitLength;
    }

    /**
    * Returns true if the number of allowed lines is limited.
    *
    * @return true if the maximum number of lines is set
    *
    * @see #getMaximumLines()
    */
    public boolean isLinesLimited() {
    return limitLines;
    }

    /**
    * Returns the characters allowed to compose the document.
    *
    * @return the allowed characters as a string
    */
    public String getAllowedText() {
    return allowedText;
    }

    /**
    * Returns true if the allowed characters are limited.
    *
    * @return true if the allowed characters are limited
    *
    * @see #getAllowedText()
    */
    public boolean isTextLimited() {
    return limitText;
    }

    /**
    * Returns true if the insertion is forced to upper case characters.
    *
    * @return true if the insertion is forced to upper case characters
    */
    public boolean isUpperCase() {
    return uppercase;
    }

    /**
    * Extends the remove method from the parent Document class to fire remove events
    * when lines are removed.
    */
    @Override
    public void remove(int offset, int length) throws BadLocationException {
    document.remove(offset, length);
    }

    /**
    * Extends the insertString method from the parent Document class. This adds :
    * <ul>
    * <li>the ability to force upper case characters insertion if the {@link #isUpperCase()}
    * property is set</li>
    * <li>the ability to block insertion of unauthorized characters if the {@link #isTextLimited()}
    * property is set. In that case, the text is limited to the {@link #getAllowedText()} characters</li>
    * <li>the ability to limit the number of lines if the {@link #isLinesLimited()} property is set. In
    * that case, the number of allowed lines is limited to {@link #getMaximumLines()}</li>
    * <li>the ability to limit the length of each line if the {@link #isLineLengthLimited()} property
    * is set. In that case, the length for each line is limited to {@link #getMaximumLineLength()}</li>
    * </ul>
    * <p>
    * It also fire insertion events when lines are inserted.</p>
    */
    @Override
    public void insertString(int offset, String inputStr, AttributeSet a) throws BadLocationException {
    String str = inputStr;
    // handle showSpaces, upper case and characters limitation
    if (uppercase || limitText) {
    StringBuilder buf = new StringBuilder();
    for (int i = 0; i < str.length(); i++) {
    char c = str.charAt(i);
    if (uppercase) {
    c = Character.toUpperCase(c);
    }
    if (limitText) {
    if (allowedText.indexOf(c) != -1) {
    buf.append(c);
    }
    } else {
    buf.append(c);
    }
    }
    str = buf.toString();
    }
    Element root = document.getDefaultRootElement();
    AbstractDocument.LeafElement elt = (AbstractDocument.LeafElement) root.getElement(root.getElementIndex(offset));
    // Gets the text to insert, taking care of adding new lines in the process
    str = getTextToInsert(root, elt, str);
    if (str.length() > 0) {
    document.insertString(offset, str, a);
    }
    // if only the length of the text is limited
    }

    /**
    * Returns the text to insert on the current line.
    *
    * @param root the root element of the Document
    * @param elt the leaf element, interface the line of text where to insert the text
    * @param t the String to insert
    */
    protected String getTextToInsert(Element root, AbstractDocument.LeafElement elt, String t) {
    // Gets the length of the line where to insert the text
    int begin = elt.getStartOffset();
    int end = elt.getEndOffset();
    int length = end - begin - 1;
    // Gets the number of lines
    int lineCount = root.getElementCount();

    // iterate through the text to insert, taking care of the line length
    // and number of lines limitation
    StringBuilder buf = new StringBuilder();

    for (int i = 0; i < t.length(); i++) {
    char c = t.charAt(i);

    // if this is a new line, we must check if we are allowed to add a new line
    if (c == '\n') {
    // we are not allowed to add a new line
    if (limitLines && lineCount >= maxLines) {
    break;
    } else {
    // ok, we can add a new line
    buf.append(c);
    lineCount++;
    length = 0;
    }
    // this is not a new line character, we add the character if we can
    } else {
    // if no line length limitation, we just add the character
    if (!limitLength) {
    buf.append(c);
    } else if (length >= maxLength) {
    // else current length >= maximum line length, we try to add a new line
    // not allowed, finish to add
    if (limitLines && lineCount >= maxLines) {
    break;
    } else {
    // adding a new line is allowed, there is remaining available lines
    buf.append('\n').append(c);
    lineCount++;
    length = 1;
    }
    // current length < maximum line length, we just add the character
    } else {
    buf.append(c);
    length++;
    }
    }
    }
    return buf.toString();
    }

    /**
    * Return the text of this Document. Special spaces characters will be trasnformed to "real" spaces.
    */
    @Override
    public String getText(int offset, int length) throws BadLocationException {
    String text = document.getText(offset, length);

    return text;
    }

    /**
    * get the offset position in the Document for the selected line.
    *
    * @param line the selected line
    * @return the offset position.
    */
    public int getOffsetPosition(int line) {
    int offset = 0;
    int count = 0;

    if (line == 0) {
    return offset;
    }

    Element root = document.getDefaultRootElement();

    try {
    for (int i = 0; i < root.getElementCount(); i++) {
    AbstractDocument.LeafElement elt = (AbstractDocument.LeafElement) root.getElement(i);

    offset = elt.getStartOffset();
    String text = getText(elt.getStartOffset(), elt.getEndOffset() - elt.getStartOffset());

    if (count == line) {
    break;
    }
    if (text.charAt(text.length() - 1) == '\n') {
    count++;
    }
    }
    } catch (BadLocationException e) {
    e.printStackTrace();
    }
    return offset;
    }

    @Override
    public int getLength() {
    return document.getLength();
    }

    @Override
    public void render(Runnable runnable) {
    document.render(runnable);
    }

    @Override
    public void addDocumentListener(DocumentListener listener) {
    document.addDocumentListener(listener);
    }

    @Override
    public void removeDocumentListener(DocumentListener listener) {
    document.removeDocumentListener(listener);
    }

    @Override
    public void addUndoableEditListener(UndoableEditListener listener) {
    document.addUndoableEditListener(listener);
    }

    @Override
    public void removeUndoableEditListener(UndoableEditListener listener) {
    document.removeUndoableEditListener(listener);
    }

    @Override
    public Element getDefaultRootElement() {
    return document.getDefaultRootElement();
    }

    @Override
    public Element[] getRootElements() {
    return document.getRootElements();
    }

    @Override
    public Position getEndPosition() {
    return document.getEndPosition();
    }

    @Override
    public Position getStartPosition() {
    return document.getStartPosition();
    }

    @Override
    public Position createPosition(int i) throws BadLocationException {
    return document.createPosition(i);
    }

    @Override
    public void getText(int i, int i0, Segment segment) throws BadLocationException {
    document.getText(i, i0, segment);
    }

    @Override
    public Object getProperty(Object key) {
    return document.getProperty(key);
    }

    @Override
    public void putProperty(Object key, Object value) {
    document.putProperty(key, value);
    }
    }

最佳答案

可以使用 TextFormatter 在 JavaFX 中实现此功能.

例如,这个快速示例实现了最大文本长度。 Swing 示例中的其他功能可以类似地实现:

package org.jamesd.examples.maxtextlength;

import javafx.application.Application;
import javafx.geometry.Insets;
import javafx.geometry.Pos;
import javafx.scene.Scene;
import javafx.scene.control.Label;
import javafx.scene.control.Spinner;
import javafx.scene.control.TextArea;
import javafx.scene.control.TextFormatter;
import javafx.scene.layout.BorderPane;
import javafx.scene.layout.HBox;
import javafx.stage.Stage;

public class HelloApplication extends Application {
@Override
public void start(Stage stage) {
TextArea textArea = new TextArea();
Spinner<Integer> maxLengthSpinner = new Spinner<>(10, 200, 100);
maxLengthSpinner.valueProperty().addListener((obs, oldLength, newLength) ->
textArea.setText(textArea.getText().substring(0, Math.min(newLength, textArea.getLength())))
);
textArea.setTextFormatter(new TextFormatter<String>(change -> {
int proposedTextLength = change.getControlNewText().length();
if (proposedTextLength > maxLengthSpinner.getValue()) {
// truncate text to maximum allowed length:
int newTextLength = change.getText().length();
int delta = proposedTextLength - maxLengthSpinner.getValue();
change.setText(change.getText().substring(0, newTextLength - delta));
// adjust caret:
change.setCaretPosition(change.getCaretPosition() - delta);
change.setAnchor(change.getAnchor() - delta);
}
return change;
}));
Label length = new Label();
length.textProperty().bind(textArea.textProperty().map(String::length).map(len -> "Length: "+len));
length.setPadding(new Insets(5));

HBox controls = new HBox(5, new Label("Max text length:"), maxLengthSpinner);
controls.setPadding(new Insets(5));
controls.setAlignment(Pos.CENTER);
BorderPane root = new BorderPane(textArea);
root.setBottom(length);
root.setTop(controls);

Scene scene = new Scene(root);
stage.setScene(scene);
stage.show();
}

public static void main(String[] args) {
launch();
}
}

我有时发现 TextFormatter 的使用有点不直观(尽管它非常强大)。您可能想引用这个excellent tutorial .

关于swing - Javafx 替代 swing javax.swing.text.Document,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/77193601/

30 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com