Algorithmus für automatische Zeilenumbrüche

Status
Nicht offen für weitere Antworten.

Mewel

Aktives Mitglied
Hallo,

ich bin auf der Suche nach einem Algorithmus der mir einen Text automatisch mit
Zeilenumbrüchen formatiert. Wichtig ist dabei das man verschiedene Sachen
"einstellen" kann:
- maximale Anzahl der Pixel pro Zeile (eine Zeile darf z.B. nur max. 500 pixel breit sein, danach automatischer Zeilenumbruch)
- Bestimmung eines oder mehrerer Trennern (z.B. leerzeichen, komma, punkt etc.)
- maximale Anzahl der Zeilen -> evt. verkleinerung der font-size & wenn text immer noch zu lang dann kürzen und mit "..." abschließen

Wenn ihr Algorithmen kennt die davon Teilbereiche lösen, würde mir das auch schon helfen.

Ich habe mich auch selber mal daran versucht, bin aber nicht 100% mit dem Ergebnis zufrieden. Wenn ihr dort Verbesserungen seht, könnt ihr mir die gerne mitteilen :).

Code:
import java.awt.Color;
import java.awt.Font;
import java.awt.Graphics2D;
import java.awt.font.TextAttribute;
import java.text.AttributedString;

import sun.font.FontDesignMetrics;

public class MultiLineTextDrawer {

	public final static int AL_LEFT = 0;
	public final static int AL_CENTER = 1;
	public final static int AL_RIGHT = 2;
	
	private Graphics2D graphics;

	private int startX = 0;
	private int startY = 0;
	private int maxLineWidth = 800;
	private int maxSubLines = 50;
	private int startFontSize = 12;
	private int minFontSize = 8;
	private int inset = 4;

	int alignment = AL_LEFT;
	
	public MultiLineTextDrawer(Graphics2D graphics) {
		this.graphics = graphics;
	}

	public void drawText(String text) {
		if(graphics == null)
			return;

		int aktFontSize = startFontSize;
		int aktSubLine = 0;

		String[] subLines = new String[1];
		subLines[0] = text;

		Font font = new Font("Arial", Font.PLAIN, aktFontSize);
		// Erstellung von mehrzeiligem Text
		int textWidth = FontDesignMetrics.getMetrics(font).stringWidth(text);
		if( textWidth > maxLineWidth ) {
			int subLinesNeeded = Math.round((((float)textWidth / (float)maxLineWidth) + 0.5f));
			
			if(subLinesNeeded  > maxSubLines)
				subLinesNeeded = maxSubLines;

			// Teile den text in möglichst 'subLinesNeeded' Teile
			String[] subStrings = text.split(" ");

			// Berechne die Einzelnen Gewichte für jeden subString
			float[] subStringWeights = new float[subStrings.length];
			for(int i = 0; i < subStrings.length; i++) {
				if(i != subStrings.length - 1)
					subStrings[i] += " ";
				subStringWeights[i] = ((float)subStrings[i].length() / (float)text.length());
			}

			// Können nur soviele Zeilen existieren wie auch Leerzeichen
			if(subStrings.length < subLinesNeeded)
				subLinesNeeded = subStrings.length;

			// subLines mit "" inialisieren (sonst wird "null" an String gehängt)
			subLines = new String[subLinesNeeded];
			for( int i = 0; i < subLines.length; i++) {
				subLines[i] = "";
			}

			// subLines werden über die Gewichte mit den subStrings gefüllt
			float aktWeight = 0.0f;
			for(int i = 0; i < subStrings.length; i++) {
				subLines[aktSubLine] += subStrings[i];
				aktWeight += subStringWeights[i];
				if( i == subStrings.length - 1 )
					break;
				if( (aktWeight + subStringWeights[i+1]) > (1.0f / subLinesNeeded) ) {
					if( aktSubLine < subLines.length - 1 ) {
						aktWeight = 0.0f;
						aktSubLine++;
					}
				}
			}
		}

		// Bei immer noch zu große Zeilen muss die Font Größe editiert werden
		boolean correctSize = false;
		while(!correctSize) {
			correctSize = true;
			for( int i = 0; i < subLines.length; i++ ) {
				font = font.deriveFont((float)aktFontSize);
				int subLineWidth = FontDesignMetrics.getMetrics(font).stringWidth(subLines[i]);
				if( subLineWidth > maxLineWidth ) {
					aktFontSize +=- 1;
					correctSize = false;
					break;
				}
			}
		}

		// Zeichne Strings
		graphics.setColor(Color.BLACK);

		for( int subCol = 0; subCol < subLines.length; subCol++) {
			// hack: sollte schon vorher bereinigt werden -> keine 0 length Strings
			if(subLines[subCol].length() == 0)
				continue;
			AttributedString drawString = new AttributedString(subLines[subCol]);
			drawString.addAttribute(TextAttribute.FONT, font);
			int y = startY - ((subLines.length - (subCol + 1)) *  (aktFontSize + inset));
			int x = startX;

			textWidth = FontDesignMetrics.getMetrics(font).stringWidth(subLines[subCol]);
			int descent = FontDesignMetrics.getMetrics(font).getDescent();
			
			if( alignment == AL_CENTER )
				x = ((startX + maxLineWidth) / 2) - (textWidth / 2);
			if( alignment == AL_RIGHT )
				x = maxLineWidth - textWidth;

			graphics.setClip(x, y - aktFontSize, textWidth, (aktFontSize + descent));
			graphics.drawString(drawString.getIterator(), x, y);
		}
	}

