Höhe von eines Strings in Pixeln (nicht Höhe einer Zeile)

Status
Nicht offen für weitere Antworten.
M

Mario

Gast
Hallo, ich bin gerade dabei eine Klasse zu schreiben, die die Schriftgröße eines übergebenen Font-Objects soweit vergrößert/verkleinert, dass ein bestimmter String möglichst genau bestimmte Ausmaße (Dimension) annimmt.

Ist der String z.B. kleiner als die angegebene Dimension, soll er soweit vergrößert werden, bis er entweder zu hoch oder zu breit ist.
(Und dann die Schriftgröße natürlich wieder um eins verkleinern.) Aber da ist schon mein erstes, kleineres, Problem.
deriveFont akzeptiert int und float Werte. Welche Genauigkeit ist bei float sinnvoll? Sieht ein Text der Schriftgröße 10.1f anders aus als der Größe 10, oder wird z.B. der float-Wert auf einen int-Wert gerundet..?

Mein eigentliches Problem ist jedoch ein anderes. Die Breite des Strings herauszufinden scheint ganz gut zu klappen mit <FontMetrics>.stringWidth(<String>), die Höhe macht mir da sehr viel mehr Schwierigkeiten:
Mit
Code:
fm.getStringBounds(String, context).getHeight();
sowie
Code:
fm.stringHeight(String)
und allem was ich noch probiert habe (z.B. mit ascent und descent) bekomm ich für den String "E" das selbe Ergebnis wie für "e" oder ".".

Die Folge ist, viele Strings werden als zu hoch bewertet und die Schriftgröße verkleinert, obwohl über einem String wie "..." noch sehr viel Platz ist. Sogar bei Großbuchstaben ist oben noch Platz. (Den Fehler, dass die Schriftgröße nur aufgrund der Breite und nicht der Höhe verkleinert wurde hab ich nicht gemacht.)

(Bei einer Funktion, die die richtige Höhe liefert, muss ich dann auch noch wissen, wie weit unter dem obersten Pixel die baseline liegt.)

Gibt es eine Möglichkeit die Höhe von Chars bzw. eines Strings in Pixeln (im Gegensatz zu der Höhe einer Zeile) zu ermitteln?



Ich hoffe ich habmein Problem verständlich dargelegt, für alle Fälle hier nochmal der Code:


Code:
 private Component paintOn;
 private String Text;
 private Dimension Size;
 private Point Corner;
 private int xPadding;
 private int yPadding;
 private Dimension TextSize;
 private int X;
 private int Y;
 private Font useFont;
 private float accuracy;


 private void Berechnen()
 {
  FontMetrics fm;
  Rectangle2D StringBounds;
  Graphics context = paintOn.getGraphics();  

  
  //FontMetrics-Objekt der aktuellen Schrift(größe)
  fm = paintOn.getFontMetrics(useFont);
  StringBounds = fm.getStringBounds(Text, context);
  //Schriftgröße schätzen, je nachdem Höhe oder Breite
  useFont = useFont.deriveFont(useFont.getSize2D() * (float) Math.min(TextSize.width / StringBounds.getWidth(), TextSize.height / StringBounds.getHeight())); 
  //FontMetrics-Objekt aktualisieren
  fm = paintOn.getFontMetrics(useFont);
  StringBounds = fm.getStringBounds(Text, context);
  
  //vergrößern wenn zu klein, (Ergebnis größer/gleich)
  while (StringBounds.getWidth() < TextSize.width && StringBounds.getHeight() < TextSize.height)
  {
   //vergrößern
   useFont = useFont.deriveFont(useFont.getSize2D() + accuracy);
   
   //FontMetrics-Objekt aktualisieren
   fm = paintOn.getFontMetrics(useFont);
   StringBounds = fm.getStringBounds(Text, context);
  }
  
  //verkleinern wenn zu groß, (Ergebnis kleiner/gleich)
  while (StringBounds.getWidth() > TextSize.width || StringBounds.getHeight() > TextSize.height)
  {
   //verkleinern
   useFont = useFont.deriveFont(useFont.getSize2D() - accuracy);
   
   //FontMetrics-Objekt aktualisieren
   fm = paintOn.getFontMetrics(useFont);
   StringBounds = fm.getStringBounds(Text, context);
  }
  
  //zentrieren, Übergabepunkt für DrawString bestimmen
  X = Corner.x + (int) Math.floor((Size.width - StringBounds.getWidth()) / 2);
     //Y = Corner.y + (int) StringBounds.getHeight() + (int) Math.floor((Size.height - StringBounds.getHeight()) / 2);  
 }
 

