2016-06-06 9 views
1

Im Laufe der Jahre wurde ich oft mit dem Problem konfrontiert, Text in einem bestimmten Bereich auf einer Java-GUI zu skalieren. Meine Lösung war, in der Regel durch, um das Problem zu umgehen:Java - Anpassung der Schrift an den Bereich

  • Redesign der Schnittstelle das Problem

  • Ändern der Fläche zu vermeiden, dass die Größe des Textes für

  • Doing eine binäre Suche passen die richtige Größe der Schrift passt die Zeichenfolge

(wenn ich auch nicht von der ersten 2 tun könnte) Während an einem anderen Projekt arbeiten vor kurzem Da ich schnell die richtige Schriftgröße für eine bestimmte Region bestimmen musste, war meine binäre Suchmethode zu langsam (ich vermute wegen der dynamischen Speicherzuweisungen, die beim Erstellen und Messen einer Schriftart viele Male hintereinander anfallen) und führte zu merklicher Verzögerung in meiner Anwendung. Was ich brauchte, war ein schneller einfacher Weg, eine Schriftgröße zu berechnen, die es ermöglichen würde, dass eine gegebene Zeichenkette in eine definierte Region der GUI passt.

Antwort

0

Endlich fiel mir auf, dass es einen viel einfacheren und schnelleren Weg gab, der zur Laufzeit nur wenige Zuweisungen benötigte. Diese neue Methode eliminiert die Notwendigkeit für jede Art von Suche und erfordert nur eine Messung, es muss jedoch eine Annahme gemacht werden, eine, die für die meisten Anwendungen vollkommen vernünftig ist.

  • Die Breite und Höhe der Schriftart muss proportional zur Schriftgröße der Schriftart sein. Dies geschieht bei allen außer den unklaren Transformationen, die an einem Renderkontext vorgenommen werden.
  • Mit dieser Annahme können wir das Verhältnis der Schriftdimensionen zur Punktgröße berechnen und linear extrapolieren, um die Schriftgröße zu finden, die wir für die gegebene Region benötigen. Einige Code, den ich schrieb, dies zu tun ist unten:

    Edit: Die Genauigkeit der Anfangsmessung wird durch die Größe der Grundschrift beschränkt. Die Verwendung einer wirklich kleinen Schriftgröße als Basis kann die Ergebnisse verwerfen. Aber je größer die Größe der Basisschriftart ist, desto genauer ist die Genauigkeit der linearen Näherung.

    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); 
         } 
        } 
    }