String width und FontMetrics

MiMi

Erfahrenes Mitglied
Hi ho, ich mal wieder ^^

Bin gerade dabei mir ein Rechteck hinter einem staendig veraendernden Text anzeigen zu lassen. Problem ist das er die Textgroesse nicht richtig annimt.
Nutz ich zb
Java:
				final FontMetrics fm = planarGraphics2D.getFontMetrics( planarGraphics2D.getFont() );
				final int width = fm.stringWidth( text );
Bekomm ich ne tolle Fehlermeldung:
Render exception: javax.media.opengl.GLException: java.lang.StackOverflowError
javax.media.opengl.GLException: java.lang.StackOverflowError
...
Caused by: java.lang.StackOverflowError
at java.awt.FontMetrics.charsWidth(FontMetrics.java:370)
at java.awt.FontMetrics.stringWidth(FontMetrics.java:343)...

WEnn ich in den java source schaue weiss ich auch warum. Denn die stringWidth ruft die CharWidth auf und umgekehrt, KA hab auch schon gegoogelt is wohl irgend nen Bug bei Java?

Nunja also hab ich folgendes probiert
Java:
				final FontRenderContext frc = planarGraphics2D.getFontRenderContext();
				final Font font = planarGraphics2D.getFont();
				final Rectangle2D bounds = font.getStringBounds( text, frc );

				final int textWidth = (int)bounds.getWidth()*50;
				final int textHeight = (int)bounds.getHeight()*50;
Jedoch musste ich, wie man sieht, mit 50 multiplizieren das man ueberhaupt nen Rechteck sieht. Nun passt es nur solange ich nicht die Kamera rein oder rauszoome. Dit Textgroesse bleibt gleichgross und wird nicht mit raus oder reingezoomt wie der Rest der gezeichneten Linien etc.

Vielleicht hat ja jemand von euch eine Idee wie ich es loesen koennte.
 
Zuletzt bearbeitet:
Hi MiMi,

schau Dir mal dieses einfache Beispiel an. Die Schriftgröße für den Text wird abhängig von der Fenstergröße gemacht. Du siehst also den Effekt, wenn Du die Größe des Fensters änderst. Funktioniert theoretisch natürlich auch, wenn der Text selbst geändert würde.

Java:
import java.awt.Font;
import java.awt.FontMetrics;
import java.awt.Graphics;
import javax.swing.JFrame;

public class FontPanel extends javax.swing.JPanel{
 
    public FontPanel() {
        super();
    }
    
    @Override
    public void paint(Graphics g) {
        super.paint(g);

        Font font = new Font("Verdana", Font.PLAIN, getWidth()/20);
        g.setFont(font);
        
        String text = "String Font Test!";
        
        FontMetrics metrics = g.getFontMetrics();
        
        int textWidth = metrics.stringWidth(text);
        int textHeight = metrics.getHeight();
        
        g.drawString(text, 100, 100);
        g.drawRect(100, 100-metrics.getAscent(), textWidth, textHeight);        
    }
 
    public static void main(String[] args) {
        JFrame f = new JFrame();
        f.setSize(400, 350);
        f.setDefaultCloseOperation(JFrame.DO_NOTHING_ON_CLOSE);
        f.getContentPane().add(new FontPanel());
        f.setVisible(true);
    }
    
}
 
Zuletzt bearbeitet:
Danke erstmal, ich werds testen sobald ich wieder ans programmieren komme. Das Ergebnis lass ich dich dann natuerlich wissen :D
 
So, habs mir ma genauer angesehen. Das Problem ist das ich ja nur die 3D koordinaten hab wohin der Text und somit auch das Rechteck gezeichnet werden muessen.
Darum hatte ich immer direkt das planarGraphics genommen, weil ich dort die 3D koordinaten angeben konnte, bzw den x und y Wert davon und der das somit auf die richtige position gebracht hat.

Ich weiss jetzt auch warum und wann der Stackoverflow kommt. Das ist nur sobald ich die Fontmetric von planarGraphics abfrage anstatt von graphics. Bei graphics hat der mit stringWidth kein Problem.

Edit: Also ich kann die Koordinaten schon umrechnen. Er zeigt den Text aber jetzt in der perspektievischen Ansicht falsch an (kann leider kein screenshot zeigen) und nur in der ansicht die nich tperspektiev ist, wird die Position richtig berechnet. Ich werd mich da nochmal weiter reinarbeiten und probieren. Mit 3D Ansicht ist das alles gar net so einfach ^^ Ich meld mich dann nochma


Edit2: Also es funktioniert nun. Das Problem ist das es flackert.
Java:
				final Component component = view.getComponent();
				final Graphics g = component.getGraphics();

				final FontMetrics metrics = g.getFontMetrics();
				final int textWidth = metrics.stringWidth( text );
				final int textHeight = metrics.getHeight();

				final int lineCenterX =  ( resultStart.x + resultEnd.x  ) / 2;
				final int lineCenterY =  ( resultStart.y + resultEnd.y ) / 2;
				final int textPosX = lineCenterX - textWidth / 2;
				final int textPosY = lineCenterY;

				g.setColor( Color.white );
				g.fillRect( textPosX , textPosY - metrics.getAscent(), textWidth , textHeight);
				g.setColor( Color.black );
				g.drawString( text , textPosX , textPosY );
				g.dispose();
Nun war es ja so das man nicht von einem Componenten die Graphics abfragen sollte. Jedoch ist meine einzige andere moeglichkeit die Graphics2D mitzugeben an die Zeichenmethode. Nutz ich jedoch wieder Graphics2D bekomm ich wieder den StackOverflow von oben
 
Zuletzt bearbeitet:
Also habs jetzt umgangen.
Hab "einfach" das Graphics2D genutzt, und dann statt stringwidth mit stringbounds gearbeitet. Ist zwar dumm das man Stringwidth net nutzen kann bei Graphics2D aber es funktioniert nun so wie es soll.
Danke fuer eine Muehe :D
 

Neue Beiträge

Zurück