使用Java,是否有任何内置的方式来呈现文本,使其仅限于graphics2D
对象上的矩形?
我知道我可以使用Graphics2D.drawString
,但它只会画出一行文字。
我也知道我可以使用
FontMetrics fm= graphics.getFontMetrics(font);
Rectangle2D rect=fm.getStringBounds("Some Text",graphics);
在某些Font font
对象上使用某些Graphics2D graphics
呈现时获取有关字符串边界的信息。
所以我可以开始循环,打破我的字符串等等以强制它适合某个矩形。
但我更不愿意写那些......
有没有现成的功能可以帮我吗?
答案 0 :(得分:6)
我写了一个可以提供帮助的小功能。 447是可用宽度,您可以从所需宽度获得以呈现文本。
private void drawTextUgly(String text, FontMetrics textMetrics, Graphics2D g2)
{
// Ugly code to wrap text
int lineHeight = textMetrics.getHeight();
String textToDraw = text;
String[] arr = textToDraw.split(" ");
int nIndex = 0;
int startX = 319;
int startY = 113;
while ( nIndex < arr.length )
{
String line = arr[nIndex++];
while ( ( nIndex < arr.length ) && (textMetrics.stringWidth(line + " " + arr[nIndex]) < 447) )
{
line = line + " " + arr[nIndex];
nIndex++;
}
GraphicsUtility.drawString(g2, line, startX, startY);
startY = startY + lineHeight;
}
}
答案 1 :(得分:4)
这可能就是你要找的东西:
<强> StringUtils.java:强>
import java.awt.FontMetrics;
import java.util.ArrayList;
import java.util.Collection;
import java.util.Iterator;
import java.util.List;
/**
* Globally available utility classes, mostly for string manipulation.
*
* @author Jim Menard, <a href="mailto:jimm@io.com">jimm@io.com</a>
*/
public class StringUtils {
/**
* Returns an array of strings, one for each line in the string after it has
* been wrapped to fit lines of <var>maxWidth</var>. Lines end with any of
* cr, lf, or cr lf. A line ending at the end of the string will not output a
* further, empty string.
* <p>
* This code assumes <var>str</var> is not <code>null</code>.
*
* @param str
* the string to split
* @param fm
* needed for string width calculations
* @param maxWidth
* the max line width, in points
* @return a non-empty list of strings
*/
public static List wrap(String str, FontMetrics fm, int maxWidth) {
List lines = splitIntoLines(str);
if (lines.size() == 0)
return lines;
ArrayList strings = new ArrayList();
for (Iterator iter = lines.iterator(); iter.hasNext();)
wrapLineInto((String) iter.next(), strings, fm, maxWidth);
return strings;
}
/**
* Given a line of text and font metrics information, wrap the line and add
* the new line(s) to <var>list</var>.
*
* @param line
* a line of text
* @param list
* an output list of strings
* @param fm
* font metrics
* @param maxWidth
* maximum width of the line(s)
*/
public static void wrapLineInto(String line, List list, FontMetrics fm, int maxWidth) {
int len = line.length();
int width;
while (len > 0 && (width = fm.stringWidth(line)) > maxWidth) {
// Guess where to split the line. Look for the next space before
// or after the guess.
int guess = len * maxWidth / width;
String before = line.substring(0, guess).trim();
width = fm.stringWidth(before);
int pos;
if (width > maxWidth) // Too long
pos = findBreakBefore(line, guess);
else { // Too short or possibly just right
pos = findBreakAfter(line, guess);
if (pos != -1) { // Make sure this doesn't make us too long
before = line.substring(0, pos).trim();
if (fm.stringWidth(before) > maxWidth)
pos = findBreakBefore(line, guess);
}
}
if (pos == -1)
pos = guess; // Split in the middle of the word
list.add(line.substring(0, pos).trim());
line = line.substring(pos).trim();
len = line.length();
}
if (len > 0)
list.add(line);
}
/**
* Returns the index of the first whitespace character or '-' in <var>line</var>
* that is at or before <var>start</var>. Returns -1 if no such character is
* found.
*
* @param line
* a string
* @param start
* where to star looking
*/
public static int findBreakBefore(String line, int start) {
for (int i = start; i >= 0; --i) {
char c = line.charAt(i);
if (Character.isWhitespace(c) || c == '-')
return i;
}
return -1;
}
/**
* Returns the index of the first whitespace character or '-' in <var>line</var>
* that is at or after <var>start</var>. Returns -1 if no such character is
* found.
*
* @param line
* a string
* @param start
* where to star looking
*/
public static int findBreakAfter(String line, int start) {
int len = line.length();
for (int i = start; i < len; ++i) {
char c = line.charAt(i);
if (Character.isWhitespace(c) || c == '-')
return i;
}
return -1;
}
/**
* Returns an array of strings, one for each line in the string. Lines end
* with any of cr, lf, or cr lf. A line ending at the end of the string will
* not output a further, empty string.
* <p>
* This code assumes <var>str</var> is not <code>null</code>.
*
* @param str
* the string to split
* @return a non-empty list of strings
*/
public static List splitIntoLines(String str) {
ArrayList strings = new ArrayList();
int len = str.length();
if (len == 0) {
strings.add("");
return strings;
}
int lineStart = 0;
for (int i = 0; i < len; ++i) {
char c = str.charAt(i);
if (c == '\r') {
int newlineLength = 1;
if ((i + 1) < len && str.charAt(i + 1) == '\n')
newlineLength = 2;
strings.add(str.substring(lineStart, i));
lineStart = i + newlineLength;
if (newlineLength == 2) // skip \n next time through loop
++i;
} else if (c == '\n') {
strings.add(str.substring(lineStart, i));
lineStart = i + 1;
}
}
if (lineStart < len)
strings.add(str.substring(lineStart));
return strings;
}
}
你把它放在自己的课堂上,然后简单地使用你拥有的东西:
FontMetrics fm= graphics.getFontMetrics(font);
Rectangle2D rect=fm.getStringBounds("Some Text",graphics);
致电wrap(String str, FontMetrics fm, int maxWidth)
,该List
会返回String
maxWidth
个已Rectangle2D
的{{1}}个String text="Some Text";
FontMetrics fm= graphics.getFontMetrics(font);
Rectangle2D rect=fm.getStringBounds(text,graphics);
List<String> textList=StringUtils.wrap(text, fm, int maxWidth);
相应的{{1}} {{1}}宽度{{1}}文字将被放入:
{{1}}
<强>参考:强>
答案 2 :(得分:4)
请参阅this answer中的LabelRenderTest
来源。它使用HTML / CSS,使用CSS设置主体宽度,从而自动换行。
答案 3 :(得分:1)
private List<String> wrap(String txt, FontMetrics fm, int maxWidth){
StringTokenizer st = new StringTokenizer(txt) ;
List<String> list = new ArrayList<String>();
String line = "";
String lineBeforeAppend = "";
while (st.hasMoreTokens()){
String seg = st.nextToken();
lineBeforeAppend = line;
line += seg + " ";
int width = fm.stringWidth(line);
if(width < maxWidth){
continue;
}else { //new Line.
list.add(lineBeforeAppend);
line = seg + " ";
}
}
//the remaining part.
if(line.length() > 0){
list.add(line);
}
return list;
}
答案 4 :(得分:1)
使用临时 JTextArea 用约 10 行代码完成完美的换行:
static void drawWrappedText(Graphics g, String text, int x, int y, int w, int h) {
JTextArea ta = new JTextArea(text);
ta.setLineWrap(true);
ta.setWrapStyleWord(true);
ta.setBounds(0, 0, w, h);
ta.setForeground(g.getColor());
ta.setFont(g.getFont());
Graphics g2 = g.create(x, y, w, h); // Use new graphics to leave original graphics state unchanged
ta.paint(g2);
}