Domanda

sto usando FontMetrics.getHeight() per ottenere l'altezza della stringa, ma mi dà un valore errato, tagliando i discendenti dei caratteri della stringa. C'è una funzione meglio posso usare?

È stato utile?

Soluzione

Il metodo getStringBounds() di seguito si basa sulla GlyphVector per la corrente Graphics2D carattere, che funziona molto bene per una stringa di riga di testo:

public class StringBoundsPanel extends JPanel
{
    public StringBoundsPanel()
    {
        setBackground(Color.white);
        setPreferredSize(new Dimension(400, 247));
    }

    @Override
    protected void paintComponent(Graphics g)
    {
        super.paintComponent(g);

        Graphics2D g2 = (Graphics2D) g;

        g2.setRenderingHint(RenderingHints.KEY_ANTIALIASING,
                            RenderingHints.VALUE_ANTIALIAS_ON);

        // must be called before getStringBounds()
        g2.setFont(getDesiredFont());

        String str = "My Text";
        float x = 140, y = 128;

        Rectangle bounds = getStringBounds(g2, str, x, y);

        g2.setColor(Color.red);
        g2.drawString(str, x, y);

        g2.setColor(Color.blue);
        g2.draw(bounds);

        g2.dispose();
    }

    private Rectangle getStringBounds(Graphics2D g2, String str,
                                      float x, float y)
    {
        FontRenderContext frc = g2.getFontRenderContext();
        GlyphVector gv = g2.getFont().createGlyphVector(frc, str);
        return gv.getPixelBounds(null, x, y);
    }

    private Font getDesiredFont()
    {
        return new Font(Font.SANS_SERIF, Font.BOLD, 28);
    }

    private void startUI()
    {
        JFrame frame = new JFrame();
        frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
        frame.add(this);
        frame.pack();
        frame.setLocationRelativeTo(null);
        frame.setVisible(true);
    }

    public static void main(String[] args) throws Exception
    {
        final StringBoundsPanel tb = new StringBoundsPanel();

        SwingUtilities.invokeAndWait(new Runnable()
        {
            public void run()
            {
                tb.startUI();
            }
        });
    }
}

Si noti che ho omesso le importazioni per chiarezza.

Il risultato:

Risultato screenshot.

Altri suggerimenti

Cosa ti fa pensare che restituisce il valore errato? E 'molto più probabile che le vostre aspettative di ciò che ritorna non corrisponde alla specifica. Si noti che è perfettamente bene se alcuni glifi nel font andare sopra o sotto quei valori.

getMaxDescent() e getMaxAscent() dovrebbe dirvi i valori massimi assoluti di quei campi per qualsiasi glifo del font.

Se volete conoscere le metriche per una stringa specifica, allora è sicuramente desidera chiamare getLineMetrics().

Di recente ho scritto il codice qui sotto come avevo bisogno misurazioni di altezza Perfect Pixel per le gamme specifiche del tipo di carattere (ad esempio: tutti i personaggi minori, o tutti i numeri).

Se avete bisogno di un codice più veloce (il mio ha per i cicli) mi sento di raccomandare in esecuzione una volta alla start-up per ottenere tutti i valori (ad esempio, da 1 a 100) in un array e quindi utilizzare la matrice al posto.

Il codice disegna praticamente tutti i caratteri della stringa di input nello stesso luogo sovrapposto su un 250x250 bitmap (aumentare o ridurre, se necessario), si comincia alla ricerca di pixel dall'alto, quindi dal basso, quindi restituisce l'altezza massima trovata. Funziona con stringhe normali anche se è stato progettato per intervalli di caratteri. Ciò significa che c'è una sorta di ridondanza nella valutazione stringhe regolari come alcuni dei personaggi ripetere. Quindi, se la stringa imput supera il conteggio alfabeto (26), utilizzare come 'Trangé' imput: "ABCD ... z" e altri personaggi che possono essere utilizzati. E 'più veloce.

La speranza che aiuta.

public int getFontPixelHeight(float inSize, Paint sourcePaint, String tRange)
{
    // It is assumed that the font is already set in the sourcePaint

    int bW = 250, bH = 250;                                     // bitmap's width and height
    int firstContact = -1, lastContact = -2;                    // Used when scanning the pixel rows. Initial values are set so that if no pixels found, the returned result is zero.
    int tX = (int)(bW - inSize)/2, tY = (int)(bH - inSize)/2;   // Used for a rough centering of the displayed characters

    int tSum = 0;

    // Preserve the original paint attributes
    float oldSize = sourcePaint.getTextSize();
    int oldColor = sourcePaint.getColor();
    // Set the size/color
    sourcePaint.setTextSize(inSize); sourcePaint.setColor(Color.WHITE);

    // Create the temporary bitmap/canvas
    Bitmap.Config bConf = Bitmap.Config.ARGB_8888;
    Bitmap hld = Bitmap.createBitmap(250, 250, bConf);
    Canvas canv = new Canvas(hld);

    for (int i = 0; i < bH; i++)
    {
        for (int j = 0; j < bW; j++)
        {
            hld.setPixel(j, i, 0); // Zero all pixel values. This might seem redundant, but I am not quite sure that creating a blank bitmap means the pixel color value is indeed zero, and I need them to be zero so the addition performed below is correct.
        }
    }

    // Display all characters overlapping at the same position
    for (int i = 0; i < tRange.length(); i++)
    {
        canv.drawText("" + tRange.charAt(i), tX, tY, sourcePaint);
    }

    for (int i = 0; i < bH; i++)
    {
        for (int j = 0; j < bW; j++)
        {
            tSum = tSum + hld.getPixel(j, i);
        }

        if (tSum > 0) // If we found at least a pixel, save row index and exit loop
        {
            firstContact = i;
            tSum = 0;   // Reset
            break;
        }   
    }

    for (int i = bH - 1; i > 0 ; i--)
    {
        for (int j = 0; j < bW; j++)
        {
            tSum = tSum + hld.getPixel(j, i);
        }

        if (tSum > 0) // If we found at least a pixel, save row index and exit loop
        {
            lastContact = i;
            break;
        }   
    }

    // Restore the initial attributes, just in case the paint was passed byRef somehow
    sourcePaint.setTextSize(oldSize);
    sourcePaint.setColor(oldColor);

    return lastContact - firstContact + 1;
}

getHeight() non può tagliare i discendenti di una stringa, solo disegnando la stringa può farlo. Si utilizza l'altezza tornato da getHeight per disegnare la stringa in qualche modo, e probabilmente si sta abusando l'altezza. Ad esempio, se si posiziona il punto di inizio della stringa in fondo a una scatola che è getHeight () alto invece, la linea di base del testo siederà sul bordo inferiore della scatola, e molto probabilmente verrà troncato i discendenti.

geometria Text è un argomento complesso, infuso con reperti storici bizzarre. Come altri hanno suggerito, utilizzare getAscent e getDescent per cercare di posizionare la linea di base correttamente all'interno del vostro box.

Autorizzato sotto: CC-BY-SA insieme a attribuzione
Non affiliato a StackOverflow
scroll top