	public int getInset() {
		return inset;
	}

	public void setInset(int inset) {
		this.inset = inset;
	}

	public int getMaxLineWidth() {
		return maxLineWidth;
	}

	public void setMaxLineWidth(int maxLineWidth) {
		this.maxLineWidth = maxLineWidth;
	}

	public int getMaxSubLines() {
		return maxSubLines;
	}

	public void setMaxSubLines(int maxSubLines) {
		this.maxSubLines = maxSubLines;
	}

	public int getStartFontSize() {
		return startFontSize;
	}

	public void setStartFontSize(int startFontSize) {
		this.startFontSize = startFontSize;
	}

	public int getStartX() {
		return startX;
	}

	public void setStartX(int startX) {
		this.startX = startX;
	}

	public int getStartY() {
		return startY;
	}

	public void setStartY(int startY) {
		this.startY = startY;
	}
	
	public Graphics2D getGraphics() {
		return graphics;
	}

	public void setGraphics(Graphics2D graphics) {
		this.graphics = graphics;
	}

	public int getAlignment() {
		return alignment;
	}

	public void setAlignment(int alignment) {
		this.alignment = alignment;
	}
}
 

SebiB90

Top Contributor
nur ein kurzer Kommentar beim überfliegen den Codes:

Code:
// Können nur soviele Zeilen existieren wie auch Leerzeichen 
         if(subStrings.length < subLinesNeeded) 
            subLinesNeeded = subStrings.length;
"Ein Leerzeichen"
->
"Ein
Leerzeichen"

Wie man sieht:
Code:
MaxZeilen = Leerzeichen+1
 

Marco13

Top Contributor
Erstmal zum letzgenannten Punkt: Das wird hakelig: Sobald man die Fontgröße ändert, ändern sich auch alle Umbrüche - d.h. wenn man merkt, dass die höhe nicht passt, muss man den Font kleiner machen und es nochmal versuchen.

Die ersten beiden sind ... ja, üblich. Da war auch schonmal ein Thread dazu ... http://www.java-forum.org/de/viewtopic.php?p=410253 (und bei der Suche eben habe ich festgestellt, dass ich dem Threadersteller damals nicht mehr geantwortet hatte :oops: ). Man kann sowas (wie dort auch schon steht) als "Kürzeste-Wege-Problem" beschreiben.
 

Mewel

Aktives Mitglied
@SebiB90
subStrings ist dann aber ein Array mit zwei Elementen:
"Ein"
"Leerzeichen"
subStrings.length is dann auch zwei.

Oder ich versteh deine Antwort grad nicht ^^?

