Easy to Learn Java: Programming Articles, Examples and Tips

Start with Java in a few days with Java Lessons or Lectures

Home

Code Examples

Java Tools

More Java Tools!

Java Forum

All Java Tips

Books

Submit News
Search the site here...
Search...
 

Swing Chapter 22. (Special topics) Printing. Easy for reading, Click here!

Custom Search
Swing Chapter 22. (Special topics) Printing. Easy for reading, Click here!

[ Return to Swing (Book) ]

Page: 2/5 



Previous Page Previous Page (1/5) - Next Page (3/5) Next Page
Subpages: 1. Java 2 Printing API overview
2. Printing images
3. Print preview
4. Printing styled text
5. Printing tables

22.2  Printing images

In this section we add printing capabilities to the JPEGEditor application introduced in chapter 13. This example will form a solid basis for the subsequent printing examples. Here we show how to implement the Printable interface to construct a custom panel with a print() method that can manage the printing of large images by splitting them up into a matrix of pages.

Figure 22.3 Running JPEGEditor example displaying native Print dialog.

<<figure22-3.gif>>

The Code: JPEGEditor.java

see \Chapter22\1

import java.awt.*;

import java.awt.event.*;

import java.awt.image.*;

import java.util.*;

import java.io.*;

import javax.swing.*;

import javax.swing.border.*;

import javax.swing.event.*;

import javax.swing.filechooser.*;

import com.sun.image.codec.jpeg.*;

import java.awt.print.*;

// Unchanged code from section 13.4

public class JPEGEditor extends JFrame

{

  // Unchanged code from section 13.4

  protected JMenuBar createMenuBar() {

    // Unchanged code from section 13.4

    mItem = new JMenuItem("Print...");

    mItem.setMnemonic('p');

    ActionListener lstPrint = new ActionListener() {

      public void actionPerformed(ActionEvent e) {

        Thread runner = new Thread() {

          public void run() {

            if (m_panel.getBufferedImage() != null)

              printData();

          }

        };

        runner.start();

      }

    };

    mItem.addActionListener(lstPrint);

    mFile.add(mItem);

    mFile.addSeparator();

    mItem = new JMenuItem("Exit");

    mItem.setMnemonic('x');

    lst = new ActionListener() {

      public void actionPerformed(ActionEvent e) {

        System.exit(0);

      }

    };

    mItem.addActionListener(lst);

    mFile.add(mItem);

    menuBar.add(mFile);

    return menuBar;

  }

  // Unchanged code from section 13.4

  public void printData() {

    getJMenuBar().repaint();

    try {

      PrinterJob prnJob = PrinterJob.getPrinterJob();

      prnJob.setPrintable(m_panel);

      if (!prnJob.printDialog())

        return;

      setCursor( Cursor.getPredefinedCursor(

        Cursor.WAIT_CURSOR));

      prnJob.print();

      setCursor( Cursor.getPredefinedCursor(

        Cursor.DEFAULT_CURSOR));

      JOptionPane.showMessageDialog(this,

        "Printing completed successfully", "JPEGEditor2",

        JOptionPane.INFORMATION_MESSAGE);

    }

    catch (PrinterException e) {

      e.printStackTrace();

      System.err.println("Printing error: "+e.toString());

    }

  }

  public static void main(String argv[]) {

    new JPEGEditor();

  }

}

class JPEGPanel extends JPanel implements Printable

{

  protected BufferedImage m_bi = null;

  public int m_maxNumPage = 1;

  // Unchanged code from section 13.4

  public int print(Graphics pg, PageFormat pageFormat,

   int pageIndex) throws PrinterException {

    if (pageIndex >= m_maxNumPage || m_bi == null)

      return NO_SUCH_PAGE;

    pg.translate((int)pageFormat.getImageableX(),

      (int)pageFormat.getImageableY());

    int wPage = (int)pageFormat.getImageableWidth();

    int hPage = (int)pageFormat.getImageableHeight();

    int w = m_bi.getWidth(this);

    int h = m_bi.getHeight(this);

    if (w == 0 || h == 0)

      return NO_SUCH_PAGE;

    int nCol = Math.max((int)Math.ceil((double)w/wPage), 1);

      int nRow = Math.max((int)Math.ceil((double)h/hPage), 1);

    m_maxNumPage = nCol*nRow;

    int iCol = pageIndex % nCol;

    int iRow = pageIndex / nCol;

    int x = iCol*wPage;

    int y = iRow*hPage;

    int wImage = Math.min(wPage, w-x);

    int hImage = Math.min(hPage, h-y);

    pg.drawImage(m_bi, 0, 0, wImage, hImage,

      x, y, x+wImage, y+hImage, this);

    System.gc();

    return PAGE_EXISTS;

  }

}

Understanding the Code

Class JPEGEditor

The java.awt.print package is imported to provide printing capabilities. A new menu item titled "Print..." has been added to the "File" menu of this application. If this item is selected and an image has been loaded, our new custom printData()method is called.

