我已经获得了基于Swing的TextArea组件的两个竞争要求:
一个简单的组合,是吗?破解UI以提供我自己的包装视图版本,该视图继承自WrappedPlainView,并覆盖calculateBreakPosition()以提供我想要的包装行为。
除了看起来不那么简单。暂时忽略从变量渲染宽度派生的问题...我发现没有为编辑调用calculateBreakPosition()我希望它需要调用(在包装文本的前面添加字符),并且它正在计算break在一些相当常见的情况下,在1或2之间的位置,没有引用我的重写方法,让我认为我正在进行优化或文本区域实现的细节,我不知道足够期待。覆盖更多调试和修复此方法的方法很难:WrappedPlainView中的许多方法都标记为final或private,包含对com.sun类的引用,和/或使用com.sun类引用private / final方法或方法。 / p>
有任何关于实现此目标的建议吗?
我目前的情况:
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]);
}
}
答案 0 :(得分:1)
不知道这是否会有所帮助,但也许不是编写自定义中断逻辑,而是可以通过使用FontMetrics来逃避:
@Override
protected int calculateBreakPosition(int p0, int p1)
{
FontMetrics original = metrics;
FontMetrics monospacedFontMetrics = ...;
int position = super.calculateBreakPosition(p0, p1);
metrics = original;
return position;
}
因此,您可以创建与当前Font相同大小的Monospaced字体,然后使用该字体获取在中断计算中使用的FontMetrics。
或者您可能需要复制calculateBreakPosition(...)
方法中的代码,以便您也可以覆盖currentWidth
以满足您的需求。