@Marco13
Ja das mit der Fontgröße stimmt schon. Ist mir bisher noch nichts besseres eingefallen. Wahrscheinlich müsste ich das in einer Schleife laufen lassen. Das immer wenn die Fontgröße verkleinert wird, nochmal alle subStrings neu berechnet werden. Danach wieder mit der Zeilengröße vergleichen und gegebenfalls die Fontgröße ändern usw.

Den Thread und das "Kürzeste-Wege-Problem" werde ich mir mal genau anschauen.
 

Wildcard

Top Contributor
Du darfst keine Klassen aus Sun Packages verwenden!
Schau dir TextLayout und alles was dazu gehört an, damit lässt sich das umsetzen.
 

Marco13

Top Contributor
Hm. Kommt vielleicht drauf an, was man erreichen will. TextLayout und der "normale" LineBreakMeasurer verwenden (laut Doku) einen ziemlich einfachen Algorithmus, der mit vermutlich keinen "schönen" Ergebnisse liefert. Aber vielleicht reichen sie ja...
 

Wildcard

Top Contributor
Mit einigen Zeilen eigener Code sind wir damit zu einem gutem Ergebnis gekommen, ist also machbar.
 

Mewel

Aktives Mitglied
Ok, werd ich mir mal anschauen. Aber warum darf ich keine Klassen aus dem Sun Package verwenden? Gibts dafür nen speziellen Grund?
 

Marco13

Top Contributor
Die sind nicht Teil der offiziellen API. Jemand anderes könnte sich "sein eigenes Java" schreiben, das GENAU SO funktioniert, wie das von Sun - aber diese Klassen zufällig nicht enthält.
 

Mewel

Aktives Mitglied
Hab das jetzt mal getestet und funktioniert auch auf den ersten Blick recht gut. Leider gibt es ein Problem mit dem LineBreakMeasurer. Er gibt mir leider keine Infos darüber, ob der Zeilenumbruch in einem Wort passiert ist (Methode: nextOffset). In diesem Fall wollte ich erstmal die Fontsize verkleinern und danach nochmal den Zeilenumbruch testen.

Nun ist in der Klasse auch noch alles private und sie selbst final. Die Klasse zu kopieren und mit nem neuen Namen zu versehen erscheint mir ein wenig unsauber, zumal sie noch Abhängigkeiten zu CharArrayIterator und TextMeasurer hat, die auch private sind.

Jemand ne Idee?
 

Marco13

Top Contributor
Eigentlich müßte da jetzt ja Wildcard was dzu sagen :meld: :wink:
Ich hab auch noch NICHTS mit dem LineBreakMeasurer und dem TextLayout gemacht, aber beim ersten Block auf die API fällt die Methode
nextLayout(float wrappingWidth, int offsetLimit, boolean requireNextWord)
auf - müßte man damit nicht indirekt rauskriegen können, ob das, was man machen will, noch in die aktuelle Zeile passt?!
 

Mewel

Aktives Mitglied
Ja, das sieht gar nich schlecht aus. Hab ich doch glatt übersehen. Werd das dann gleich mal testen. Danke.
 
Status
Nicht offen für weitere Antworten.
Ähnliche Java Themen
  Titel Forum Antworten Datum
