【问题标题】:Change line spacing in JTextArea (not JTextPane)更改 JTextArea 中的行距(不是 JTextPane)
【发布时间】:2013-07-19 17:11:22
【问题描述】:

我正在尝试找到一种方法来更改 JTextArea 组件中的行距。

一点点搜索似乎总是揭示相同的答案:“使用 JTextPane 代替,然后调用 setParagraphAttributes”。

但我想知道是否有可能只使用 JTextArea 来实现这一点,例如,弄乱字体。

使用deriveFont(...) 方法,可以更改字体的跟踪和字距,即字符之间的水平间距,但我一直无法找到改变垂直间距的方法(可能是上升,下降,领先)。我错过了什么吗?

【问题讨论】:

  • 您需要 1. 将 JTextPane 中的所有方法添加到您自己的 JTextArea,2. 使用 Html 并需要其他技巧来强制在 JTextArea 中正确呈现 Html
  • A little bit of searching always seems to reveal the same answer: - 那么 JTextPane 有什么问题?你为什么要为 JTextArea 重新发明轮子?
  • :) 我期待这些 cmets... 有时我只是对学习新事物和弄清楚什么是可能的感兴趣。这个deriveFont(...) 函数有十亿个选项,包括应用基于矩阵的几何变换等。我只是想知道是否有可能用它来做一些魔术。它的文档记录很差,所以一些用例示例会很好。顺便说一句:轻量级编码有什么问题?如果一个简单的 JTextArea 可以解决问题,为什么还要使用完整的富文本 JTextPane?
  • 没有其他想法,任何人??? ;)

标签: java swing fonts jtextarea css


【解决方案1】:

正如 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 以修改行高的方法。例如,是否有某种方法可以影响字体报告的上升、下降和前导值?似乎很奇怪,您几乎可以更改字体外观的任何其他方面,除了这个......

【讨论】:

    【解决方案2】:

    轻量级编码有什么问题?

    没什么,你应该使用最简单的组件来完成这项工作。但如果简单的组件不支持需求,通常是因为需求更复杂,您需要更复杂的组件来实现功能。很少有设置类的属性这么简单。

    有时我只是对学习新事物和弄清楚什么是可能的感兴趣。

    Swing 文本组件使用View 来绘制文本。视图的职责是格式化和定位文本。所以每个视图都决定了何时换行以及下一行的位置。

    在 JTextArea 的情况下,它使用 Plainview 或 WrappedPlanView。对于Plainview,绘画代码为:

    drawLine(line, g, x, y);
    y += fontHeight;
    

    使用 FontMetrics.getHeight() 方法确定 fontHeight。

    所以这个值基本上是硬编码在视图中的。您总是可以为您的文本区域提供自定义视图,但覆盖视图通常不是一件容易的事。

    【讨论】:

    • 正确...这就是为什么我希望有一种方法可以弄乱提供给 JTextArea 而不是文本区域的字体。我找到了一种方法来做到这一点(见我的回答),但可能会做得更好。
    • 顺便说一句:这个小冒险教会了我很多关于 Swing 的知识。我对 Swing 有点陌生,不知道它的底层有多复杂。有时打开潘多拉的盒子会很有趣,实际上潜入使一切正常的所有弹簧和齿轮。即使我实际上从不应该/不需要弄乱它,我仍然喜欢学习这些概念(这里:组件、UI、RenderContexts、视图、指标,...)。通常可以找到一些关于如何优雅地构建代码和解决某些问题的聪明想法,尽管在这种情况下,它看起来有点混乱...... ;)
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2012-08-22
    • 2010-12-23
    • 2011-08-20
    • 1970-01-01
    • 2018-12-05
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多