The printData() method retrieves a PrinterJob instance and passes it our m_panel component (an instance of JPEGPanel -- which now implements the Printable interface, see below). It then invokes a native Print dialog and initializes printing by calling print(). If no exception was thrown, a "Printing completed successfully" message is displayed when printing completes. Otherwise the exception trace is printed.

Class JPEGPanel

This class, which was originally designed to just display an image, now implements the Printable interface and is able to print a portion of its displayed image upon request. A new instance variable, m_maxNumPage, holds a maximum page number available for this printing. This number is set initially to one and its actual value is calculated in the print() method (see below).

The print() method prints a portion of the current image corresponding to the given page index. If the current image is larger than a single page, it will be split into several pages which are arranged as several rows and columns (a matrix). When printed they can be placed in this arrangement to form one big printout.

First this method shifts the origin of the graphics context to take into account the page's margins, and calculates the width and height of the area available for drawing: wPage and hPage.

        pg.translate((int)pageFormat.getImageableX(),

            (int)pageFormat.getImageableY());

        int wPage = (int)pageFormat.getImageableWidth();

        int hPage = (int)pageFormat.getImageableHeight();

Local variables w and h represent the width and height of the whole BufferedImage to be printed. (If any of these happens to be 0 we return NO_SUCH_PAGE.) Comparing these dimensions with the width and height of a single page, we can calculate the number of columns (not less than 1) and rows (not less than 1) in which the original image should be split to fit to the page's size:

        int nCol = Math.max((int)Math.ceil((double)w/wPage), 1);

        int nRow = Math.max((int)Math.ceil((double)h/hPage), 1);

        m_maxNumPage = nCol*nRow;

The product of rows and columns gives us the number of pages in the print job, m_maxNumPage.

Now, because we know the index of the current page to be printed (it was passed as parameter pageIndex) we can determine the current column and row indices (note that enumeration is made from left to right and then from top to bottom), iCol and iRow:

        int iCol = pageIndex % nCol;

        int iRow = pageIndex / nCol;

        int x = iCol*wPage;

        int y = iRow*hPage;

        int wImage = Math.min(wPage, w-x);

        int hImage = Math.min(hPage, h-y);

We also can calculate the coordinates of the top-left corner of the portion of the image to be printed on this page (x and y), and the width and height of this region (wImage and hImage). Note that in the last column or row of our image matrix, the width and/or height of a portion can be less then the maximum values (which we calculated above--wPage and hPage).

Now we have everything ready to actually print a region of the image to the specified graphics context. We now need to extract this region and draw it at (0, 0), as this will be the origin (upper-left hand corner) of our printed page. The Graphics drawImage() method does the job. It takes ten parameters: an Image instance, four coordinates of the destination area (top-left and bottom-right--not width and height), four coordinates of the source area, and an ImageObserver instance.

        pg.drawImage(m_bi, 0, 0, wImage, hImage,

            x, y, x+wImage, y+hImage, this);

        System.gc();

Note: Because the print() method may be called many times for the same page (see below), it makes good sense to explicitly invoke the garbage collector in this method. Otherwise we may run out of memory.

Running the Code

