0

I'm trying to save text from a JEditorPane as a pdf once a save button is clicked.

saveAs.addActionListener(new ActionListener() {
        @Override
        public void actionPerformed(ActionEvent e) {

            String title = JOptionPane.showInputDialog(null, "Enter a name for file...");
            try{
                paintToPDF(newBlanktoEdit, title);
            }catch (Exception exc){
                exc.printStackTrace();
            }
        }
    });

The method paintToPDF does the job correctly, however the Pane is parsed as a graphics2D component, and so wrapping the line is not possible.

protected void paintToPDF(JEditorPane newPane, String title) throws Exception{

    newPane.setBounds(0, 0, (int) convertToPixels(612 - 58), (int) convertToPixels(792 - 60));

    Document doc = new Document();
    FileOutputStream out = new FileOutputStream(title + ".pdf");
    PdfWriter writer = PdfWriter.getInstance(doc, out);

    doc.setPageSize(new com.lowagie.text.Rectangle(612, 792));
    doc.open();
    PdfContentByte cb = writer.getDirectContent();
    cb.saveState();
    cb.concatCTM(1, 0, 0, 1, 0, 0);

    DefaultFontMapper mapper = new DefaultFontMapper();
    mapper.insertDirectory("c:/windows/fonts");

    Graphics2D g = cb.createGraphics(612, 792, mapper, true, .92f);

    AffineTransform at = new AffineTransform();
    at.translate(convertToPixels(20), convertToPixels(20));
    at.scale(pixelToPoint, pixelToPoint);

    g.transform(at);
    g.setColor(Color.WHITE);
    g.fill(newPane.getBounds());

    Rectangle alloc = getVisivleEditorRect(newPane);
    newPane.getUI().getRootView(newPane).paint(g, alloc);

    g.setColor(Color.BLACK);
    g.draw(newPane.getBounds());

    g.dispose();
    cb.restoreState();
    doc.close();
    out.flush();
    out.close();
}

private float convertToPixels(int points){

    return (float) (points / pixelToPoint);
}

private Rectangle getVisivleEditorRect(JEditorPane newPane){

    Rectangle alloc = newPane.getBounds();
    if((alloc.width > 0) && (alloc.height > 0)){
        alloc.x = alloc.y = 0;
        Insets insets = newPane.getInsets();
        alloc.x += insets.left;
        alloc.y += insets.top;
        alloc.width -= insets.left + insets.right;
        alloc.height -= insets.top + insets.bottom;
        return alloc;
    }
    return null;
}

with,

int inch = Toolkit.getDefaultToolkit().getScreenResolution();
float pixelToPoint = (float) 72 / (float) inch;

I'm looking for a solution based on an external library, i tried expermenting with iText and PDFBox, to no avail so far.

I want to point out that the solution above uses com.lowagielibrary.

roeygol
  • 4,908
  • 9
  • 51
  • 88
omlfc be
  • 147
  • 2
  • 13
  • You want to save the form of the editor pane or the text in it? – Frakcool Jan 10 '17 at 19:09
  • The text, and just to clarity, the JEditorPane can be changed to a JtextPane, or JTextArea, depending on the solution you have in mind. – omlfc be Jan 10 '17 at 19:16
  • You could use StandardPrint first to turn your JEditorPane (or other Component) display into an Image, and then convert that into a PDF using lowagie: https://sourceforge.net/p/tus/code/HEAD/tree/tjacobs/print/StandardPrint.java – ControlAltDel Jan 10 '17 at 19:19
  • Can you make an example on how it should look like? With iText it's not difficult to do it. `com.lowagie` refers to `iText` actually, just in the first releases they did, later the package was changed to `itext` – Frakcool Jan 10 '17 at 19:19
  • i have no preferences on how it should look like, as long as it's saved as a pdf file, nothing special. Can you show how it would be done using iText ?, and thanks for the info. – omlfc be Jan 10 '17 at 19:39

1 Answers1

1

From what I understand you want to convert your GUI to images and print it in a PDF, if this is not what you want please clarify.

Here's a simple program that creates the following GUI (without the text written in it), which is a JTextArea and a JButton.

enter image description here

When clicked, the button opens a new Document, takes the area and converts it to an image, then adds that image to the PDF and later does the same with the button, so you get a similar output in a PDF like this one:

enter image description here

The trick is to use both java.awt.Image and com.itextpdf.text.Image, the former to convert the JComponent to images and the latter to print them in the PDF, this trick was found and based on this peeskillet's answer.

So, without further explanation, here's the code that achieves the results above:

import java.awt.BorderLayout;
import java.awt.Color;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.image.BufferedImage;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.IOException;

import javax.swing.BorderFactory;
import javax.swing.JButton;
import javax.swing.JComponent;
import javax.swing.JFrame;
import javax.swing.JTextArea;
import javax.swing.SwingUtilities;

import com.itextpdf.text.Document;
import com.itextpdf.text.DocumentException;
import com.itextpdf.text.Image;
import com.itextpdf.text.PageSize;
import com.itextpdf.text.pdf.PdfWriter;

public class PdfFromUserInput {

    private JFrame frame;
    private JTextArea area;
    private JButton button;
    private Document document;
    private PdfWriter writer;

    public static void main(String[] args) {
        SwingUtilities.invokeLater(new Runnable() {
            @Override
            public void run() {
                new PdfFromUserInput().createAndShowGui();
            }
        });
    }

    public void openPdf() throws FileNotFoundException, DocumentException {
        document = new Document(PageSize.A4, 30, 30, 30, 30);
        writer = PdfWriter.getInstance(document, new FileOutputStream("myFile.pdf"));
        document.open();
    }

    public void closePdf() {
        document.close();
    }

    public java.awt.Image getImageFromComponent(JComponent component) throws DocumentException {
        BufferedImage image = new BufferedImage(component.getWidth(), component.getHeight(), BufferedImage.TYPE_INT_RGB);
        component.paint(image.getGraphics());
        return image;
    }

    public void addImageToDocument(java.awt.Image img) throws IOException, DocumentException {
        Image image = Image.getInstance(writer, img, 1);
        image.scalePercent(50);
        document.add(image);
        System.out.println("printed!");
    }

    public void createAndShowGui() {
        frame = new JFrame("PDF creator");
        area = new JTextArea(10, 30);
        area.setBorder(BorderFactory.createLineBorder(Color.RED));
        button = new JButton("Create PDF");

        button.addActionListener(new ActionListener() {
            @Override
            public void actionPerformed(ActionEvent e) {
                try {
                    openPdf();
                    java.awt.Image img = getImageFromComponent(area);
                    addImageToDocument(img);
                    img = getImageFromComponent(button);
                    addImageToDocument(img);
                    closePdf();
                } catch (DocumentException e1) {
                    e1.printStackTrace();
                } catch (FileNotFoundException e1) {
                    e1.printStackTrace();
                } catch (IOException e1) {
                    e1.printStackTrace();
                }
            }
        });

        frame.add(area, BorderLayout.CENTER);
        frame.add(button, BorderLayout.SOUTH);

        frame.pack();
        frame.setVisible(true);
        frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
    }
}
Community
  • 1
  • 1
Frakcool
  • 10,915
  • 9
  • 50
  • 89