swing以多种字体将文本写入图像,并使用java包装
我试图用给定的文本和样式创建一个图像。例如
“textStyle(优惠结束于2016年12月25日。除外条款适用,免责声明)textStyle(详情请参见下划线)”
在上面的一行中,我正在拆分并创建一个映射,该映射将textStyle块的第一个参数存储为键,第二个参数存储为值,其中第二个参数定义要应用于第一个参数的样式。因此,map的条目看起来像
现在,当我在这个地图上迭代,将文本写入图像时,我会检查文本是否溢出宽度。如果是,则它会打断文本并将其添加到水平中心的下一行。例如,让我们假设我正在尝试写“报价截止2016年12月25日。排除适用。”使用Arial字体,字体大小为12。在写作过程中,我发现我可以一直写作到“报价截止2016年12月23日”只有“排除适用”必须放在下一行。但它把文本写在水平中心,忽略了水平方向上还有空间,所以我也可以在同一行中写“查看详细信息”
请帮忙。下面是我尝试过的代码。我也尝试过创建一个JTextPane,然后将其转换为图像,但这不是一个选项,因为它首先创建帧,使其可见,写入帧,然后处理帧。大多数时候,我在SwingUtilities上都遇到了Nullpointer异常。调用EANDWAIT
实际:http://imgur.com/7aIlcEQ 应为http://imgur.com/038zQTZ
public static BufferedImage getTextImage(String textWithoutStyle, Map<String, String> textToThemeMap, Properties prop, int height, int width) {
BufferedImage img = new BufferedImage(width,height,BufferedImage.TYPE_4BYTE_ABGR);
Graphics2D g2d = img.createGraphics();
g2d.setPaint(Color.WHITE);
FontMetrics fm = g2d.getFontMetrics();
Map<String, Font> textToFontMap = new LinkedHashMap<String, Font>();
for(Map.Entry<String, String> entry : textToThemeMap.entrySet()) {
if(StringUtils.isNotBlank(entry.getKey()) && StringUtils.isNotBlank(entry.getValue())) {
Font font = getFont(prop, entry.getValue().trim());
g2d.setFont(font);
fm = g2d.getFontMetrics();
String string = entry.getKey();
char[] chars = null;
int i = 0, pixelWidth = 0;
List<String> newTextList = new ArrayList<String>();
if(fm.stringWidth(string) > (width - 10)) {
chars = string.toCharArray();
for (i = 0; i < chars.length; i++) {
pixelWidth = pixelWidth + fm.charWidth(chars[i]);
if(pixelWidth >= (width - 10)) {
break;
}
}
String newString = WordUtils.wrap(string, i, "\n",false);
String[] splitString = newString.split("\n");
for(String str : splitString) {
newTextList.add(str);
textToFontMap.put(string, font);
}
} else {
newTextList.add(string);
textToFontMap.put(string, font);
}
}
}
Font font = new Font("Arial", Font.BOLD, 14);
int spaceOfLineHeight = (textToFontMap.size() - 1) * 7;
int spaceOfText = textToFontMap.size() * font.getSize();
int totalSpace = spaceOfLineHeight + spaceOfText ;
int marginRemaining = height - totalSpace;
int tempHt = marginRemaining / 2 + 10;
String txt = null;
for(Map.Entry<String, Font> entry : textToFontMap.entrySet()) {
txt = entry.getKey();
font = entry.getValue();
g2d.setFont(font);
fm = g2d.getFontMetrics();
int x = (width - fm.stringWidth(txt)) / 2;
int y = tempHt;
g2d.drawString(txt, x, y);
tempHt = tempHt + fm.getHeight();
}
// g2d.drawString(text.getIterator(), 0, (int)lm.getAscent() + lm.getHeight());
// g2d.dispose();
return img;
}
// Code with JTextPane ------------------------------------------
public static BufferedImage getTextImage(final Map < String, String > textToThemeMap, final Properties prop, final int height, final int width) throws Exception {
JFrame f = new JFrame();
f.setSize(width, height);
final StyleContext sc = new StyleContext();
DefaultStyledDocument doc = new DefaultStyledDocument(sc);
final JTextPane pane = new JTextPane(doc);
pane.setSize(width, height);
// Build the styles
final Paragraph[] content = new Paragraph[1];
Run[] runArray = new Run[textToThemeMap.size()];
int i = 0;
for (Map.Entry < String, String > entry: textToThemeMap.entrySet()) {
if (StringUtils.isNotBlank(entry.getValue().trim()) && StringUtils.isNotBlank(entry.getKey().trim())) {
Run run = new Run(entry.getValue().trim(), entry.getKey());
runArray[i++] = run;
}
}
content[0] = new Paragraph(null, runArray);
/*createDocumentStyles(sc, prop,textToThemeMap.values());
addText(pane, sc, sc.getStyle("default"), content);
pane.setEditable(false);*/
try {
SwingUtilities.invokeAndWait(new Runnable() {
public void run() {
try {
createDocumentStyles(sc, prop, textToThemeMap.values());
} catch (MalformedURLException e) {
//e.printStackTrace();
}
addText(pane, sc, sc.getStyle("default"), content);
pane.setEditable(false);
}
});
} catch (Exception e) {
System.out.println("Exception when constructing document: " + e);
}
f.getContentPane().add(pane);
f.setVisible(true);
f.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
BufferedImage img = new BufferedImage(width, height, BufferedImage.TYPE_4BYTE_ABGR);
Graphics2D gd = img.createGraphics();
f.paint(gd);
f.dispose();
/*ImageIO.write(img, "png", new File("C:\\Users\\spande0\\Desktop\\a.png"));
System.out.println("done");*/
return img;
}
# 1 楼答案
我怀疑问题出在你的“Y”计算中
必须保持前几行占据的高度,并将其添加到当前的“Y”
目前,对于所有行,“Y”值都是相同的
在for循环外声明prevHeight。然后执行以下操作
基于这些评论,我建议您将函数分解为两个较小的函数