2016-06-06 5 views
1

Много раз за эти годы я столкнулся с проблемой изменения размера текста в определенной области на графическом интерфейсе Java. Мое решение, как правило, работать по вопросу:Java - Изменение размера шрифта в соответствии с областью

  • Перестройка интерфейса, чтобы избежать проблем

  • Изменения области в соответствии с размером текста

  • Doing бинарного поиском (если я не мог выполнить ни один из первых 2)

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

ответ

0

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

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

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

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

import java.awt.Font; 
import java.awt.FontMetrics; 
import java.awt.Graphics; 
import java.awt.Shape; 
import java.awt.font.GlyphVector; 
import java.awt.geom.Rectangle2D; 

public class FontUtilities 
{ 
    public static Font createFontToFit 
    (
     String value, 
     double width, 
     double height, 
     Font base, 
     Graphics context 
    ) 
    { 
     double measuredWidth; 
     double measuredHeight; 
     double baseFontSize; 
     FontMetrics ruler; 
     Rectangle2D bounds; 
     double heightBasedFontSize; 
     double widthBasedFontSize; 
     GlyphVector vector; 
     Shape outline; 

     if 
     (
      (value == null) || 
      (base == null) || 
      (context == null) || 
      (width != width) || 
      (height != height) 
     ) 
     { 
      return null; 
     } 

     //measure the size of the string in the current font size 
     baseFontSize = base.getSize2D(); 
     ruler = context.getFontMetrics(base); 


     vector = base.createGlyphVector(ruler.getFontRenderContext(), value); 

     //use the bounds measurement on the outline of the text since this is the only 
     //measurement method that seems to be bug free and consistent in java 
     outline = vector.getOutline(0, 0); 
     bounds = outline.getBounds(); 

     measuredWidth = bounds.getWidth(); 
     measuredHeight = bounds.getHeight(); 

     //assume that each of the width and the height of the string 
     //is proportional to the font size, calculate the ratio 
     //and extrapolate linearly to determine the needed font size. 
     //should have 2 font sizes one for matching the width, and one for 
     //matching the height, return the least of the 2 
     widthBasedFontSize = (baseFontSize*width)/measuredWidth; 
     heightBasedFontSize = (baseFontSize*height)/measuredHeight; 

     if(widthBasedFontSize < heightBasedFontSize) 
     { 
      return base.deriveFont(base.getStyle(), (float)widthBasedFontSize); 
     } 
     else 
     { 
      return base.deriveFont(base.getStyle(), (float)heightBasedFontSize); 
     } 
    } 
}