有 Java 编程相关的问题?

你可以在下面搜索框中键入要查询的问题!

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) 个答案

  1. # 1 楼答案

    我怀疑问题出在你的“Y”计算中

    int spaceOfLineHeight = (newTextList.size() - 1) * 7;
    int spaceOfText = newTextList.size() * font.getSize();
    int totalSpace = spaceOfLineHeight + spaceOfText;
    int marginRemaining = height - totalSpace;
    
    int tempHt = marginRemaining / 2 + 10;
    

    必须保持前几行占据的高度,并将其添加到当前的“Y”

    目前,对于所有行,“Y”值都是相同的

    在for循环外声明prevHeight。然后执行以下操作

    int tempHt = marginRemaining / 2 + 10;
    tempHT += prevHeight;
    prevHeight = tempHeight
    

    基于这些评论,我建议您将函数分解为两个较小的函数

    // Loop through the strings and find out how lines are split and calculate the X, Y 
    // This function will give the expected lines
    
    splitLinesAndComputeResult
    
    // Just render the lines
    renderLines