当前位置: 首页 > 知识库问答 >
问题:

以固定字符宽度换行JTextArea

吕衡
2023-03-14
  1. 必须使用可变宽度字体(因为它看起来很漂亮)。
  2. 必须以特定字符宽度换行文本(以匹配文本UI)

一个简单的连击实现,是吗?修改UI以提供我自己版本的包装视图(它继承自WrappedPlainView),并重写calculateBreakPosition()以提供我想要的包装行为。

只是看起来不那么简单。正在忽略由可变呈现宽度派生的问题...我发现calculateBreakPosition()没有被调用用于我预期需要它调用的编辑(在包装文本的前面添加字符),并且它在一些相当常见的场景中计算中断位置1或2,而没有引用我的重写方法,这让我认为我遇到了优化或文本区域实现的细节,我对此并不了解。事实证明,重写更多的方法来调试和修复这个问题是很困难的:WrappedPlainView中的许多方法标记为final或private,包含对com.sun类的引用,和/或引用private/final方法或使用com.sun类的方法。

有什么建议让这件事开始吗?

我目前拥有的:

package com.foo.inputs;

import java.util.Vector;
import javax.swing.text.BadLocationException;
import javax.swing.text.Element;
import javax.swing.text.WrappedPlainView;

public class CustomWrappedPlainView extends WrappedPlainView
{
    private int charsWide;

    public CustomWrappedPlainView(Element elem, int width)
    {
        super(elem, true);
        this.charsWide = width;
    }


    @Override    
    protected int calculateBreakPosition(int p0, int p1)
    {
        int length = p1 - p0; 
        // Check for fit without wrapping.
        if(length <= charsWide)
        {
            return p1;
        }

        // Given: Past this point, we have at least charsWide+1 characters.

        String text;
        try
        {
            // Get one extra character.  If wrapping at 5 chars and the/
            // first six chars are: '12345 '  then we don't need to split
            // anything - that extra char matters.
            text = getDocument().getText(p0, charsWide+1);
        } catch(BadLocationException err)
        {
            // Should not happen
            // Fall back to max width
            return p0 + charsWide; 
        }
        return p0 + getBreakPosition(text, charsWide);
    }


    /** Determine where to break a substring. */
    static protected int getBreakPosition(String text, int charsWide)
    {
        // Paranoid check to avoid string bound errors
        if(text.length() <= charsWide)
        {
            return text.length();
        }

        // keep this simple, until/unless we need something more complex.

        for(int i = charsWide; i>= 0; i--)
        {
            char nyble = text.charAt(i);
            if(Character.isAlphabetic(nyble))
            {
                continue;
            }
            if(Character.isDigit(nyble))
            {
                continue;
            }
            if(Character.isWhitespace(nyble))
            {
                // Wrap AFTER the space.
                // Don't start new lines with a space.
                return i+1;
            }
        }
        // Fallback: wrap after our break point
        return charsWide;
    }

    /** 
     * Utility method for CustomTextAreaEditor.  Ultimately this must
     * match the break logic from {@link #calculateBreakPosition(int, int)}
     * exactly to allow for WYSIWYG.
     */
    public static String[] breakOutLines(String text, int wrapWidth)
    {
        String[] paragraphs = text.split("\n");
        Vector<String> lines = new Vector<>();
        nextParagraph:
        for(String paragraph : paragraphs)
        {
            int length = paragraph.length();
            while(length > 0)
            {
                if(length <= wrapWidth)
                {
                    lines.add(paragraph);
                    continue nextParagraph;
                }
                int breakPoint = getBreakPosition(paragraph, wrapWidth);
                lines.add(paragraph.substring(0,breakPoint));
                paragraph = paragraph.substring(breakPoint);
                length = paragraph.length();
            }
        }
        return lines.toArray(new String[0]);
    }
}

共有1个答案

陆斌
2023-03-14

我不知道这是否有帮助,但也许您可以不用编写自定义的break逻辑,而不用玩FontMetrics:

@Override    
protected int calculateBreakPosition(int p0, int p1)
{
    FontMetrics original = metrics;
    FontMetrics monospacedFontMetrics = ...;

    int position = super.calculateBreakPosition(p0, p1);

    metrics = original;

    return position;
}

因此您可以创建一个与当前字体大小相同的单间距字体,然后使用该字体获得要在中断计算中使用的FontMetrics。

或者,您可能需要从CalculateBreakPosition(...)方法复制代码,以便也可以重写CurrentWidth以使其符合您的需要。

 类似资料:
  • 问题内容: 我有这段代码(在字符串中打印所有排列的出现) 我想打印字符串可变项中所有出现的排列。 由于排列的长度不同,因此我想固定宽度并以一种不太好的方式打印它: 我该如何使用呢? 问题答案: 编辑2013-12-11- 这个答案很老。它仍然是有效且正确的,但是关注此问题的人们应该更喜欢新格式的语法。 您可以使用以下字符串格式: 基本上: 该字符运筹学蟒蛇它将不得不替代的东西令牌 该字符运筹学蟒蛇

  • 问题内容: 我是Java Swing的新手,对下一个代码感到困惑。 我的目标是制作带有 2个JTextPane的 垂直可滚动面板 。具有父面板固定宽度70%的第一个JTextPane和具有固定宽度30%的第二个JTextPane。因为这两个JTextPane具有固定的宽度,所以它们只能在垂直方向上扩展更多文本。 我使用此解决方案,因为我只想为此2个JTextPane使用一个滚动条。 我的初始化代码

  • 我是Java Swing的新手,我对下一个代码感到困惑。 null

  • 问题内容: 我只想要固定宽度的文本列,但所有字符串都在右侧填充,而不是左侧! 产生 但是我们想要 问题答案: 您可以在尺寸要求前加上左对齐:

  • 问题内容: 我有两个div容器。 虽然其中一个需要为特定宽度,但我需要对其进行调整,以便另一个div占用其余空间。有什么办法可以做到吗? 问题答案: HTML: CSS: 您也可以使用这样做,这通常是一种更好的方法:如何将输入元素与其标签放在同一行?

  • 问题内容: 在无序列表中: 允许添加class或style属性,但不允许填充文本以及添加或更改标签。 该页面正在使用Courier New呈现。 目标是在跨度后排列文本。 “ OR”的理由并不重要。 懒惰的动物文字可能包含在其他元素中,但我必须仔细检查。 问题答案: ul { 就像Eoin所说的那样,您需要在“空”跨度中放置一个不间断的空格,但是您不能为内联元素分配宽度,只能填充/边距,因此您需要