Geht doch nichts über eine genaue Beschreibung der Anforderungen von Anfang an
Den Zeilenumbruch kann man im einfachsten Fall selbst reindengeln. Allerdings kann das natürlich beliebig kompliziert werden, wenn die Zeilenumbrüche automatisch auf Basis des verfügbaren Platzes gefunden werden sollen. Natürlich ist das alles möglich, aber … ab einem bestimmten Punkt sollte man nicht mehr versuchen, diese Funktionalität (die nichts mehr mit „rotierendem Text“ zu tun hat) in dieses Pseudo3DText-Beispiel reinzudengeln, sondern sich ein standalone-Beispiel zu machen, mit einer Methode wie
String[] splitIntoLines(Font font, String string, float availableWidth) { ... }
Ob man das dann in dieser Methode „selbst“ macht, oder eine TextArea verwendet, die einem diese umbrüche schon berechnet, muss man sich dann überlegen.
Wenn es nur darum geht, einen String in mehrere Zeilen aufzuteilen, wenn er explizit angegebene Zeilenumbrüche "
" enthält, wäre das noch einfach. Aber alles darüber hinausgehende sollte man vermutlich getrennt davon besprechen…
import java.awt.Font;
import java.awt.Graphics;
import java.awt.Graphics2D;
import java.awt.GridLayout;
import java.awt.RenderingHints;
import java.awt.Shape;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.font.FontRenderContext;
import java.awt.font.GlyphVector;
import java.awt.geom.AffineTransform;
import java.awt.geom.Path2D;
import java.awt.geom.Rectangle2D;
import javax.swing.JFrame;
import javax.swing.JPanel;
import javax.swing.SwingUtilities;
import javax.swing.Timer;
public class Pseudo3DText
{
public static void main(String[] args)
{
SwingUtilities.invokeLater(new Runnable()
{
@Override
public void run()
{
createAndShowGUI();
}
});
}
private static void createAndShowGUI()
{
JFrame frame = new JFrame();
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.getContentPane().setLayout(new GridLayout(1, 1));
Pseudo3DTextPanel p = new Pseudo3DTextPanel();
startAnimation(p);
frame.getContentPane().add(p);
frame.setSize(800, 300);
frame.setLocationRelativeTo(null);
frame.setVisible(true);
}
private static void startAnimation(final Pseudo3DTextPanel p)
{
Timer timer = new Timer(40, new ActionListener()
{
double angleRad = 0.0;
@Override
public void actionPerformed(ActionEvent e)
{
angleRad += 0.1;
p.setAngle(angleRad);
}
});
timer.start();
}
}
class Pseudo3DTextPanel extends JPanel
{
private double angleRad = 0;
void setAngle(double angleRad)
{
this.angleRad = angleRad;
repaint();
}
@Override
protected void paintComponent(Graphics gr)
{
super.paintComponent(gr);
Graphics2D g = (Graphics2D)gr;
g.setRenderingHint(
RenderingHints.KEY_ANTIALIASING,
RenderingHints.VALUE_ANTIALIAS_ON);
String string = "Not rotating
Multiline";
Font font = g.getFont().deriveFont(100.0f);
g.setFont(font);
AffineTransform oldAT = g.getTransform();
g.translate(400, 100);
double scaling = Math.cos(angleRad);
g.scale(scaling, 1.0);
g.fill(createMultilineShape(font, string));
g.setTransform(oldAT);
}
public static Shape createMultilineShape(Font font, String string)
{
final FontRenderContext fontRenderContext =
new FontRenderContext(null, true, true);
Path2D path = new Path2D.Double();
String lines[] = string.split("
");
double offsetY = 0;
for (String line : lines)
{
GlyphVector glyphVector = font.createGlyphVector(
fontRenderContext, line);
Shape lineShape = glyphVector.getOutline(0,0);
AffineTransform at =
AffineTransform.getTranslateInstance(0, offsetY);
path.append(lineShape.getPathIterator(at), false);
offsetY += lineShape.getBounds().height;
}
return center(path);
}
/**
* Create a shape for the given string with the given
* font, centered at the origin.
*
* @param font The font
* @param string The string
* @return The shape for the string
*/
public static Shape createShape(Font font, String string)
{
final FontRenderContext fontRenderContext =
new FontRenderContext(null, true, true);
GlyphVector glyphVector = font.createGlyphVector(
fontRenderContext, string);
Shape shape = glyphVector.getOutline(0,0);
return center(shape);
}
private static Shape center(Shape shape)
{
Rectangle2D bounds = shape.getBounds2D();
double cx = bounds.getCenterX();
double cy = bounds.getCenterY();
AffineTransform at =
AffineTransform.getTranslateInstance(-cx, -cy);
return at.createTransformedShape(shape);
}
}