我正在尝试找到一种方法来更改 JTextArea 组件中的行距。
一点点搜索似乎总是揭示相同的答案:“改为使用 JTextPane,然后调用 setParagraphAttributes”。
但我想知道是否有可能只用一个 JTextArea 来实现这一点,例如,弄乱字体。
使用该deriveFont(...)
方法,可以更改字体的跟踪和字距,即字符之间的水平间距,但我一直无法找到更改垂直间距的方法(可能是上升、下降、前导)。我在那里错过了什么吗?
正如 camickr 指出的那样,JTextArea
不提供直接更改行高的方法。它只是使用相应的提供的字体高度FontMetrics
。
但是,这使用以下辅助类打开了一个攻击点:
public class FontMetricsWrapper extends FontMetrics {
private final FontMetrics target;
public FontMetricsWrapper(FontMetrics target) {
super(target.getFont());
this.target = target;
}
@Override
public int bytesWidth(byte[] data, int off, int len) {
return target.bytesWidth(data, off, len);
}
@Override
public int charWidth(char ch) {
return target.charWidth(ch);
}
@Override
public int charWidth(int codePoint) {
return target.charWidth(codePoint);
}
// ... tons more @Override's, all of the same form:
//
// @Override
// public baz foo(bar, ...) {
// return target.foo(bar, ...);
// }
}
然后,可以像这样创建 JTextArea:
JTextArea myTextArea = new JTextArea("Some text") {
@Override
public FontMetrics getFontMetrics(Font font) {
return new FontMetricsWrapper(super.getFontMetrics(font)) {
@Override
public int getHeight() {
return 10; // Gives line height in pixels
}
};
}
};
这绝对不是最干净的解决方案,仅作为概念证明。例如,一个问题是getFontMetrics(...)
经常被调用,并且在给定的示例中,每次都会创建一个包装类的新实例。因此,至少,缓存FontMetricsWrapper
为每个给定字体创建的 HashMap 将是有序的......
但是,我真正希望的是一种方法来使用Font
或者可能是相关的FontRenderContext
传递到 JTextArea 来修改行高。例如,是否有某种方法可以影响字体报告的上升、下降和前导值?似乎很奇怪,您几乎可以更改字体外观的任何其他方面,除了这个......
轻量级编码有什么问题?
没什么,你应该使用最简单的组件来完成这项工作。但如果简单的组件不支持需求,通常是因为需求更复杂,您需要更复杂的组件来实现功能。设置类的属性很少会这么简单。
有时我只是对学习新事物和弄清楚什么是可能的感兴趣。
Swing 文本组件使用 aView
来绘制文本。视图的职责是格式化和定位文本。所以每个视图都决定了何时换行以及下一行的位置。
对于 JTextArea,它使用 Plainview 或 WrappedPlanView。对于Plainview,绘画代码是:
drawLine(line, g, x, y);
y += fontHeight;
其中 fontHeight 是通过使用 FontMetrics.getHeight() 方法确定的。
所以这个值基本上是硬编码在视图中的。您始终可以为您的文本区域提供自定义视图,但覆盖视图通常不是一件容易的事。