2016-07-25 5 views
0

特定のテキストとスタイルで画像を作成しようとしています。例えば;イメージを複数のフォントでJavaでラップして書き込む

「TEXTSTYLE(オファーが25/12/2016を終了します。除外を適用します。、免責事項)TEXTSTYLE(下線、詳細を参照してください)」上記の行で

私は分裂だとTEXTSTYLEの最初のパラメータを保存するマップを作成します第2パラメータが最初のパラメータに適用されるスタイルを定義する場合は、keyとしてブロックし、2番目のパラメータをvalueとしてブロックします。したがって、マップのエントリは、次のようになります。

このマップを繰り返してイメージにテキストを書き込むと、テキストが幅をオーバーフローしているかどうかが確認されます。そうであれば、それはテキストを分割し、それを水平中心の次の行に追加する。たとえば、「Offer ends 25/12/2016。Exclusions Apply」と書いてみたいと言っています。 Arialとフォントサイズ12.私が書いている間、私は "Offer ends 23/12/2016。"と "Exclusions apply"が次の行に書き込まれるまで書くことができます。しかし、それは、横にスペースがあるので、同じ行に「詳細を見る」と書くことができないということを無視して、テキストを水平の中心に書き出します。

助けてください。以下は私が試したコードです。私はまた、JTextPaneを作成してイメージに変換しようとしましたが、最初にフレームを作成し、それを可視にして書き込み、それを破棄するので、これをオプションにすることはできません。そして、ほとんどの時間私はSwingUtilities.invokeAndWaitでNullpointer例外を取得していました。

実際: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; 
} 
+0

なぜ 'JTextPane'を使用しないのですか? – trashgod

+0

JTextPaneは、最初にフレームを作成し、それを表示し、書き込みしてから処理するため、オプションにすることはできません。私はそのポップアップが来て消えないようにしたい。私はjtextpaneを使用して私が使用したコードを添付しました。それを確認します。そして、ほとんどの時間私はSwingUtilities.invokeAndWaitでNullpointer例外を取得していました。 – user973179

+0

ペインを表示せずに検証することができます([こちら](http://stackoverflow.com/a/13139308/230513))。 [* Initial Threads *](http://docs.oracle.com/javase/tutorial/uiswing/concurrency/initial.html)も参照してください。 – trashgod

答えて

0

私は問題があなたの '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'値は同じです。

preループの外側に高さを宣言します。次の操作を行います。

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

コメントに基づいて、機能を2つの小さな機能に分解することをお勧めします。

// 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 
+0

ええ、それは正しいですが、私は解決したい問題ではありません。私がここで解決したい問題は、ラインがオーバーフローすると分かると、それが分割されるということです。だから、2行目から2行目を書き出すときに、次の文字列、つまり「詳細を見る」も処理しなければならないので、次の行に送るのではなく、同じ行に格納することもできます。あなたが言及した問題を解決する私の更新されたコードを見てください。 – user973179

+0

あなたの投稿を期待どおりに更新してください。 (おそらくあなたは "コード"の書式を使用することができます)..それを明確にする。 – Vivasaayi

+0

私は広告イメージへの評判を持っていませんが、私が追加したリンクを参照してください – user973179

関連する問題