The previous section explained how to print simple components and covered techniques that can be used to print screen captures. However, if you want to print more than one component per page, or if your component is larger than one page size, you need to do some additional work inside your print
method. This section explains what you need to do and concludes with an example of how to print the contents of a JTable
component.
- Multiple Components Per Page
- Components Larger Than One Page
- Printing A
JTable
Component - Printing A Sales Report
Multiple Components Per Page
There are times when printing one component on a page does not meet your printing needs. For example, you might want to include a header on each page or print a footer with the page number--something that isn't necessarily displayed on the screen.
Unfortunately, printing multiple customized components on a page is not as easy as adding additional paint
calls because each paint
call overwrites the output of the previous call.
The key to printing more than one component on a page, is to use the translate(double, double)
and setClip
methods in the Graphics2D
class.
The translate
method moves an imaginary pen to the next position of the print output where the component can be painted and then printed. There are two translate
methods in the Graphics2D
class. To print multiple components you need the one t hat takes double
arguments because this translate
method allows relative positioning. Be sure to cast any integer values to double or float. Relative positioning in this context means that previous calls to translate
are taken into account when calculating the new translated point.
The setClip
method is used to restrict the component to only be painted, and therefore printed, in the area specified. This lets you print multiple components on a page by moving the imaginary pen to different points on the page and then painting each component in the clip area.
Example
You can replace the print
method in the Abstract Window Toolkit (AWT) and Swing printbutton.java examples with the following code to add the footer message Company Confidential to the page.
|
In the new print
method, the Graphics2D
context is clipped before calling the parent JButton
paint
method. This prevents the JButton paint
method from overwriting the bottom of the page. The translate
method is used to point the JButton paint
method to start the paint
at offset 0,0 from the visible part of the page. The visible area was already calculated by the previous translate
call:
g2.translate(pf.getImageableX(), pf.getImageableY());
For some components, you might also need to set the foreground color to see your results. In this example the text color was printed in black.
Useful Methods To Call In The print
Method
The following methods are useful for calculating the number of pages required and for shrinking components to fit on a page:
PageFormat
methods:
getImageableHeight()
returns the page height you can user for printing your output.
getImageableWidth()
returns the page width you can use for printing your output.
Graphics2D
method:
scale(xratio, yratio)
scales the 2D graphics context by this size. A ratio of one maintains the size, less than one will shrink the graphics context.
Components Larger Than One Page
The Java 2 Printing API has a Book
API that provides the concept of pages. However, the Book
API only adds printable objects to a collection of printable objects. It does not calculate page breaks or split components over multiple pages.
When printing a simple component on a page, you only have to check for the index value being greater or equal to one and return NO_SUCH_PAGE
when this value is reached.
To print multiple pages, you have to calculate the number of pages needed to contain the component. You can calculate the total number of pages needed by subtracting the space taken by the component from the value returned by getImageableHeight
. Once the total number of pages is calculated, you can run the following check inside the print
method:
if (pageIndex >=TotalPages) {
return NO_SUCH_PAGE;
}
The Printing framework calls the print
method multiple times until pageIndex
is less than or equal to TotalPages
. All you need to do is create a new page from the same component on each print
loop. This is done by treating the printed page like a sliding window over the component. The part of the component that is to be printed is selected by a translate
call to mark the top of the page and a setClip
call to mark the bottom of the page. The following diagram illustrates this process.
The left side of the diagram represents the page sent to the printer. The right side contains the long component being printed in the print
method.
The first page can be represented as follows:
The printed page window then slides along the component to print the second page, page index one.
This process continues until the last page from the total number of pages is reached:
The Report.java class uses many of the advanced techniques covered in this section to print out the data and header of a
JTable
component that can span many pages. The printed output also includes a footer at the bottom with the page number.
This diagram shows how the report looks when it prints:
|
Print a Sales Report
The SalesReport.java Applet
class prints a sales report with the rows split over multiple pages with numbers at the bottom of each page. Here is how the application looks when launched:
You need this policy file to launch the applet:
grant {
permission java.lang.RuntimePermission
"queuePrintJob";
};
To launch the applet assuming a policy file named printpol
and an HTML file named SalesReport.html
, you would type:
appletviewer -J-Djava.security.policy=
printpol SalesReport.html
This diagram shows how the report prints: