5

我的应用程序中有一个文本字段。尽管它是一个文本字段,但用户有时会在其中粘贴大量文本。此外,该问题的其他功能也投入了大量资金。

有时文本过多以至于 JVM 在 fontmanager.dll 中出现访问冲突。Oracle 似乎对解决问题本身不感兴趣,所以我想至少尽量避免它。

限制用户输入的文本数量显然是不可接受的(否则这将是最明显的解决方案),但允许设置它然后禁用文本字段是可以接受的。当文本绑定回模型时,它应该再次包含全文。

由于这本质上是视图中的一个错误,我认为修复应该在视图中,而不是在模型中解决它并在那里添加其他属性。

我的第一次尝试是这样的:

public class LimitedTextField extends JTextField {
    static final int LIMIT = 10000;
    private String fullString;

    @Override
    public void setText(String text) {
        if (text != null && text.length() > LIMIT) {
            fullString = text;
            setEnabled(false);
        } else {
            fullString = null;
            super.setText(text);
            setEnabled(true);
        }
    }

    @Override
    public String getText() {
        if (fullString != null) {
            return fullString;
        } else {
            return super.getText();
        }
    }
}

这确实通过了简单的单元测试,但是一旦我为 BeansBinding 编写了一个附加测试,我发现它不起作用,因为 BeansBinding 不绑定到文本属性,而是绑定到文档,模拟文本属性。所以实际上 getText() 在那个测试中总是返回一个空字符串。

我现在正在考虑尝试制作一个 Document 实现来做我想做的事情,但是在文档级别做这种技巧肯定不容易。我可以看到它拥有的所有方法,但是我找不到一种限制文本的好方法,而不会在调用 getText() 时使该文本不可用。

4

3 回答 3

1

有限长度的文档真的很容易做到。当然有几种方法,这是最简单的(在我们的环境中生产):

package com.twist.ui.text.document;

import javax.swing.text.AttributeSet;
import javax.swing.text.BadLocationException;
import javax.swing.text.PlainDocument;

public class LimitedLengthDocument extends PlainDocument {
    private static final long serialVersionUID = 1L;

    private int limit;

    public LimitedLengthDocument(int limit) {
        super();
        this.limit = limit;
    }

    public void insertString(int offset, String str, AttributeSet attr) throws BadLocationException {
        if (str == null)
            return;

        // insert the string as usual.
        super.insertString(offset, str, attr);

        // If user tries to paste in a String that will not fit into the textfield, this approach will 
        // insert the text and remove the extra characters from the right.      

        // if resultant doc length is greater than the allowable size, truncate the document.
        if( getLength() > limit  )
            super.remove(limit, getLength() - limit);
    }
}
于 2010-08-05T19:49:26.160 回答
1

毫无疑问,这是一个艰难的过程。除了不尝试渲染太多文本之外,您还希望以最小的影响影响该字段的绘制。我唯一的建议是考虑创建自己的绘画策略(请参阅http://forums.sun.com/thread.jspa?threadID=481290)以及绘制文本的位置,只需绘制字符的子集. 您可以尝试构建一个新的 UIDelegate 来绘制文本组件,但这也可能非常困难。此绘画概述可能会帮助您指导您进行自定义绘画。本文可能会帮助您了解如何在所有文本字段或您尝试更正的文本字段中应用自定义 UI 委托

于 2010-08-05T08:02:22.927 回答
1

您可以使用单行 JTextArea,而不是使用 JTextField。然后,您可以在 Document 中插入换行符。然后在绘制文本时,您将只看到一行。

您可能还需要重写 getText() 方法以删除换行符。不确定它是否有帮助,但它可能会让你朝着不同的方向思考。

于 2010-08-05T14:52:17.987 回答