java - pasos - Cómo generar una cadena en múltiples líneas usando gráficos
swing containers (5)
Mi programa anula public void paint(Graphics g, int x, int y);
para dibujar algunas picaduras usando g.drawString(someString, x+10, y+30);
Ahora someString puede ser bastante largo y, por lo tanto, puede que no encaje en una línea.
¿Cuál es la mejor manera de escribir el texto en múltiples líneas?
Por ejemplo, en un rectángulo (x1, y1, x2, y2)?
Construye incrementalmente tu cuerda, una palabra a la vez, usando el método de Epaga para encontrar la longitud de tu cuerda. Una vez que la longitud es más larga que su rectángulo, elimine la última palabra e imprima. Repite hasta que te quedes sin palabras.
Suena como un mal algoritmo, pero para cada línea, es realmente O (screenWidth / averageCharacterWidth) => O (1).
Aún así, use un StringBuffer para construir su cadena.
Gracias a la sugerencia de Epaga y un par de ejemplos en la red (no tan obvio de encontrar! Usé principalmente Break a Line para el diseño de texto ), pude hacer un componente para mostrar el texto envuelto. Está incompleto, pero al menos muestra el efecto deseado.
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();
}
}
}
Solo por diversión, hice que encajara en un círculo (¡ay !, no hay justificación, parece):
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();
}
}
Aunque no estoy muy seguro acerca de la computación dx.
Puede usar un JLabel e incrustar el texto con html.
JLabel.setText("<html>"+line1+"<br>"+line2);
java.awt.font.TextLayout podría ser útil. Aquí hay un fragmento de su código de ejemplo:
Graphics2D g = ...;
Point2D loc = ...;
Font font = Font.getFont("Helvetica-bold-italic");
FontRenderContext frc = g.getFontRenderContext();
TextLayout layout = new TextLayout("This is a string", font, frc);
layout.draw(g, (float)loc.getX(), (float)loc.getY());
Rectangle2D bounds = layout.getBounds();
bounds.setRect(bounds.getX()+loc.getX(),
bounds.getY()+loc.getY(),
bounds.getWidth(),
bounds.getHeight());
g.draw(bounds);
De lo contrario, siempre puedes utilizar un elemento de texto Swing para hacer el trabajo por ti, simplemente pasa los gráficos en los que quieras pintar.
Tuve un problema yo esta es mi solución:
Graphics2D g=....
FontRenderContext frc = g.getFontRenderContext();
TextLayout layout = new TextLayout(text, font, frc);
String[] outputs = text.split("/n");
for(int i=0; i<outputs.length; i++){
g.drawString(outputs[i], 15,(int) (15+i*layout.getBounds().getHeight()+0.5));
Espero que ayude ... simple pero funciona.