iText in Action: Chapter 7: Making documents interactive


If you compile and execute this example, you'll get the following result:

You can download the full source code of MoviePosters2, or read it here:

 * This class is part of the book "iText in Action - 2nd Edition"
 * written by Bruno Lowagie (ISBN: 9781935182610)
 * For more info, go to:
 * This example only works with the AGPL version of iText.
package part2.chapter07;
import java.sql.SQLException;
import java.util.List;
import com.lowagie.database.DatabaseConnection;
import com.lowagie.database.HsqldbConnection;
import com.lowagie.filmfestival.Movie;
import com.lowagie.filmfestival.PojoFactory;
import com.itextpdf.text.DocumentException;
import com.itextpdf.text.Image;
import com.itextpdf.text.Rectangle;
import com.itextpdf.text.pdf.PdfAction;
import com.itextpdf.text.pdf.PdfAnnotation;
import com.itextpdf.text.pdf.PdfName;
import com.itextpdf.text.pdf.PdfReader;
import com.itextpdf.text.pdf.PdfStamper;
import com.itextpdf.text.pdf.PushbuttonField;
public class MoviePosters2 {
    /** The resulting PDF file. */
    public static final String RESULT
        = "results/part2/chapter07/movie_posters_2.pdf";
    /** A pattern for an info string. */
    public static final String INFO = "Movie produced in %s; run length: %s";
    /** A JavaScript snippet */
    public static final String JS1 =
        "var t = this.getAnnot(this.pageNum, 'IMDB%1$s'); t.popupOpen = true; "
    	+ "var w = this.getField('b%1$s'); w.setFocus();";
    /** A JavaScript snippet */
    public static final String JS2 =
        "var t = this.getAnnot(this.pageNum, 'IMDB%s'); t.popupOpen = false;";
     * Creates a PDF with information about the movies
     * @param    filename the name of the PDF file that will be created.
     * @throws    DocumentException 
     * @throws    IOException 
     * @throws    SQLException
    public void manipulatePdf(String src, String dest)
        throws IOException, DocumentException, SQLException {
    	// Create a database connection
        DatabaseConnection connection = new HsqldbConnection("filmfestival");
        // Create a reader
        PdfReader reader = new PdfReader(src);
        // Create a stamper
        PdfStamper stamper = new PdfStamper(reader, new FileOutputStream(dest));
        // Loop over all the movies to add a popup annotation
        List<Movie> movies = PojoFactory.getMovies(connection);
        Image img;
        float x = 11.5f;
        float y = 769.7f;
        float llx, lly, urx, ury;
        for (Movie movie : movies) {
            img = Image.getInstance(String.format(MoviePosters1.RESOURCE, movie.getImdb()));
            img.scaleToFit(1000, 60);
            llx = x + (45 - img.getScaledWidth()) / 2;
            lly = y;
            urx = x + img.getScaledWidth();
            ury = y + img.getScaledHeight();
            addPopup(stamper, new Rectangle(llx, lly, urx, ury),
                String.format(INFO, movie.getYear(), movie.getDuration()), movie.getImdb());
            x += 48;
            if (x > 578) {
                x = 11.5f;
                y -= 84.2f;
        // Close the stamper
        // Close the database connection
     * Adds a popup.
     * @param stamper the PdfStamper to which the annotation needs to be added
     * @param rect the position of the annotation
     * @param title the annotation title
     * @param contents the annotation content
     * @param imdb the IMDB number of the movie used as name of the annotation
     * @throws IOException
     * @throws DocumentException
    public void addPopup(PdfStamper stamper, Rectangle rect,
        String title, String contents, String imdb)
        throws IOException, DocumentException {
    	// Create the text annotation
        PdfAnnotation text = PdfAnnotation.createText(stamper.getWriter(),
            rect, title, contents, false, "Comment");
        text.setName(String.format("IMDB%s", imdb));
        text.setFlags(PdfAnnotation.FLAGS_READONLY | PdfAnnotation.FLAGS_NOVIEW);
        // Create the popup annotation
        PdfAnnotation popup = PdfAnnotation.createPopup(stamper.getWriter(),
            new Rectangle(rect.getLeft() + 10, rect.getBottom() + 10,
                rect.getLeft() + 200, rect.getBottom() + 100), null, false);
        // Add the text annotation to the popup
        popup.put(PdfName.PARENT, text.getIndirectReference());
        // Declare the popup annotation as popup for the text
        text.put(PdfName.POPUP, popup.getIndirectReference());
        // Add both annotations
        stamper.addAnnotation(text, 1);
        stamper.addAnnotation(popup, 1);
        // Create a button field
        PushbuttonField field = new PushbuttonField(
                stamper.getWriter(), rect,
                String.format("b%s", imdb));
        PdfAnnotation widget = field.getField();
        // Show the popup onMouseEnter
        PdfAction enter = PdfAction.javaScript(
            String.format(JS1, imdb), stamper.getWriter());
        widget.setAdditionalActions(PdfName.E, enter);
        // Hide the popup onMouseExit
        PdfAction exit = PdfAction.javaScript(
            String.format(JS2, imdb), stamper.getWriter());
        widget.setAdditionalActions(PdfName.X, exit);
        // Add the button annotation
        stamper.addAnnotation(widget, 1);
     * Main method.
     * @param    args    no arguments needed
     * @throws DocumentException 
     * @throws IOException
     * @throws SQLException
    public static void main(String[] args)
        throws IOException, SQLException, DocumentException {
        new MoviePosters2().manipulatePdf(MoviePosters1.RESULT, RESULT);
Powered by GeSHi

The MoviePosters2 example is part of the book iText in Action (ISBN 9781935182610).

It's a small standalone application. You can use this example for inspiration, but please read the book if there's something you don't understand about the example. You'll find more info in Chapter 7. Note that this example depends on DatabaseConnection, HsqldbConnection, Movie, PojoFactory, and maybe some other examples.

Keywords for this example: Button fields, PdfReader, PdfStamper, Action > additional actions, Annotation > popup annotation, Annotation > widget annotations

If you want this example to work, you need the following jars: iText.jar, hsqldb.jar

This example uses the following resources: 0062622.jpg, 0423866.jpg, 0090583.jpg, 0268126.jpg, 0094625.jpg, 0245712.jpg, 0211915.jpg, 0072684.jpg, 0372784.jpg, 0266308.jpg, 0120601.jpg, 0090563.jpg, 0088847.jpg, 0368619.jpg, 0388795.jpg, 0362496.jpg, 0154420.jpg, 0095765.jpg, 0033467.jpg, 0066921.jpg, 0270288.jpg, 0813547.jpg, 0104029.jpg, 0190332.jpg, 0473444.jpg, 0468569.jpg, 0101700.jpg, 0256009.jpg, 0246578.jpg, 0057012.jpg, 0111797.jpg, 0279064.jpg, 0338013.jpg, 0120663.jpg, 0137523.jpg, 0120679.jpg, 0093058.jpg, 0113568.jpg, 0203515.jpg, 0452623.jpg, 0301357.jpg, 0372782.jpg, 0299977.jpg, 0051808.jpg, 0210727.jpg, 0385004.jpg, 0347149.jpg, 0119349.jpg, 0044741.jpg, 0201265.jpg, 0097576.jpg, 0255589.jpg, 0091288.jpg, 0099902.jpg, 0320042.jpg, 0048254.jpg, 0049406.jpg, 0323872.jpg, 0339230.jpg, 0169102.jpg, 0259393.jpg, 0056172.jpg, 0113627.jpg, 0418832.jpg, 0449059.jpg, 0056193.jpg, 0164711.jpg, 0378284.jpg, 0091480.jpg, 0948530.jpg, 0102494.jpg, 0376007.jpg, 0247586.jpg, 0283509.jpg, 0809931.jpg, 0457430.jpg, 0050825.jpg, 0311648.jpg, 0091790.jpg, 0419073.jpg, 0100436.jpg, 0105652.jpg, 0095953.jpg, 0042876.jpg, 0093206.jpg, 0180093.jpg, 0235060.jpg, 0096018.jpg, 0445691.jpg, 0056443.jpg, 0047478.jpg, 0081505.jpg, 0088128.jpg, 0094006.jpg, 0054331.jpg, 0145487.jpg, 0316654.jpg, 0413300.jpg, 0245429.jpg, 0374546.jpg, 0090060.jpg, 0092005.jpg, 0278736.jpg, 0348150.jpg, 0269217.jpg, 0103064.jpg, 0181852.jpg, 0088247.jpg, 0482901.jpg, 0108399.jpg, 0344510.jpg, 0107156.jpg, 0098635.jpg, 0100935.jpg, 0120903.jpg, 0376994.jpg, 0290334.jpg, 0857355.jpg, 0055630.jpg, 0402595.jpg, filmfestival.script.