【问题标题】:Limit TextField's text area (margins/padding)限制 TextField 的文本区域(边距/填充)
【发布时间】:2021-02-22 09:03:58
【问题描述】:

我在 JavaFX 中使用了一些 TextField,我想限制它们显示文本的区域。我已经限制了它们的最大字符数,但在某些情况下,输入的最大字符数大于文本字段的宽度。如您所见,文本与我添加的自定义擦除文本按钮重叠。

我想知道我是否可以将文本的右边距向左移动一点(不改变 TextField 的属性 - 大小、坐标),这样按钮和文本就不会再重叠了。

我已经尝试过边距、填充,但它们没有达到我的要求。

如何限制我的 TextField 的最大长度(来自 stackoverflow):

public class LimitedJFXTextField extends JFXTextField {

    private final IntegerProperty maxLength;

    public LimitedJFXTextField() {
        super();
        this.maxLength = new SimpleIntegerProperty(-1);
    }

    public IntegerProperty maxLengthProperty() {
        return this.maxLength;
    }

    public final Integer getMaxLength() {
        return this.maxLength.getValue();
    }

    public final void setMaxLength(Integer maxLength) {
        Objects.requireNonNull(maxLength,
                "Max length cannot be null, -1 for no limit");
        this.maxLength.setValue(maxLength);
    }

    @Override
    public void replaceText(int start, int end, String insertedText) {
        if (this.getMaxLength() <= 0) {
            // Default behavior, in case of no max length
            super.replaceText(start, end, insertedText);
        } else {
            // Get the text in the textfield, before the user enters something
            String currentText = this.getText() == null ? "" : this.getText();

            // Compute the text that should normally be in the textfield now
            String finalText = currentText
                    .substring(0, start) + insertedText + currentText
                    .substring(end);

            // If the max length is not excedeed
            int numberOfexceedingCharacters = finalText.length() - this
                    .getMaxLength();
            if (numberOfexceedingCharacters <= 0) {
                // Normal behavior
                super.replaceText(start, end, insertedText);
            } else {
                // Otherwise, cut the the text that was going to be inserted
                String cutInsertedText = insertedText.substring(
                        0,
                        insertedText.length() - numberOfexceedingCharacters
                );

                // And replace this text
                super.replaceText(start, end, cutInsertedText);
            }
        }
    }
}

【问题讨论】:

  • 布局是皮肤的任务:添加子类,子类TextFieldSkin,添加需要的东西并覆盖computeXX和layoutChildren以适应它们。无关:为什么这个手动破解来限制字符数?这是可能的,但属于石器时代,目前实现它的方法是使用 TextFormatter
  • 无论如何,无论何时寻求调试帮助,都需要 minimal reproducible example - 而不仅仅是(复制?)代码的 sn-p。实际上,当布局出现问题时,根本不需要其他专业,如字符限制(重复:以非常过时的方式!)
  • @DevilsHnd 不能确定,但​​是:问题是关于布局,而不是关于限制字段中的字符数(这在您引用的 QA 中得到了很好的回答:)
  • @kleopatra 是的,你是对的,问题是关于布局的。另外,我使用的是手动破解,因为老实说,我不知道 TextFormatter。我第一次尝试使用 TextProperty,但至少在我的实现方式中,它是错误的。然后,我切换到手动石器时代的黑客。谢谢你的帮助!我还没有解决我的问题,即使你给了我一个解决方案,但我会继续努力。至少,我修改了限制字符数的方式:)
  • @kleopatra 你能再具体一点吗?我正在尝试你所说的,在过去的几个小时里,我什至没有一点进展(加上谷歌搜索了 2 天;除了你的建议之外,没有找到相关的东西)。如果我的回复很烦人,或者违反了一些规则,请删除我的帖子。谢谢!

标签: java javafx textfield jfoenix


【解决方案1】:

这是使用ControlsFX 的解决方案。

import java.io.IOException;
import javafx.application.Application;
import javafx.scene.Scene;
import javafx.scene.control.Label;
import javafx.scene.layout.StackPane;
import javafx.scene.paint.Color;
import javafx.stage.Stage;
import org.controlsfx.control.textfield.CustomTextField;

/**
 * JavaFX App
 */
public class App extends Application
{

    private static Scene scene;

    @Override
    public void start(Stage stage) throws IOException
    {
        CustomTextField customTextField = new CustomTextField();
        customTextField.setText("Hello World!");

        Label labelX = new Label("x");
        labelX.setTextFill(Color.RED);
        customTextField.setRight(labelX);
        customTextField.setMaxWidth(200);

        scene = new Scene(new StackPane(customTextField), 500, 500);//loadFXML("primary"), 640, 480);
        stage.setScene(scene);
        stage.show();
    }
}

【讨论】:

    【解决方案2】:

    我从来没有用过JFXTextField,所以请对这个答案持保留态度。

    但是,由于JFXTextField extends TextField,您应该能够更改 TextField 的属性。其中之一称为padding

    所以只使用“普通”的 TextField,你可以使用这个:

    public class ExampleApp extends Application {
    
        public static void main(String[] args) {
            Application.launch(args);
        }
    
        @Override
        public void start(Stage stage) {
            var textField = new TextField();
            textField.setPadding(new Insets(0, 50, 0, 0)); // This adds 50px right padding
            textField.setText("Hello World!");
    
            var label = new Label("x");
    
            var pane = new StackPane(textField, label);
            StackPane.setAlignment(label, Pos.CENTER_RIGHT);
    
            var scene = new Scene(pane, 500, 500);
            stage.setScene(scene);
            stage.show();
        }
    }
    

    或者,如果您更喜欢 FXML,请使用:

    <TextField>
        <padding>
            <Insets right="50"/>
        </padding>
    </TextField>
    

    StackPane 和 Label 只是为了演示一些重叠项目,与 Sedricks 的答案相同。实际上限制文本字段内部文本的重要部分是填充。

    【讨论】:

    • 它不起作用。它修改了我的 TextField 皮肤(使其更小)。这是 TextField 最初的样子,没有填充(电话文本字段),以及 TextField 看起来有填充(邮件文本字段):photo demo
    • 不过,这是样式问题。您需要区分行为(这就是您的问题)和外观(您的屏幕截图)。如果您需要帮助修复底部边框的长度,请将您的文本字段的 CSS 添加到您的问题中。
    • 这是JFXTextField的默认皮肤:css-file
    猜你喜欢
    • 2011-07-18
    • 1970-01-01
    • 1970-01-01
    • 2016-07-25
    • 1970-01-01
    • 2016-10-08
    • 1970-01-01
    • 2011-03-04
    相关资源
    最近更新 更多