How to Print Java Screens
Important!
You may do well to start with this more recent
List of Java Image Software
maintained by Marco Schmidt.
I have not updated this page in over a year,
so some problems may well have been solved in better ways.
I believe this page is still useful,
if you think not please let me know.
Here is a recent addition,
Portable Network Graphics (PNG)
encoder.
Thanks to David Eisenberg at
david@catcode.com
Support for printing a screen was absent in Java 1.0,
and added in 1.1,
but with a number of bugs,
both in the concept and implementation.
Some problems remain in the 1.2 version.
The general idea is the same as for drawing to an offscreen buffer.
First obtain a "special"
Graphics g context,
and recreate your screen,
using this context for all the regular drawing operations.
In the case of an offscreen buffer,
the result is drawing into a bitmap or pixelmap.
Here,
with a different specialized Graphics context,
the result is writing a file of PostScript commands.
Since PostScript also has commands like drawString and drawLine,
it is more or less a direct translation.
You then send this file to a printer that understands PostScript.
The result is finally drawing a bitmap on paper.
The standard 1.1 example goes like this:
Toolkit tk;
if (null != (tk = Toolkit.getDefaultToolkit ())) {
/* This launches a Print Dialog,
* that's why it needed aFrame to construct the Dialog.
* Dialog details depend on platform.
* There are a set of properties you can pass in and out,
* but they depend on platform,
* will someday be standardized they tell us. */
PrintJob pj = tk.getPrintJob
(aFrame,
aFrame.getTitle () + " print",
(Properties)null);
/* Null if user cancels out -- otherwise go ahead */
if (null != pj) {
/* Graphics context which produces PostScript code,
* that can be rendered by a PostScript printer or viewer,
* instead of actually drawing into a bit map,
* that shows up on the screen. */
Graphics pg = pj.getGraphics ();
if (null != pg) {
/* Do not assume defaults -- set them */
Font myFont = top.getFont ();
if (null == myFont)
myFont = new Font("Courier", Font.PLAIN, 14);
pg.setFont(myFont);
/* Walk your tree and render everything into Graphics pg.
* This method defaults to paint () for Component,
* but many things override it,
* especially all peer-based (AWT) components,
* because they do not **really** draw into g,
* but g tells them **how** to draw.
* And here we really do have to draw into g,
* to generate the PostScript code. */
top.printAll (pg);
/* The dispose flushes it to be printed,
* or closes the file if that was the destination. */
pg.dispose ();
}
/* We could get another pg and print another page... */
pj.end ();
}
}
Well, that's really not hard,
too bad it doesn't work,
for a couple of reasons --
- printAll -- some of the peer-based AWT components
have buggy printAll methods,
and draw things twice or not at all,
or in the wrong place.
Some of them throw null-pointer exceptions,
effectively cutting short your output,
even if you have try / catch wrapped around the top level printAll,
so that your program doesn't crash outright.
There were once similar problems drawing to an offscreen image,
but those have been fixed long ago.
Sun continues to get this wrong in every release.
They now appear to have put it into their "not our problem" list,
both for AWT and the newer Swing components.
Their
latest answer
http://developer.java.sun.com/developer/onlineTraining/Programming/JDCBook/render.html
is to use your own rendering and tree-walker code,
such as provided here.
- PrintJob -- locks you into generating PostScript output,
as in the example above.
You cannot render to other formats,
such as GIF or JPG.
The sun.image
package available in JDK 1.2,
does support JPG output,
but there is still no support for GIF output,
and of course it is not an "offical" part of the release,
so it could be changed or dropped at any time.
- There is no PrintJob support for printing other files
that your program has produced,
such as a log or journal.
Too bad,
because this dialog does give you access to network printers,
something the program should be able to do.
PrintJob has a "FileName" property you can set,
but this is NOT how to print some other file,
it is just the default name if the user prints to a file.
- PrintJob again -- does not handle page sizes properly.
It may or may not tell you the correct page size,
with or without subtracting for margins.
In fact,
it should scale your entire output to fit the page,
which is a lot better than making you revise your layout.
The page dimensions are in points (1/72 inch) not pixels,
but all the AWT dimensions will take them as pixels,
so expect some change in size.
I have been able to work around these problems,
with the aid of some code that others have written,
copyrighted,
and shared with the public.
- PSGr
- PSGr (the PostScript Graphics Context) implements all public
methods of the Graphics class,
for example drawRect () and drawString ()
but instead of drawing on the screen,
it writes a file of the equivalent PostScript commands for printing.
Unlike the awt offering,
PSGr offers additional (non-Graphics) public methods related to PostScript,
with scale () the one of most interest here.
PSGr was written and is copyright by
Ernest Friedman-Hill
email at
ejfried@ca.sandia.gov
I did the port from 1.0 to 1.1 Java,
that is available here.
- JpegEncoder
- JpegEncoder processes an Image,
and produces a compressed JPEG encoding of that Image.
For our purpose,
the Image will be an OffScreenImage,
for which we can do getGraphics (),
and into which we draw to replicate the Java screen.
JpegEncoder was written and is copyright by
James R weeks
email at
james@obrador.com
- GifEncoder.java
- Produces a GIF compressed encoding of an Image,
again for our purpose,
an OffScreenImage,
into which we have replicated the Java screen.
Written and Copyright (C) 1996 by
Jef Poskanzer
email at jef@acme.com
I have made two minor but useful additions to GifEncoder:
- Nearest-color sharing,
if the on-screen Image has more than the 256 colors allowed by the GIF standard.
This retains the first 256 colors found by scanning the image,
and maps any others to the closest fit.
There is no promise that the first 256 colors are the best subset,
but it usually works out pretty well.
- Clipping,
to encode only a specified Rectangle,
perhaps as user-specified by a rubber-band box,
rather than the entire Image.
See Cropper.java
as an example using this feature.
- ImageEncoder.java
- Base class for GifEncoder,
and for some other encoders too.
See the acme site.
- IntHashtable.java
- Support class for GifEncoder.
- BitmapEncoder.java
- Produces a Microsoft Windows Bitmap Encoding.
Again for our purpose,
from an OffScreenImage,
into which we have replicated the Java screen.
Written by Jean-Pierre Dubé,
and presented as
Java Tip 60,
by Javaworld
- LoadBitmap.java
- LoadBitmap is not part of this demo,
it is for input rather than output.
It allows your Java program to load and display
a Microsoft Windows Bitmap Encoded image,
as easily as a GIF or JPG image.
Written by Jeff West, with John D. Mitchell,
and presented as
Java Tip 43,
by Javaworld
What I am doing here is trying to make these classes better known,
providing an example of their use,
and also providing some additional useful code.
I want to stress that this is not a "mirror site"
or support site for these classes,
and I certainly am not taking credit for them.
If you find them useful,
by all means thank the original authors,
and please let me know too.
If you have any problems with the code presented here,
please write to me,
and do not bother the original authors.
You might want to visit the original sites,
and see if they have newer versions.
You also might want to
drop Sun a note,
and ask why they still don't provide these things.
Because applets are not allowed to print or save files,
the example is written as an application.
You will have to download the sources and compile it.
Please see my otherJava Techniques
Please also visit theMorris Hirsch home page.
Was this Helpful?
Was this Helpful?
Was it what you were looking for?
How did you find this page?
Search result,
following a link,
recommendation?
Please let me know.
Finally,
if you did NOT find this page useful,
or you think the information is out of date,
or you know other information that should be mentioned here,
please let me know that too.
Email
me at morris_hirsch@brown.edu
Legalities
This software is provided free of charge with no support.
Email
me at morris_hirsch@brown.edu
if you do have a problem,
and I will try to help,
but I cannot promise to.
Except for all sections which are identified as the work,
and copyright,
of others,
this work is Copyright (C) 1998 by Morris Hirsch.
All rights reserved,
except as granted here.
Redistribution and use in source and binary forms,
with or without modification,
for any purpose,
are permitted,
except as may be restricted by original copyright holders,
provided that the following conditions are met:
-
Redistributions of source code must retain the above copyright notice,
all earlier copyright notices of others,
this list of conditions and the following disclaimer.
-
Redistributions in binary form must reproduce the above copyright notice,
all earlier copyright notices of others,
this list of conditions and the following disclaimer,
in the documentation,
and/or other materials provided with the distribution.
DISCLAIMER
This software is provided free of charge with no support.
This software is provided in source format;
You are advised to examine it and understand it,
before putting it to use.
This software uses only algorithms and coding techniques
that are available to the public in the open literature.
You are however,
advised to make your own determination of legality,
for your intended use.
This software is provided by the Author and Contributors ``AS IS''
and any express or implied warranties,
including, but not limited to,
the implied warranties of merchantability
and fitness for a particular purpose,
are disclaimed.
In no event shall the Author or Contributors,
or their Agents,
be liable for any direct, indirect, incidental, special, exemplary,
or consequential damages
(including, but not limited to,
procurement of substitute goods or services;
loss of use, data, or profits;
or business interruption)
however caused and on any theory of liability,
whether in contract, strict liability,
or tort (including negligence or otherwise)
arising in any way out of the use of this software,
even if advised of the possibility of such damage.