Figure 22.2 shows a Page Setup dialog brought up by our program when run on a Windows NT platform. Be aware that the print job could take up to 15 minutes to print (and this assumes you don't run out of memory first)!

As we mentioned in the beginning of this chapter, the Java 2 printing environment is not yet fully matured. It doesn't work with all printers as expected, so writing and debugging printing applications may be difficult in many cases (a print preview capability is great help, as we will see in the next section). Also note that because we are using a printable job and not a pageable job, the page range is displayed as 1 to 9999 (see section 22.1.2--this may differ depending on your platform).

The most annoying thing with Java 2 printing is that is terribly slow. This is mainly because we are dealing with an Image (BufferedImage is a subclass of Image). Images and printing clash severely. As we will see in later examples, printing is much faster when Images are not involved.

The size of a relatively simple print job spooled to the printer may be unreasonably large. This makes Java 2 printing applications hardly comparable with native applications (at least at the time of this writing). Be sure to have plenty of memory, time, and patience when running this example. Or, alternatively, wait for the next Java 2 release.

Note: It is recommended that the DoubleBuffered property of components be set to false during printing if the print() method directly calls a component's paint() method. Note that it is only safe to call paint() from the print() method if we are sure that print() is executing in the AWT event dispatching thread. Refer back to chapter 2 for how to shut off double-buffering, and how to check if  a method is running within the AWT event-dispatching thread.



[ Return to Swing (Book) ]


Top 10 read Java Articles
 Get free "1000 Java Tips eBook"

 Java Calendar and Date: good to know facts and code examples

 Array vs ArrayList vs LinkedList vs Vector: an excellent overview and examples

 How can I convert any Java Object into byte array? And byte array to file object

 The Java Lesson 1: What is Java?

 How do I compare two dates and times, date between dates, time between times and

 Maven vs Ant or Ant vs Maven?

 How to open, read, write, close file(s) in Java? Examples on move, rename and de

 Java Array

 Java: JLabel font and color


[ More in News Section ]
Java Lessons

The Java Lesson 1:
What is Java?
The Java Lesson 2:
Anatomy of a simple Java program
The Java Lesson 3:
Identifiers and primitive data types
The Java Lesson 4:
Variables, constants, and literals
The Java Lesson 5:
Arithmetic operations, conversions, and casts
The Java Lesson 6:
Boolean expressions and operations
The Java Lesson 7:
Bitwise operations
The Java Lesson 8:
Flow control with if and else
The Java Lesson 9:
switch statements
The Java Lesson 10:
for, while, and do-while statements
The Java Lesson 11:
Using break and continue
The Java Lesson 12:
Class methods and how they are called
The Java Lesson 13:
Using the Math class
The Java Lesson 14:
Creating and calling custom class methods
The Java Lesson 15:
Overloading class methods
The Java Lesson 16:
An introduction to objects and object references
The Java Lesson 17:
The String class
The Java Lesson 18:
The StringBuffer class
The Java Lesson 19:
Initializing and processing arrays of primitives
The Java Lesson 20:
Initializing and processing arrays of objects
The Java Lesson 23:
Inheritance and overriding inherited methods
The Java Lesson 24:
abstract classes and polymorphism
The Java Lesson 25:
Interfaces, instanceof, and object conversion and casting
The Java Lesson 26:
Introduction to graphical programming and the java.awt packa
The Java Lesson 27:
The Component class
The Java Lesson 28:
Containers and simple layout managers
The Java Lesson 29:
The Color and Font classes
The Java Lesson 30:
Drawing geometric shapes
The Java Lesson 31:
Choice, List, and Checkbox controls
The Java Lesson 32:
Using the Scrollbar graphical control
The Java Lesson 33:
Menus and submenus
The Java Lesson 34:
An introduction to applets and the Applet class
The Java Lesson 35:
Essential HTML to launch an applet and pass it parameters
The Java Lesson 36:
Mouse event processing
Java Lesson 37:
Menus and submenus
Java Lesson 38:
The WindowListener interface and the WindowAdapter class
Java Lesson 39:
An introduction to GridBagLayout
Java Lesson 40:
An introduction to the Java Collections API
Java Lesson 41:
Exception handling with try, catch, and finally blocks
Java Lesson 42:
Claiming and throwing exceptions
Java Lesson 43:
Multithreading, the Thread class, and the Runnable interface
Java Lesson 44:
An introduction to I/O and the File and FileDialog classes
Java Lesson 45:
Low-level and high-level stream classes
Java Lesson 46:
Using the RandomAccessFile class
Java Lessons by
Joh Huhtala: Update

Latest articles
 Java Profiler JProbe to Resolve Performance Problems Faster

 SSL with GlassFish v2, page 5

 SSL with GlassFish v2, page 4

 SSL with GlassFish v2, page 3

 SSL with GlassFish v2, page 2

 The Java Lesson 2: Anatomy of a simple Java program, page 2

 New site about Java for robots and robotics: both software and hardware.

 Exceptions -III: What's an exception and why do I care?

 Exceptions -II: What's an exception and why do I care?

 Exceptions: What's an exception and why do I care?

 Double your Java code quality in 10 minutes, here is receipt

 Murach's Java Servlets and JSP

 How to get ascii code from a char in Java?

 Can we just try without catch? Yes!

 Make Tomcat page load faster

 Make your Tomcat More secure - limit network address for certain IP addresses

 New Java book online starts now here...

 Implementing RESTful Web Services in Java

 Firefox trimming from 1 GB to 40 Mb with many tabs opened

 SSL with GlassFish v2

 My request to replublish Tech Tips

 Search JavaFAQ.nu site here

 New Advanced Installer for Java 6.0 brings XML updates and imports 3rd party MSI

 EJB programming restrictions

 Maven vs Ant or Ant vs Maven?

 Why Java does not use default value which it should?

 How to unsign signed bytes in Java - your guide is here

 The Java Lesson 3: Identifiers and primitive data types. Page 2

 The Java Lesson 7: Bitwise operations with good examples, click here! Page 4

 The Java Lesson 7: Bitwise operations with good examples, click here! Page 3


[ More in News Section ]


Home Code Examples Java Forum All Java Tips Books Submit News, Code... Search... Offshore Software Tech Doodling

RSS feed Java FAQ RSS feed Java FAQ News     

    RSS feed Java Forums RSS feed Java Forums

All logos and trademarks in this site are property of their respective owner. The comments are property of their posters, all the rest 1999-2006 by Java FAQs Daily Tips.

Interactive software released under GNU GPL, Code Credits, Privacy Policy