我可以限制 JTextField 中可绘制的文本长度,同时仍存储完整文本吗?

发布于 2024-09-13 16:03:33 字数 1194 浏览 3 评论 0原文

我的应用程序中有一个文本字段。尽管它是一个文本字段,但用户有时会向其中粘贴大量文本。此外,该问题的其他功能也设置了大量的内容。

有时,由于文本太多,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() 在该测试中总是返回一个空字符串。

我现在正在考虑尝试创建一个文档实现来实现我想要的功能,但在文档级别实现这种技巧确实不容易。我可以看到它拥有的所有方法,但我找不到一种好的方法来限制文本,而又不会在调用 getText() 时使该文本不可用。

I have a text field in my application. Despite it being a text field, users sometimes paste huge amounts of text into it. Additionally, other functions of the problem set large amounts in as well.

Sometimes there is so much text that the JVM gets an access violation in fontmanager.dll. Oracle doesn't appear to be interested in fixing the problem itself, so I would like to at least try to avoid it.

Limiting the amount of text the user inputs is apparently not acceptable (otherwise this would be the most obvious solution) but it's acceptable to allow it to be set and then disable the text field. When the text is bound back to the model, it should contain the full text again.

Since this is inherently a bug in the view, I figured that the fix should be in the view, as opposed to working around it in the model and adding the additional properties there.

My first attempt went something like this:

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();
        }
    }
}

This does pass naive unit tests, but once I wrote an additional test for BeansBinding, I found that it didn't work because BeansBinding doesn't bind to the text property but rather binds to the Document, simulating a text property. So actually getText() always returns an empty string on that test.

I am now looking at trying to make a Document implementation which will do what I want, but it sure isn't easy to do this kind of trick at the document level. I can see all the methods it has, but I can't find a good way to limit the text without also making that text unavailable when calling getText().

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(3

十秒萌定你 2024-09-20 16:03:33

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

This is a tough one no doubt. You want to affect the painting of the field with minimal impact other than not trying to render too much text. The only suggestion I have is to look at creating your own painting strategy (see http://forums.sun.com/thread.jspa?threadID=481290) and where the text is drawn, just draw a sub-set of the characters. You could look at trying to build a new UIDelegate for drawing the text component but that might be pretty hard too. This painting overview might help steer you with regards to custom painting. This article might help you with how to apply a custom UI delegate across all textfields or just the one you are trying to correct.

长发绾君心 2024-09-20 16:03:33

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

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

Instead of using a JTextField maybe you could use a sinlge line JTextArea. Then you can insert a newline character into the Document. Then when the text is painted you will only see a single line.

You will probably need to override the getText() method as well to remove the newline character. Not sure if it helps but it may get you thinking in a different direction.

执手闯天涯 2024-09-20 16:03:33

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

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);
    }
}

The Limited Length Document is really easy to do. Of course there are several approches, Here is the simplest (works in production in our environment):

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);
    }
}
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文