【问题标题】:Swing text API: Override LabelView with different string length?Swing 文本 API:用不同的字符串长度覆盖 LabelView?
【发布时间】:2013-12-07 17:41:23
【问题描述】:

我有一个 StyledDocument 实例,其中包含表示数字的字符串等。通过覆盖字符串元素的属性,我为它们使用了从 LabelView 派生的自定义视图。我想允许用户选择显示数字的基数,例如十进制或十六进制。这是我目前的解决方案:

public class AddressView extends LabelView {
    @Override
    public Segment getText(int p0, int p1) {
        // get string representation of the number from the model
        String stringNumber = super.getText(p0, p1).toString();

        // get base from document's attributes
        int base = getDocument().getProperty(BaseProperty);

        // convert string to desired base
        String stringNumberOverride = Integer.toString(Integer.parseInt(stringNumber), base);

        // return as segment (can have a different length, JTextPane doesn't like that)
        char[] strNum = stringNumberOverride.toCharArray();
        return new Segment(strNum, 0, strNum.length);
    }
}

只有一个问题:选择文本不再起作用,因为返回的 getText 字符串没有请求的长度 (p1 - p0)。 JTextPane 组件被实现为精确选择那么多字符,因此使用上述解决方案,用户只能选择 p1 - p0 字符,即使新的基础可以在模型中显示更长的数字字符串表示形式。

那么,让 View 显示与模型中的字符串长度不同的字符串的正确方法是什么?我不想仅仅因为用户需要不同的内容表示而更新模型。

编辑:这是一个独立的示例。尝试选择文本 - 您只能选择所有字符或不选择字符,因为模型中只有一个字符。

package mini;

import javax.swing.*;
import javax.swing.text.*;

public class Mini extends JFrame {
    public Mini() {
        setDefaultCloseOperation(EXIT_ON_CLOSE);
        JTextPane pane = new JTextPane();
        pane.setEditorKit(new MyEditorKit());
        add(new JScrollPane(pane));
        pack();
    }

    public static void main(String[] args) {
        Mini mini = new Mini();
        mini.setVisible(true);
    }
}

class MyEditorKit extends StyledEditorKit {
    @Override
    public ViewFactory getViewFactory() {
        return new ViewFactory() {
            public View create(Element elem) {
                return new MyView(elem);
            }
        };
    }
}

class MyView extends LabelView {
    public MyView(Element elem) {
        super(elem);
    }

    @Override
    public Segment getText(int p0, int p1) {
        String line = "Displayed text that's longer than model text";
        return new Segment(line.toCharArray(), 0, line.length());
    }
}

【问题讨论】:

  • 这个问题需要一个 SSCCE,在本地变量中为 Document 提供硬编码值,注意 Java7 与 Java6 相比有一些重要的变化(一些错误???)
  • 我认为@StanislavL 是解决该领域问题的合适人选,请在您的帖子中搜索 ViewFactory 或 LabelView 等附加参数
  • 我真的很难理解你。您能否进一步解释一下,您实际上想要实现什么:I want to allow the user to select the base of the displayed number, e.g. decimal or hexadecimal 这是什么意思?
  • @Sage:嗯,我的文档中有包含像“123”这样的数字的字符串。我使用 Element 的自定义实例,因此我可以为它们使用自定义 View 实例。现在我希望能够以十六进制而不是十进制显示它们,例如“0x7B”而不是“123”。我不想更改模型中的所有字符串,因为那样太慢了。在视图中覆盖 getText 时,用户无法再正确选择文本,因为长度不同(0x7B 与 123 为 4 个字符)。那么正确的做法是什么?
  • @fpw,如果您在插入时更改字符串,它不会使其变慢。由于不使用Docuemnt,我很难理解你的观点。如果我正确理解你,如果我输入:This is what your ID 123 and reach to the station. 你想要它:this is what your ID 0x7B and reach to the station。我不认为使用 EditorKit 来更改视图上的数据会使这更快。因为,返回的标签视图的 getText 总是会在插入数据时被调用,并且需要调用文档的完整文本来呈现视图。

标签: java swing text view jtextpane


【解决方案1】:

有几种可能的解决方法。

  1. 您能否为添加的数字定义更大的字符串,例如空格总是有相同长度的文本?例如。您有 1-100 之间的数字,因此在前后添加空格以始终包含 3 个字符。

  2. 如果您只需要更改渲染,请保持所有原样。你可以覆盖

    public void paint(图形 g, 形状 a)

方法并使用g.drawString() 来呈现所需的文本。您可以从文档的方法public Font getFont(AttributeSet attr) 设置字体。问题是如何处理数字中的大小变化和插入符号导航,但也有可能克服。

【讨论】:

  • 建议 1 是可能的,但它就像一个 hack,只在这种情况下有效。这些数字只是一个例子,我想有一个通用的解决方案来使用没有 Document 的 LabelViews,我可以安排它们中的许多并选择跨越它们的文本。我在您的网站上查看了与您的第二个建议类似的内容 - 连字符示例。它遇到了同样的问题,请尝试通过连字符选择文本(我尝试向您发送邮件,但您的地址被转发到死地址)
  • 您可以使用 slapitsky (a) gmail.com 通常您拥有所需的所有工具。您可以在 JTextPane 中检查是否选择了范围并更改绘制背景/前景。
猜你喜欢
  • 2016-09-23
  • 2013-11-28
  • 2011-10-31
  • 2014-03-12
  • 2012-12-23
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多