Merci à l'indice Epaga et quelques exemples sur le Net (pas si évident à trouver! J'ai utilisé principalement Break a Line for text layout), je pourrais faire un composant pour afficher le texte enveloppé. C'est incomplet, mais au moins cela montre l'effet recherché.
class TextContainer extends JPanel
{
private int m_width;
private int m_height;
private String m_text;
private AttributedCharacterIterator m_iterator;
private int m_start;
private int m_end;
public TextContainer(String text, int width, int height)
{
m_text = text;
m_width = width;
m_height = height;
AttributedString styledText = new AttributedString(text);
m_iterator = styledText.getIterator();
m_start = m_iterator.getBeginIndex();
m_end = m_iterator.getEndIndex();
}
public String getText()
{
return m_text;
}
public Dimension getPreferredSize()
{
return new Dimension(m_width, m_height);
}
public void paint(Graphics g)
{
super.paintComponent(g);
Graphics2D g2 = (Graphics2D) g;
FontRenderContext frc = g2.getFontRenderContext();
LineBreakMeasurer measurer = new LineBreakMeasurer(m_iterator, frc);
measurer.setPosition(m_start);
float x = 0, y = 0;
while (measurer.getPosition() < m_end)
{
TextLayout layout = measurer.nextLayout(m_width);
y += layout.getAscent();
float dx = layout.isLeftToRight() ?
0 : m_width - layout.getAdvance();
layout.draw(g2, x + dx, y);
y += layout.getDescent() + layout.getLeading();
}
}
}
Juste pour le plaisir, je l'ai fait convenable un cercle (hélas, aucune justification, il semble):
public void paint(Graphics g)
{
super.paintComponent(g);
Graphics2D g2 = (Graphics2D) g;
FontRenderContext frc = g2.getFontRenderContext();
LineBreakMeasurer measurer = new LineBreakMeasurer(m_iterator, frc);
measurer.setPosition(m_start);
float y = 0;
while (measurer.getPosition() < m_end)
{
double ix = Math.sqrt((m_width/2 - y) * y);
float x = m_width/2.0F - (float) ix;
int width = (int) ix * 2;
TextLayout layout = measurer.nextLayout(width);
y += layout.getAscent();
float dx = layout.isLeftToRight() ?
0 : width - layout.getAdvance();
layout.draw(g2, x + dx, y);
y += layout.getDescent() + layout.getLeading();
}
}
Je ne suis pas sûr de calcul dx, cependant.
Je l'ai déjà eu. Mon problème est, je ne veux pas un rectangle autour du texte, mais le texte à l'intérieur d'un rectangle donné. – Burkhard
Notez que le constructeur de TextLayout, non documenté, lève une exception si la chaîne que vous passez est vide. –
Utilisez \t Forme labelShape = textLayout1.getOutline (null); puis g2d.fill (labelShape); ils devraient éliminer la frontière – mk7