2013-07-20 3 views
1

Я пытаюсь найти способ изменения межстрочного интервала в компоненте JTextArea.Изменение межстрочного интервала в JTextArea (не JTextPane)

Немного поиска всегда, кажется, показывает тот же ответ: «Вместо этого используйте JTextPane, а затем вызовите setParagraphAttributes».

Но мне интересно, можно ли достичь этого только с помощью JTextArea, например, возиться с шрифтом.

С помощью метода deriveFont(...) можно изменить отслеживание и кернинг шрифта, то есть горизонтальное расстояние между символами, но я не смог найти способ изменить вертикальный интервал (возможно, восхождение, спуск , ведущий). Я что-то там пропал?

+1

вам нужно 1. добавить все методы из JTextPane в свой собственный JTextArea, 2. использовать Html и потребовать другие трюки принудительное рендеринг Html в JTextArea правильно – mKorbel

+1

'Немного поиска всегда, кажется, показывает тот же ответ:' - так что же не так с JTextPane? Почему вы пытаетесь изобрести колесо для JTextArea? – camickr

+0

:) Я ожидал этих комментариев ... Иногда мне просто интересно узнать что-то новое и выяснить, что возможно. Существует миллиард опций для этой функции 'deriveFont (...)', включая применение геометрических преобразований на основе матриц и т. Д. Мне просто интересно, можно ли с этим справиться. Это довольно плохо документировано, поэтому некоторые примеры использования были бы хороши. BTW: Что не так с легким кодированием? Зачем переходить на полноэкранную JTextPane, если простой JTextArea может сделать трюк? –

ответ

4

Как указал камикр, 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(...) вызывается довольно часто и в данном примере каждый раз создает новый экземпляр класса-оболочки. Итак, по крайней мере, HashMap, который кэширует созданный FontMetricsWrapper для каждого заданного шрифта, будет в порядке ...

Но, я действительно надеялся, был способ играть с Font или, возможно, связанный FontRenderContext, переданный в JTextArea, чтобы изменить высоту линии. Например, есть ли способ повлиять на данные о восходящем, нисходящем и ведущих значениях шрифта? Кажется странным, что вы можете существенно изменить любой другой аспект внешнего вида шрифта, за исключением этого ...

1

Что не так с легким кодированием?

Ничего, вы должны использовать простейший компонент для работы. Но если простой компонент не поддерживает требование, это обычно происходит потому, что требование является более сложным, и для реализации функциональности вам нужен более сложный компонент. Редко было бы так же просто установить свойство класса.

Иногда мне просто интересно узнать что-то новое и выяснить, что возможно.

Компоненты качания текста используют текст View, чтобы нарисовать текст. Форма зрения и расположение текста зависит от мнения. Таким образом, каждое представление определяет, когда нужно обернуть и где разместить следующую строку.

В случае JTextArea используется либо Plainview, либо WrappedPlanView. Для Plainview код картина:

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

, где FontHeight определяется с использованием метода FontMetrics.getHeight().

Таким образом, значение в основном жестко закодировано в представлении. Вы всегда можете предоставить пользовательский вид для своей текстовой области, но переопределение представления обычно не является легкой задачей.

+0

Правильно ... Вот почему я надеялся, что, возможно, испортится шрифт, предоставленный JTextArea вместо текстовой области. Я нашел один способ сделать это (см. Мой ответ), но, вероятно, можно сделать лучше. –

+0

BTW: Это небольшое приключение учит меня довольно много о Swing. Я немного новичок в Swing и понятия не имею, насколько сложно это под капотом. Может быть интересно открыть коробку Пандоры иногда и фактически погрузиться во все пружины и шестерни, которые заставляют все работать. Даже если мне никогда не нужно/нужно возиться с любым из них, мне все равно нравится изучать понятия (здесь: Компоненты, пользовательские интерфейсы, RenderContexts, Views, Metrics, ...). Часто есть некоторые умные идеи, которые можно найти о том, как структурировать код и решать некоторые проблемы элегантно, хотя в этом случае он выглядит немного беспорядочным ...;) –