m@nu

Bekanntes Mitglied
ich hatte das problem auch...
hier die lösung:
Code:
TextLayout textLayout = new TextLayout("Mein Text", meineFont, g2.getFontRenderContext());
Rectangle2D bounds = textLayout.getBounds();
über das Rectangle2D "bounds" hast zu zugriff auf die wirkliche pixel-grösse des strings :)
 
M

Mario

Gast
Danke, ich bekomme jetzt die Pixelgröße meines Strings, aber ich finde die baseline nicht.

Wo muss der Startpunkt von drawString hin?



p.s. Ich habe mein Graphics2D so bekommen:
Graphics2D g2d = (Graphics2D) <Component>.getGraphics();

doch frage ich mich warum das funktioniert, ist das Graphics-Objekt von Component eigentlich ein Graphics2D-Objekt?
 

m@nu

Bekanntes Mitglied
sobald du die werte vom TextLayout verwendest, sind die informationen über die baseline etc. "verloren" ... über die bounds hast quasi wirklich ein rechteck mit deinem text drin.
ich denke aber, wenn du nicht das TextLayout zeichnest, sondern das TextLayout nur zur höhenbestimmung verwendest, solltest du auch weiterhin die baseline von deinen FontMetrics entsprechend verwenden können.

per getGraphics() erhälst du ein "normales" Graphics.
dein vorgehen über das casten ist richtig :) Graphics2D leitet von Graphics ab. somit kann eine Graphic-Instanz in ein Graphics2D "gequetscht" werden :)
 
M

Mario

Gast
Der Punkt ist, dass ich das TextLayout benutze um zu schauen, wie groß die Schriftgröße sein muss, dass ein String (möglichst) genau in ein Rechteck passt, (z.B. ein JPanel, oder in meinem konkreten Fall, ein bestimmter Bereich in einem JPanel um den ich mit drawRect(a, b, c, d) einen Rahmen gezogen hab.)

So, jetzt nachdem ich weiß welche Schriftgröße mein Text haben muss, der genau in dieses Rechteck passt, muss ich ihn nur noch da rein zeichnen.. Da hilft mir doch dann FontMetrics nicht weiter, oder doch?
Oder kann man vielleicht das TextLayout wie ein Bild einzeichen (mit angabe des Punktes oben-links (a, b)<die gleichen a, b wie bei drawRect>)?


p.s. Ach ich dachte das mit dem Casten funktioniert nur so:
Graphics g = (Graphics) new Graphics2D(...);
Graphics2D g2 = (Graphics2D) g;

nicht aber Graphics2D g2 = (Graphics2D) new Graphics(...);

naja, praktisch..
 
M

Mario

Gast
Ich hab's mit der draw-Methode des TextLayout-Objects versucht, aber das funktioniert nicht, es wird nichts gezeichnet..
 
M

Mario

Gast
Oh, ich muss mich korrigiren, es zeichnet doch aber es verschwindet (fast) immer sofort wieder..

Außerdem braucht man hier ebenfalls die baseline..

Code:
Schriftzug.draw(this); //in paintComponent

//in meiner Klasse
 public void draw(Component paintOn)
 {
  Graphics2D g2d = (Graphics2D) paintOn.getGraphics();
  
  if (berechnet == false)
  {
   Berechnen(g2d);
  }
  
  textLayout.draw(g2d, Corner.x, Corner.y+(float)textLayout.getBounds().getHeight()); //hier bräuchte ich die baseline
 }
 

