J'utilise FontMetrics.getHeight()
pour obtenir la hauteur de la chaîne, mais elle me donne une valeur erronée, coupant les descendants des caractères chaîne. Y a-t-il une meilleure fonction que je peux utiliser?Comment obtenir la hauteur de chaîne réelle en Java?
Répondre
La méthode getStringBounds()
ci-dessous est basée sur la GlyphVector
pour la police Graphics2D
actuelle, qui fonctionne très bien pour une chaîne de ligne de texte:
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();
}
});
}
}
Notez que j'ai omis les importations pour plus de clarté.
Le résultat:
et FontMetrics.getDescent() pourrait faire l'affaire.
Qu'est-ce qui vous fait penser qu'il renvoie une valeur erronée? Il est beaucoup plus probable que votre attente de ce qu'elle renvoie ne correspond pas à la spécification. Notez que c'est parfaitement correct si certains glyphes dans la police dépassent ces valeurs.
getMaxDescent()
et getMaxAscent()
doivent vous indiquer les valeurs maximales absolues de ces champs pour tout glyphe de la police.
Si vous voulez connaître les métriques pour une chaîne spécifique, alors vous voulez absolument appeler getLineMetrics()
.
getHeight()
ne peut pas couper les descendants d'une chaîne, seul le dessin de la chaîne peut le faire. Vous utilisez la hauteur retournée par getHeight
pour dessiner la corde d'une manière ou d'une autre, et vous utilisez probablement la hauteur. Par exemple, si vous positionnez le point de départ de la chaîne au bas d'une case getHeight() haute, la ligne de base de votre texte sera placée sur le bord inférieur de la boîte, et très probablement les descendeurs seront coupés.
La géométrie du texte est un sujet complexe, infusé d'artefacts historiques bizarres. Comme d'autres l'ont suggéré, utilisez getAscent
et getDescent
pour essayer de positionner correctement la ligne de base dans votre boîte.
J'ai écrit récemment le code ci-dessous comme je l'ai besoin des mesures de pixels en hauteur parfaites pour des gammes spécifiques de la police (par exemple: tous les caractères inférieurs, ou tous les numéros).
Si vous avez besoin d'un code plus rapide (le mien a pour boucles), je recommande de l'exécuter une fois au démarrage pour obtenir toutes les valeurs (par exemple de 1 à 100) dans un tableau.
Le code tire essentiellement tous les caractères de la chaîne d'entrée au même endroit sur un bitmap 250x250 (augmenter ou réduire si nécessaire), il commence à rechercher les pixels du haut, puis du bas . Il fonctionne avec des chaînes normales même s'il a été conçu pour des plages de caractères. Cela signifie qu'il existe une sorte de redondance lors de l'évaluation de chaînes régulières, comme le répètent certains caractères. Donc, si votre chaîne d'imputation dépasse le nombre d'alphabets (26), utilisez comme imputation 'tRange': "abcd ... z" et d'autres caractères qui peuvent être utilisés. C'est plus rapide.
Espérons que ça aide.
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;
}
- 1. JavaScript - fonction pour obtenir la largeur de l'image réelle et la hauteur (navigateur croisé)
- 2. Comment obtenir la valeur réelle d'un DependancyProperty?
- 3. Comment puis-je obtenir la largeur et la hauteur d'une chaîne de texte avec CAM :: PDF?
- 4. Obtention de la hauteur réelle d'un élément auto-hauteur dans IE
- 5. Comment obtenir la largeur réelle d'un pop-up WPF
- 6. Comment obtenir la hauteur de la table dans PDFsharp?
- 7. Comment puis-je obtenir la valeur affichée au lieu de la valeur réelle dans Excel?
- 8. Obtenir une adresse IP "réelle" avec VB.NET?
- 9. Comment puis-je obtenir l'erreur réelle derrière HttpResponseException?
- 10. Obtenir la hauteur d'un ImageSource dans Silverlight
- 11. jQuery - obtenir une hauteur et la réutiliser
- 12. Comment puis-je obtenir la hauteur de l'écran du navigateur?
- 13. Comment obtenir la date de cette chaîne?
- 14. SDK iPhone: Comment mesurer la largeur et la hauteur d'une chaîne à l'aide de Quartz?
- 15. Calcul de la largeur et de la hauteur d'une chaîne formatée en C#
- 16. WPF: Comment puis-je obtenir la hauteur d'une ligne listview?
- 17. Mysql réelle boucle de chaîne d'échappement plusieurs variables
- 18. Obtenir la valeur de chaîne dans la classe de chaîne
- 19. hauteur de la page en javascript
- 20. Obtenir la largeur et la hauteur d'origine de l'actioncript
- 21. Obtenir l'image Hauteur et largeur
- 22. CSS: Hauteur de la zone de texte en pourcentage de la hauteur de la fenêtre d'affichage
- 23. Java rapporte alias (lien symbolique) comme taille 0 sur Mac OSX. Comment puis-je obtenir la taille réelle du fichier?
- 24. convertir la chaîne de caractères hexadécimale en entier en Java
- 25. Comment obtenir la longueur d'une chaîne en Perl?
- 26. Analyse de la chaîne de date JavaScript en Java
- 27. Comment définir la hauteur de la liste SWT en lignes?
- 28. Comment puis-je obtenir la largeur maximale et la hauteur d'un appareil en android
- 29. Comment obtenir la hauteur de l'élément du corps en utilisant JQuery
- 30. Comment obtenir la taille réelle sur disque d'un fichier à partir de PowerShell?
@nierito Bonne réponse et bonne démo! Sur la base de ce que vous avez dit, j'ai essayé de raccourcir votre code (en supposant que l'on ait défini une «police» et obtenu le 'FontMetrics'). Cela fonctionne plutôt bien. 'police.createGlyphVector (fontMetrics.getFontRenderContext(), texte) .getVisualBounds(). getHeight(); ' –
Comment l'utilisation de GlyphVector.getPixelBounds se compare-t-elle à Font.getStringBounds et TextLayout.getBounds? Y a-t-il un gros avantage au code plus complexe? Dans un test simple, j'ai trouvé que la méthode Font sur-reporté la hauteur par rapport aux deux autres. J'aime ça et le TextLayout ne nécessite pas de point x et y. – jla
c'est 8 ans, mais quand j'utilise g2d.scale (x, x); il ne peut pas s'afficher correctement! – yelliver