B Algorithmus für Arbeit mit fehlenden Listenelementen? Allgemeine Java-Themen 1
L Klassen Algorithmus für das folgende Problem entwickeln? Allgemeine Java-Themen 30
L Algorithmus für kürzesten Weg mit Wegpunkten Allgemeine Java-Themen 21
L Algorithmus für Poker-Hände Allgemeine Java-Themen 7
chik 2 return werte für Greedy-Algorithmus (gelöst) Allgemeine Java-Themen 3
C Algorithmus für Array Allgemeine Java-Themen 9
S Algorithmus für Sudoku Allgemeine Java-Themen 17
F Algorithmus für Sortierung gesucht Allgemeine Java-Themen 15
D Algorithmus für die Erkennung fehlerhafter Eingaben Allgemeine Java-Themen 4
schegga_B AES-Algorithmus in javax.crypto Allgemeine Java-Themen 3
M Laufzeit des Prim Algorithmus Allgemeine Java-Themen 3
O Newton Algorithmus Java Allgemeine Java-Themen 1
CptK Backpropagation Algorithmus Allgemeine Java-Themen 6
N Google Authenticator Algorithmus (SHA1) Allgemeine Java-Themen 1
gotzi242 Schatzsuche mithilfe eines O(log n) Algorithmus Allgemeine Java-Themen 2
Zrebna Quicksort-Algorithmus - zufälliges Pivot wählen Allgemeine Java-Themen 6
B Algorithmus Warteschlange Ringpuffer wirklich fehlerfrei Allgemeine Java-Themen 8
M Probleme mit Negamax-Algorithmus Allgemeine Java-Themen 29
F Q - Learning Algorithmus Bug Allgemeine Java-Themen 4
M Salesman Problem - Bruteforce Algorithmus Allgemeine Java-Themen 23
M Minmax Algorithmus Verständnisproblem Allgemeine Java-Themen 2
H Rundreise frage (Algorithmus) Allgemeine Java-Themen 18
F KMP-Algorithmus Allgemeine Java-Themen 9
S Algorithmus welcher True-Werte in einem Array findet und auswertet. Allgemeine Java-Themen 5
U Methoden Algorithmus MergeSort String [ ] array sortieren programmieren Allgemeine Java-Themen 17
P MinMax Algorithmus Allgemeine Java-Themen 0
J Abhängigkeit zwischen Rechenzeit und Speicherbedarf in einen Algorithmus Allgemeine Java-Themen 7
K Djikstra-Algorithmus Allgemeine Java-Themen 1
T Minimax/Alphabeta Algorithmus hängt sich auf (?) Allgemeine Java-Themen 2
M Algorithmus zum Zahlen einteilen Allgemeine Java-Themen 8
O Best Practice Hilfe bei Algorithmus gesucht Allgemeine Java-Themen 10
S Algorithmus um Objekte auf einer Flaeche mit gleichem Abstand anzuordnen..? Allgemeine Java-Themen 20
S Rucksackproblem und genetischer Algorithmus Allgemeine Java-Themen 9
L Abbruch des Algorithmus Allgemeine Java-Themen 8
D Input/Output Ausgleichen chemischer Reaktionsgleichungen mit dem Gauß-Algorithmus Allgemeine Java-Themen 2
Messoras A*-Algorithmus integrieren Allgemeine Java-Themen 3
S Buchscan 3D Dewarp Algorithmus - Ansätze Allgemeine Java-Themen 1
B Verteilungs-/Vergabe-Algorithmus mit abhängigen Score-Werten Allgemeine Java-Themen 3
Androbin "Shunting Yard"-Algorithmus Allgemeine Java-Themen 6
B Algorithmus - Project Euler Problem 18 Allgemeine Java-Themen 2
N Algorithmus zum bewerten von mathematischen Funktionen Allgemeine Java-Themen 11
O Algorithmus Optimierung Allgemeine Java-Themen 3
Joew0815 Algorithmus - Zahlenfolge in 4 ähnliche Teile aufteilen Allgemeine Java-Themen 0
O Tag Cloud Algorithmus Idee gesucht Allgemeine Java-Themen 2
A Implementierung eines Algorithmus (Farthest Insertion zur Lösung des TSP) in O(n²) Allgemeine Java-Themen 2
C Eclipse Probleme bei selbst erstelltem Algorithmus Allgemeine Java-Themen 2
H Graph-Algorithmus gesucht Allgemeine Java-Themen 21
N Algorithmus durch Workflow Allgemeine Java-Themen 7
M tree-based diff Algorithmus (Code-Vergleiche) Allgemeine Java-Themen 3
S Uhrzeit Algorithmus sale Allgemeine Java-Themen 11
N A*-Algorithmus Allgemeine Java-Themen 5
A Suche Algorithmus zum Erstellen eines planaren Graphen Allgemeine Java-Themen 5
F Methoden Algorithmus zur Gegnerfindung (Turnier) Allgemeine Java-Themen 9
T Algorithmus Graph Allgemeine Java-Themen 10
J Algorithmus gesucht (Stringtransformation) Allgemeine Java-Themen 4
B Algorithmus Krankenhausbelegung Allgemeine Java-Themen 17
S Algorithmus von Dijkstra Allgemeine Java-Themen 2
alex_fairytail OOP Banknoten Algorithmus Teil 2 Allgemeine Java-Themen 13
2 ArrayList aktualisieren Algorithmus Allgemeine Java-Themen 11
alex_fairytail Methoden Banknoten Algorithmus Allgemeine Java-Themen 10
R Codehinweise: Algorithmus Größenvergleich von n Zahlen Allgemeine Java-Themen 5
SuperSeppel13 WTF?! Algorithmus-Geschwindigkeitstest Allgemeine Java-Themen 2
C Algorithmus Problem in Minesweeper Allgemeine Java-Themen 5
S Algorithmus um Labyrinth zu erzeugen Allgemeine Java-Themen 6
V Problem mit A* Pathfinder-Algorithmus Allgemeine Java-Themen 2
S Algorithmus um nächst folgende Primzahl zu berechnen Allgemeine Java-Themen 7
S Algorithmus Problem. Rechtecke effizient auf Spielfeld anordnen. Allgemeine Java-Themen 7
C Algorithmus-Hilfe Allgemeine Java-Themen 20
J Algorithmus Längenkombinationen? Allgemeine Java-Themen 7
M Kombinationen über rekursiven Algorithmus berechnen? Allgemeine Java-Themen 10
D Abstruse Probleme mit eigenem replace Algorithmus Allgemeine Java-Themen 11
P RC4 Algorithmus Allgemeine Java-Themen 3
D RSA Verfahren - Erweiterter Euklidischer Algorithmus Allgemeine Java-Themen 4
C IBAN und Bic Validieren (Algorithmus) Allgemeine Java-Themen 10
P Problem mit A*-Algorithmus Allgemeine Java-Themen 12
M Wörter Algorithmus Allgemeine Java-Themen 7
K Postleitzahlen Algorithmus Allgemeine Java-Themen 12
G Problem mit Algorithmus Allgemeine Java-Themen 3
T Hilfe bei einem Algorithmus Allgemeine Java-Themen 2
S Stemming-Algorithmus gesucht (z.B. Porter) Allgemeine Java-Themen 2
RoliMG präfix zu infix algorithmus Allgemeine Java-Themen 6
Z A*-Algorithmus - Probleme mit offener/geschlossener Liste Allgemeine Java-Themen 7
S Javaimplementierung des MD5 Algorithmus Allgemeine Java-Themen 2
E Container-Pack-Algorithmus Allgemeine Java-Themen 4
G k nearest neighbor algorithmus Allgemeine Java-Themen 7
C HASH Algorithmus 2 Strings ergeben das Selbe. Allgemeine Java-Themen 2
P Page Rank Algorithmus implementieren Allgemeine Java-Themen 7
T Problem RSA-Algorithmus in Java? Allgemeine Java-Themen 2
minzel Hash-Algorithmus Allgemeine Java-Themen 9
Y komprimierung mittels Huffman-Algorithmus, bit-shifting. Allgemeine Java-Themen 2
K Algorithmus Allgemeine Java-Themen 10
I Verschlüsselung mit Pwd. - User soll Algorithmus wählen Allgemeine Java-Themen 4
J fällt euch ein Algorithmus ein? Allgemeine Java-Themen 4
N Euklidischer Algorithmus in Java und keine Terminierung. Allgemeine Java-Themen 7
T Algorithmus verbessern Allgemeine Java-Themen 10
U Suche Algorithmus zur bestimmung des längsten Wegs Allgemeine Java-Themen 3
U Ford-Fulkerson Algorithmus gesucht Allgemeine Java-Themen 1
U Dijkstra Algorithmus gesucht Allgemeine Java-Themen 4
I hash-algorithmus Allgemeine Java-Themen 9
kodela Eingabe für TextArray bedingt sperren Allgemeine Java-Themen 3

Ähnliche Java Themen

Neue Themen


Oben