m@nu

Bekanntes Mitglied
versuch einmal, anstatt die referenz auf deine Component, die referenz auf die Graphics-instanz zu einer draw-methode weiterzugegben.

wieso brauchst du die baseline überhaupt? vertikales zentrieren? sonst irgendeine positionierung?
... benutz' doch ganz gewöhnlich die drawString-methode von der Graphics-klasse.
 
M

Mario

Gast
Ja, klar die Graphics-instanz. Danke.

Aber das Problem mit der baseline existiert immernoch.
Wofür ich sie brauch ist ganz einfach:

drawString(String, x, y) zeichnet den String so, dass die baseline des Strings auf y liegt..
"The baseline of the leftmost character is at position (x, y) in this graphics context's coordinate system."
 

m@nu

Bekanntes Mitglied
ja aber wo liegt dann das problem?? ggg
du willst deinen string vertikal zentriert zeichnen?
dies habe ich bis jetzt nur über das textlayout hinbekommen
Code:
(höhe von container / 2) - (höhe von textlayout / 2)
die baseline ändert von schrift zu schrift... aus diesem grund glaube ich nicht, es ist möglich, mit der baseline für die zentrierung zu arbeiten....
 
M

Mario

Gast
Hi Manu,
ich glaub am besten mach ich dir mein Problem mit einen kleinen Beispielprogramm klar.
Einfach ausführen, man sieht schön, wie der Rahmen zwar die richtige Größe hat, aber einfach an der falschen Stelle ist..
(Bzw. eigentlich ist der Text an der falschen Stelle und in meinen Programm passt sich die Schriftgröße dem Rahmen an, aber zur Darstellung meines Problems tut das nichts zur Sache..)

Code:
import javax.swing.*;
import java.awt.*;
import java.awt.font.TextLayout;

public class Test {

	public static void main(String[] args)
	{
	 //myFrame Frame = new myFrame();
	 JFrame f = new JFrame();
	 f.setLayout(null);
	 f.setDefaultCloseOperation(f.EXIT_ON_CLOSE);
	 f.setBounds(100,100,500,500);
	 f.setVisible(true);
	 
	 myJPanel p = new myJPanel();
	 f.add(p);
	 p.setVisible(true);
	 p.setBounds(0,0,500,500);
	}
}

class myJPanel extends JPanel
{
	myJPanel()
	{
	 super();
	}
	
	protected void paintComponent(Graphics g)
	{
		super.paintComponent(g);
		
		Font useFont = g.getFont();
		Point Corner = new Point(100,100);
		
		String Text = "Test mit g";
		Graphics2D g2d = (Graphics2D) g;
		TextLayout textLayout = new TextLayout(Text, useFont, g2d.getFontRenderContext());

		g.drawRect(Corner.x, Corner.y, (int) textLayout.getBounds().getWidth(), (int) textLayout.getBounds().getHeight());

		textLayout.draw(g2d, Corner.x, Corner.y);
//		genauso mit
		g.setFont(useFont);
		g.drawString(Text, Corner.x, Corner.y);		
	}
}
 

daLenz

Aktives Mitglied
hi,

ist dir schon aufgefallen, dass bei drawString respektiv bei textLayout.draw der ausgangspunkt (x,y) unten/links ist, während bei drawRect von oben/links ausgegangen wird?

wenn du noch die höhe des strings zu y hinzufügst, ist es im rechteck:
Code:
textLayout.draw(g2d, Corner.x, Corner.y + (int)textLayout.getBounds().getHeight());
das g geht so jedoch über den rand...

so jedoch ist es genau im rechteck (bzw. genau auf der linie des rechtecks...):
Code:
 textLayout.draw(g2d, Corner.x, Corner.y + textLayout.getAscent() - textLayout.getDescent());

greetz
 
M

Mario

