java 如何使用图形在多行上输出字符串
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/239537/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
How to output a String on multiple lines using Graphics
提问by Burkhard
My Program overrides public void paint(Graphics g, int x, int y);in order to draw some stings using g.drawString(someString, x+10, y+30);
我的程序覆盖public void paint(Graphics g, int x, int y);以便使用g.drawString(someString, x+10, y+30);
Now someString can be quite long and thus, it may not fit on one line.
现在 someString 可能很长,因此它可能不适合一行。
What is the best way to write the text on multiple line.
For instance, in a rectangle (x1, y1, x2, y2)?
在多行上编写文本的最佳方法是什么。
例如,在一个矩形 (x1, y1, x2, y2) 中?
采纳答案by PhiLho
Thanks to Epaga's hint and a couple of examples on the Net (not so obvious to find! I used mainly Break a Line for text layout), I could make a component to display wrapped text. It is incomplete, but at least it shows the intended effect.
多亏了 Epaga 的提示和网络上的几个例子(不是很明显!我主要使用Break a Line 进行文本布局),我可以制作一个组件来显示换行的文本。它是不完整的,但至少它显示了预期的效果。
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();
}
}
}
Just for fun, I made it fitting a circle (alas, no justification, it seems):
只是为了好玩,我让它适合一个圆圈(唉,似乎没有理由):
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();
}
}
I am not too sure about dx computation, though.
不过,我对 dx 计算不太确定。
回答by Epaga
java.awt.font.TextLayoutmight be helpful. Here's a snippet of their example code:
java.awt.font.TextLayout可能会有所帮助。这是他们的示例代码的片段:
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);
Otherwise you could always use a Swing text element to do the job for you, just pass in the Graphics you want it to paint into.
否则,您始终可以使用 Swing 文本元素为您完成这项工作,只需传入您希望它绘制的图形即可。
回答by Ryan Fox
Incrementally build your string, one word at a time, using Epaga's method to find the length of your string. Once the length is longer than your rectangle, remove the last word and print. Repeat until you run out of words.
使用 Epaga 的方法来查找字符串的长度,一次一个单词地逐步构建您的字符串。一旦长度超过矩形,删除最后一个单词并打印。重复直到你用完单词。
It sounds like a bad algorithm, but for each line, it's really O(screenWidth/averageCharacterWidth) => O(1).
这听起来像一个糟糕的算法,但对于每一行,它实际上是 O(screenWidth/averageCharacterWidth) => O(1)。
Still, use a StringBuffer to build your string!
仍然,使用 StringBuffer 来构建您的字符串!
回答by msj121
Had some trouble myself this is my solution:
我自己遇到了一些麻烦,这是我的解决方案:
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));
Hope that helps.... simple but it works.
希望有所帮助.... 简单但有效。
回答by michelemarcon
You can use a JLabel and embed the text with html.
您可以使用 JLabel 并使用 html 嵌入文本。
JLabel.setText("<html>"+line1+"<br>"+line2);

