2016-07-25 35 views
0

Ich versuche, ein Bild mit einem gegebenen Text und Stil zu erstellen. z.B;Schreibe Text in Bild in mehreren Schriften mit Wrapping in Java

„Textart (Angebot endet am 25/12/2016. Ausschlüsse gelten., Haftungsausschluss) Textart (Details siehe, unterstrichen)“

In über der Linie i am Aufspalten und eine Karte erstellen, die den ersten Parameter von Textart speichert Block als Schlüssel und zweiter Parameter als Wert, wobei zweiter Parameter den auf den ersten Parameter anzuwendenden Stil definiert. Daher wird ein Eintrag der Karte aussehen.

Wenn ich jetzt über diese Map iteriere, um den Text zu schreiben, überprüfe ich, ob der Text die Breite überläuft. Wenn ja, unterbricht es den Text und fügt ihn der nächsten Zeile im horizontalen Zentrum hinzu. Nehmen wir zum Beispiel an, ich versuche zu schreiben "Angebot endet am 25/12/2016. Ausschlüsse gelten." mit Arial und Schriftgröße 12. Während des Schreibens finde ich, dass ich schreiben kann, bis "Angebot endet 23.12.2016." nur und "Ausschlüsse gelten" muss in nächste Zeile gehen. Aber es schreibt den Text in horizontaler Mitte, wobei vernachlässigt wird, dass, da horizontal noch Platz ist, ich auch "See Details" in derselben Zeile schreiben kann.

Bitte helfen. Unten ist der Code, den ich versucht habe. Ich habe auch versucht, ein JTextPane zu erstellen und es dann in Bild zu konvertieren, aber das kann keine Option sein, da es zuerst den Rahmen erstellt, es sichtbar macht, es schreibt und dann disposed. Und die meiste Zeit bekam ich eine Nullpointer-Ausnahme auf SwingUtilities.invokeAndWait.

Aktuell: http://imgur.com/7aIlcEQ http://imgur.com/038zQTZ Erwartete

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

Warum nicht ein 'JTextPane' verwenden? – trashgod

+0

JTextPane kann keine Option sein, da es zuerst den Rahmen erstellt, sichtbar macht, schreibt und dann entsorgt. Ich möchte nicht, dass Popup erscheint und verschwindet. Ich habe den Code, den ich verwendet habe, an jtextpane angehängt. Prüfe das. Und die meiste Zeit bekam ich eine Nullpointer-Ausnahme auf SwingUtilities.invokeAndWait. – user973179

+0

Sie können das Fenster überprüfen, ohne es sichtbar zu machen, wie [hier] vorgeschlagen (http://stackoverflow.com/a/13139308/230513); Siehe auch [* Initial Threads *] (http://docs.oracle.com/javase/tutorial/uiswing/concurrency/initial.html). – trashgod

Antwort

0

Ich vermute, dass das Problem in Ihrer 'Y' Berechnung ist.

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; 

Sie haben die Höhe von den vorherigen Linien besetzt zu halten und es zu dem aktuell ‚Y‘ hinzuzufügen.

Im Moment sind für alle Linien die Y-Werte gleich.

Deklarieren Sie prevHeight außerhalb der for-Schleife. und dann folgendes tun.

Basierend auf den Kommentaren, werde ich vorschlagen, dass Sie Ihre Funktion in zwei kleinere Funktionen aufgliedern.

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

Ja, das stimmt, aber das ist nicht das Problem, das ich lösen möchte. Problem, das ich hier lösen möchte, ist, dass, wenn es herausfindet, dass die Linie überläuft, es es teilt. Wenn also die zweite Zeile von der Teilung geschrieben wird, sollte sie sich um die nächste Zeichenfolge kümmern, d. H. "Details anzeigen", da sie auch in derselben Zeile untergebracht werden kann, anstatt sie zur nächsten Zeile zu senden. Sehen Sie sich meinen aktualisierten Code an, der das von Ihnen erwähnte Problem löst. – user973179

+0

Können Sie Ihren Beitrag bitte mit den erwarteten und tatsächlichen Werten aktualisieren? (wahrscheinlich können Sie "Code" Formatierung verwenden). Nur um es klar zu machen. – Vivasaayi

+0

Ich habe keinen Ruf, um Bilder zu ads, bitte sehen Sie die Links, die ich hinzugefügt habe – user973179