Gast
Hallo daLenz, ich war ziemlich überrascht, dass deine Variante funktioniert, da ich sie schon ausgeschlossen hatte, dann ist mir wieder klar geworden, warum ich sie ausgeschlossen hatte:

Benutz mal Teststrings, wie "aaa" oder "ggg" oder gar "..." dann geht's wieder schief.
Man bräuchte sowas wie eine getRealAscent-Methode, die aber bei "A" und "a" einen unterschiedlichen Wert liefert..
 
Status
Nicht offen für weitere Antworten.
Ähnliche Java Themen
  Titel Forum Antworten Datum
J Problem mit der Höhe eines Panels AWT, Swing, JavaFX & SWT 11
G Swing Höhe des View eines JScrollPane fest auf Höhe des JScrollPane setzen! AWT, Swing, JavaFX & SWT 4
F Swing Höhe eines Headers einer JTable anpassen AWT, Swing, JavaFX & SWT 4
F 2D-Grafik Problem mit höhe||breite eines JFrames AWT, Swing, JavaFX & SWT 4
E Wie Breite und Höhe eines Panels festlegen? AWT, Swing, JavaFX & SWT 5
B Höhe eines Buttons festlegen AWT, Swing, JavaFX & SWT 7
G Höhe eines JPanels ermittlen AWT, Swing, JavaFX & SWT 3
K Höhe und Breite eines Panels im GridBagLayout ermitteln AWT, Swing, JavaFX & SWT 9
L Swing TextPanel Schrift untereinander und auf einer Höhe AWT, Swing, JavaFX & SWT 3
Jose05 Javafx Label Höhe=Breite AWT, Swing, JavaFX & SWT 1
sascha-sphw JavaFX ListCell höhe verändert sich beim ändern der Text-Farbe AWT, Swing, JavaFX & SWT 14
X JavaFX AreaChart area höhe wird nicht richtig dargestellt AWT, Swing, JavaFX & SWT 2
R Java FX - Fxml - relative Größenangaben für Breite und Höhe einer TextArea AWT, Swing, JavaFX & SWT 8
J JavaFX TableView - Höhe der Zeilen AWT, Swing, JavaFX & SWT 3
B JFreeChart Gantt Höhe Tasks AWT, Swing, JavaFX & SWT 1
Z Java Draw -JFrame finde nicht die Mitte & höhe, breite AWT, Swing, JavaFX & SWT 7
S SWT TableCell mit Composite als Inhalt / Höhe der Cell/Row AWT, Swing, JavaFX & SWT 5
T Swing JScrollPane in JPanel - Breite dynamisch, Höhe fix - wie? AWT, Swing, JavaFX & SWT 2
A LayoutManager Höhe von NORTH beim BorderLayout ändern AWT, Swing, JavaFX & SWT 4
M Wie ermittele ich die Breite und Höhe meines Displays in Pixel AWT, Swing, JavaFX & SWT 3
T LayoutManager GridBagLayout - zwei jTable mit unterschiedlicher Höhe AWT, Swing, JavaFX & SWT 2
N Swing Optimale Höhe eine JTextPanes bei festgelegter Breite bestimmen AWT, Swing, JavaFX & SWT 23
P Höhe der TitleBar vom JFrame AWT, Swing, JavaFX & SWT 2
Landei Swing JToolbar: Textfelder mit normaler Höhe? AWT, Swing, JavaFX & SWT 2
T jpanel höhe netbeans.... AWT, Swing, JavaFX & SWT 5
H LayoutManager Auf gleicher Höhe anordnen AWT, Swing, JavaFX & SWT 4
_dp jTextArea/jTextPanel Auto Höhe AWT, Swing, JavaFX & SWT 5
D JPanel höhe setzen AWT, Swing, JavaFX & SWT 2
H variable Höhe einer JTextArea (als Renderer/Editor) als Zelle einer JTable AWT, Swing, JavaFX & SWT 9
N Höhe einstellen JScrollPane AWT, Swing, JavaFX & SWT 3
G JTable Multiple Row Header Example - Probleme mit der Höhe der Zellen AWT, Swing, JavaFX & SWT 4
S Für Breite und Höhe werden 0.0 angezeigt AWT, Swing, JavaFX & SWT 2
C Swing JTextArea mit fester Breite und angepasster Höhe??? AWT, Swing, JavaFX & SWT 8
G JList Höhe? AWT, Swing, JavaFX & SWT 2
P Breite und Höhe des contentPane abfragen AWT, Swing, JavaFX & SWT 3
Y Einzigartigkeit des GridBagLayout - individuelle Höhe/Breite AWT, Swing, JavaFX & SWT 4
S Tabelle soll sich auch in der Höhe resizen? AWT, Swing, JavaFX & SWT 4
T Breite des Containers ist gegeben - wie die Höhe berechnen? AWT, Swing, JavaFX & SWT 3
H JTabbedPane Höhe-Problem AWT, Swing, JavaFX & SWT 3
S [BorderLayout]WEST/EAST sollen über ganze Höhe gehen; AWT, Swing, JavaFX & SWT 3
G Linie nach Höhe einer Zahl zeichnen? AWT, Swing, JavaFX & SWT 3
A JTextFiled-Breite und Höhe ändern AWT, Swing, JavaFX & SWT 3
S Feste Breite und Höhe für einen formatierten Text. AWT, Swing, JavaFX & SWT 5
S JFrame Fenster höhe der Titelzeile? AWT, Swing, JavaFX & SWT 13
G Klasse Image - Höhe und Breite ermitteln AWT, Swing, JavaFX & SWT 12
B BorderLayout.WEST (JTree strecken in Höhe) AWT, Swing, JavaFX & SWT 2
D Jtable Header Höhe setzen ? AWT, Swing, JavaFX & SWT 2
B JEditorPane: Höhe für bestimmte Breite bestimmen AWT, Swing, JavaFX & SWT 4
javasdann Höhe von Titlebar in jInternalFrame ändern AWT, Swing, JavaFX & SWT 5
J DefaultTableCellRenderer & Höhe AWT, Swing, JavaFX & SWT 3
D JLabel mit fester Breite und beliebiger Höhe AWT, Swing, JavaFX & SWT 4
O warum ist die Höhe meines JPanels 0? AWT, Swing, JavaFX & SWT 8
L wie kann man die Höhe und Breite von JList festlegen AWT, Swing, JavaFX & SWT 3
C Titel-Balken höhe?! AWT, Swing, JavaFX & SWT 4
C Höhe der Titelleiste in JInternalFrame AWT, Swing, JavaFX & SWT 4
jojoge wie kann ich in eine Benennung eines JButtons eine Variable einbauen? AWT, Swing, JavaFX & SWT 6
L paintComponent in Panel eines Borderlayouts hinzufügen AWT, Swing, JavaFX & SWT 3
I Einbindung eines jpg/png/icons in eine GUI AWT, Swing, JavaFX & SWT 1
Splayfer Umrandung eines AttributedStrings AWT, Swing, JavaFX & SWT 2
Guybrush Threepwood Einfachste Möglichkeit zum Abspielen eines Videos in Swing AWT, Swing, JavaFX & SWT 4
Jose05 NullPointerException bei Beschreiben eines Labels aus einem Array AWT, Swing, JavaFX & SWT 12
Jose05 zugreifen auf ein Objekt eines GridPanes AWT, Swing, JavaFX & SWT 0
melaniemueller Verschiebung eines Fensters über Button AWT, Swing, JavaFX & SWT 27
news2swen automatisches erstellen eines Languagefiles AWT, Swing, JavaFX & SWT 1
B Stylen eines JTextPane funktioniert nicht AWT, Swing, JavaFX & SWT 1
MiMa Schliessen eines FXML Fensters? AWT, Swing, JavaFX & SWT 10
B JavaFX Farbe eines Quadrates in einer separaten Klasse ändern AWT, Swing, JavaFX & SWT 4
L AWT Ändern der Farbe eines BufferedImage mit Farbähnlichkeit AWT, Swing, JavaFX & SWT 5
B veränderte Größe eines Panels im Vorhinein wissen? AWT, Swing, JavaFX & SWT 1
L Komponenten eines Panels werden erst nach Klick darauf angezeigt AWT, Swing, JavaFX & SWT 13
L JavaFX Validierung eines Spinner AWT, Swing, JavaFX & SWT 1
M Builden eines lauffähigen JAR Files AWT, Swing, JavaFX & SWT 3
K Swing Text eines Lables in einer Methode ändern AWT, Swing, JavaFX & SWT 13
M JavaFX rotieren eines Kreises mit konstanter Geschwindigkeit AWT, Swing, JavaFX & SWT 1
K JavaFX Allgemeine Fragen zu dem Aufbau eines Programms hinsichtlich der Klassen AWT, Swing, JavaFX & SWT 1
M JavaFX Auf ein UI Elemement eines anderen Controllers zugreifen AWT, Swing, JavaFX & SWT 0
P Bewegung eines Balkens in eineum JPanel welches als Spielfeld fungiert AWT, Swing, JavaFX & SWT 2
Tronert JavaFX Linienstärke eines Separators ändern? AWT, Swing, JavaFX & SWT 3
N JavaFX Group: Gezieltes entfernen eines Objects (Rectangle) AWT, Swing, JavaFX & SWT 0
J Ziehen eines Buttons im JPanel AWT, Swing, JavaFX & SWT 2
J Drag and Drop eines Buttons AWT, Swing, JavaFX & SWT 0
M NullPointerException bei Übergabe eines RadioButtons AWT, Swing, JavaFX & SWT 11
DaCrazyJavaExpert Swing Extern den Text eines nicht fetsgelegten Buttons bekommen. AWT, Swing, JavaFX & SWT 12
J JavaFX Rectangle innerhalb eines Rectangle oder Panes positionieren? AWT, Swing, JavaFX & SWT 1
C JavaFX Inhalt eines SplitPane's durch Menü-Auswahl ändern? AWT, Swing, JavaFX & SWT 13
J linken Bildausschnitt eines BufferedImage abschneiden AWT, Swing, JavaFX & SWT 4
J bestimmten Bereich eines JPanels drucken AWT, Swing, JavaFX & SWT 2
D LookAndFeel Überschreiben eines UIDelegate AWT, Swing, JavaFX & SWT 0
T Java FX Probleme beim befüllen eines Tableviews AWT, Swing, JavaFX & SWT 5
C Zeichen eines 6 -Eckes AWT, Swing, JavaFX & SWT 1
U JavaFX Wechsel der Scene nach betätigen eines Button AWT, Swing, JavaFX & SWT 2
F Screenshot eines JPanel AWT, Swing, JavaFX & SWT 3
S JavaFX TreeItem: Icon am Ende eines Eintrags anhängen AWT, Swing, JavaFX & SWT 2
D TAB Taste innerhalb eines JSpinner AWT, Swing, JavaFX & SWT 2
R Update eines Labels bei Methodenaufruf einer anderen Klasse AWT, Swing, JavaFX & SWT 9
F Swing Spaltenbreite einer Column eines JTable auslesen AWT, Swing, JavaFX & SWT 5
D Swing Komponenten Anordnung eines Panels in Verbindung eines weiteren Panels AWT, Swing, JavaFX & SWT 9
F Swing Rotation eines Bildes mit beliebigen Koordinaten um den Mittelpunkt AWT, Swing, JavaFX & SWT 3
Cromewell JavaFX Nur bestimmten Teil eines Canvas rendern und anzeigen AWT, Swing, JavaFX & SWT 2
Z Swing Variable eines Objekt aus Hashmap in JList anzeigen AWT, Swing, JavaFX & SWT 1

Ähnliche Java Themen

Neue Themen


Oben