|
Frequently Asked Questions (last revised: 3/6/09) | |
Q1: Was there a J2PrinterWorks 1.0?
A: No. J2PrinterWorks is the successor product to our earlier
products J2TextPrinter and J2TablePrinter, which were both released as
versions 1.0, 1.1, 1.2, and 1.3. The J2TextPrinter and
J2TablePrinter classes within J2PrinterWorks were the 2.0 versions of
the earlier J2TextPrinter and J2TablePrinter products, so
it made sense to number the initial release of J2PrinterWorks to be 2.0
as well.
Q2: What happened to the "J2PrinterWorks Text Edition" and the "J2PrinterWorks Table Edition"?
A: Beginning with the J2PrinterWorks 5.0 release, the two
J2PrinterWorks subset editions were dropped in favor of the (former)
J2PrinterWorks Complete product. Because of the overwhelming
customer preference for J2PrinterWorks Complete, the
increasing difficulty of maintaining separate build, test, and
distribution paths, and the added complexity of supporting three
separate releases, it was decided to converge the J2PrinterWorks family
on a single complete J2PrinterWorks product priced at an intermediate
price point. All J2PrinterWorks Text Edition and Table Edition
customers on annual maintenance were upgraded to the full
J2PrinterWorks 5.0 product at no charge.
Q3: How do I convert my code to J2PrinterWorks from J2TextPrinter
1.x or
J2TablePrinter 1.x?
A: See "Converting
from 1.x" section
of this documentation.
Q4: Does my component need to be on the screen in order to print?
A: For Swing components, it is not necessary that your JTextPane,
JTable, JTree, JList, JPanel, etc. be
in a JFrame visible on the screen at the time of printing or to have
ever been displayed at all (however, this is not necessarily true for
third-party components, see below J2PanelPrinter Q8). You may be
printing from a server
application and have no display. Or you may have, for example, a
JTextPane
displayed but wish to print from a different non-GUI copy of the
JTextPane. The latter situation can arise when you want to set
the printing JTextPane properties different from your on-screen
JTextPane display, such as to force white backgrounds, different page
width, borders, or fonts appropriate for a printed page. In such
cases, you can use code like:
JTextPane pane2 = new JTextPane();
pane2.setStyledDocument(pane1.getStyledDocument());
pane2.setSize(pane2.getPreferredSize()); // setting a
size is required
printer.print(new J2TextPrinter(pane2));
Even if you do use a JFrame, you can still specify JFrame.setVisible(false)
so it does not appear on the screen, or alternatively JFrame.setLocation(10000,10000)
to move it off-screen.
Q5: How do I control the size of my printed components?
A: Either get them drawn on the screen explicitly with the sizes you
want, or setPreferredSize (not setSize) for
your components, which J2PrinterWorks will use to determine their
sizes. If your components are not displayed, J2PrinterWorks
internally puts your component in a non-visible JFrame and calls pack(),
which Java redraws based on the preferred sizes of your
components.
Q6: Can I build a web page that prints on the user's printer?
A: Yes, but there are multiple issues you need
to be aware of. First, you can build a server-side application
that prints, but it can only print on printers known to the server
machine,
which may or may not include the printer desired by
your user. To print on the user's printer, the appropriate
technique
is to build an applet which downloads to the user's machine and prints
on the printers known to the user's machine. However, Java
specifies that it is a security violation to print from a regular
(untrusted) applet, just as it is a security violation for an applet to
read or write
files on
the user's machine. As a result, Java will automatically prompt
the user with "An applet would like to print. Is this OK?", so
the user can say "yes" or "no". In order to print from an applet
without this prompt, you need to "sign" your applet or set up the
security policy on the user's machine to grant your applet the printing
privilege (see "How do I sign an applet" under
Miscellaneous ).
Another consideration is that J2PrinterWorks uses the Java 2
printing
model, that is, it requires JDK 1.2 or later. Therefore you need
to
assure that your user's browser has a Java plug-in for JDK 1.2 or
later.
This is generally true for recent most recent verions of most popular
browsers. If the user's browser does not have the Java plug-in
for JDK 1.2 or later, it is
readily
available by free download from Sun, and it is possible to configure
your web page so
that
it offers to download and install the Java 2 plug-in if it is detected
that
the user's browser does not have it.
Alternatives to using a Java applet to print are to install a
regular Java application on the user's machine, or to download and use
a
Java Web Start application on the user's machine.
Q1: What is a Pageable?
A: Pageable is a Java 2 interface that is part
of the Java JDK as defined by Sun and which appears in the package java.awt.print
. Pageable defines a set of paginated pages, i.e., a indexed
sequence of printable pages. Pageable requires 3 implemented
methods: getNumberOfPages() specifying the number of pages
in the Pageable, getPrintable(int n) specifying the Printable
(a Java 2 class that prints a single page) for the nth page, and getPageFormat(int
n) specifying the PageFormat (another Java 2 class that describes
the paper characteristics, i.e., orientation, size, margins) on which
the nth page is to be printed. Printing a multi-page document in
Java requires implementing a Pageable for your document content.
This requires that you calculate in advance all the page breaks for
your document content (not an easy task). J2PrinterWorks contains
a number of components such as J2TextPrinter, J2TablePrinter,
J2TreePrinter, J2ListPrinter, J2ComponentPrinter, and J2PanelPrinter
that will take any
JTextPane, JTable,
JTree, JList, Component, or JPanel, respectively, and implement a
corresponding
Pageable.
Q2: What is a Flowable?
A: Flowable is an interface defined by Wildcrest Associates that
appears in the package com.wildcrest.j2printerworks.
Flowable defines a print operation that can be advanced by specified
rectangular amounts through a given piece of content such as a
JTextPane or a JTable, starting at the beginning and continuing
in print order to the end. Flowable can be used to paginate
a given piece of content starting and ending in the middle of any page,
and a sequence of Flowables can be printed back-to-back over a series
of pages. The J2PrinterWorks abstract class J2Pageable can
take any individual Flowable and create a Pageable from it. For
example, J2TextPrinter subclasses J2Pageable and implements the
Flowable methods for any JTextPane and, as a result, J2Pageable
implements the corresponding Pageable methods using these Flowable
methods.
In addition, the container class J2FlowPrinter can take any sequence of
Flowables
and create an overall Pageable as well as single Flowable from them.
Q3: Can I make my own Flowables?
A: Yes. By implementing the Flowable interface, you can create a
printable component that can paginate and be intermixed back-to-back
with other Flowable instances. Moreover, if you extend the
abstract base class J2Pageable and implement its Flowable interface,
you will also have a full J2PrinterWorks Pageable with support for
headers, footers, margins, orientation, scale, etc. To see sample
code for implementing your own Flowable, click here.
Q1: What are the differences between J2Printer and J2Printer14?
A: J2Printer14 is a subclass of J2Printer. J2Printer14 inherits
all the methods of J2Printer and adds several more methods that let you
use the new Java printing features of
JDK 1.4 including printer discovery, programmatic printer selection,
printer attributes, and cross-platform print dialogs. J2Printer
works under any JDK 1.2.x or later. J2Printer14
only
works
under JDK 1.4.x or later.
Q2: What are the differences between J2Printer and
J2PrinterWebStart?
A: J2PrinterWebStart is a subclass of J2Printer.
J2PrinterWebStart inherits
all the methods of J2Printer but implements them so they can run under
the Java Web Start JNLP APIs. Since the Java Web Start JNLP APIs
don't quite support all the printing capabilities of the full Java
PrinterJob printing model, a few method that J2PrinterWebStart inherits
from J2Printer have no effect under Java Web Start (see "J2Printer"
section of this documentation).
Q3: Should I use the PrintRequestAttributeSet API or the
J2Printer methods
like setPaperSize to set my printing settings?
A: Either or both. You can set the values of the number of
copies, print job name, paper size, orientation, and margins (printable
area) using either API and even intermix calls from the two APIs under
JDK 1.4.x or later. J2Printer14 will keep all the values in synch
between
the two systems, ensuring that setting values under either API will
update the values under the other. However, it is probably a less
confusing coding style to stay
within one system or the other. Also, if you are using JDK 1.4.x
or later,
you are much better off using the PrintRequestAttributeSet style since
it
allows you to do many more things.
Q4: The cross-platform print dialog comes up saying Pages
1 to 1. Can this be fixed?
A: This is a bug in Java (see "Known Problems"). Java does show
your number of pages correctly
as the upper bound in the native print dialog. For the
cross-platform dialog, you can
fix this in your code by setting the PageRanges attribute:
PrintRequestAttributeSet aset = new
HashPrintRequestAttributeSet();
aset.add(new
PageRanges(1,j2printer14.getPageable().getNumberOfPages()));
j2printer14.setPrintRequestAttributeSet(aset);
Q5: How can I "print to file"?
A: The user can always select the "print to file" option in the
standard print dialog to save their printing output to a file instead
of to an actual printer. If you wish to accomplish the same thing
programatically, under JDK 1.4 or later, you can use the J2Printer14
class to
specify the printer attribute javax.print.attribute.standard.Destination
,
which implements both the PrintJobAttribute
and PrintRequestAttribute
interfaces, in order to redirect your printing output to a local
disk file, e.g., file:out.prn
.
In addition, the J2Printer14 method printToPS can be used to send
your printing output to a Postscript file. The J2Printer method
printToHTML can be used to
send your printing output to a series of HTML pages, including .jpg
files for each of the individual page images. Likewise, the
J2Printer method getPageImage can be used to get an Image for any
individual page and the method saveImageToFile can save such any Image
to a file.
The method printToPDF can be used to send your printing output to a PDF file.
This method requires the use of the free, open source component
iText.jar available from http://www.lowagie.com/iText.
In addition you can also use
printToPS to create Postscript files and use 3rd party programs such as
Adobe Acrobat Distliller or PS2PDF (part of Ghostscript) to convert
these to PDF files.
See the sample code provided in the J2Printer14 documentation under
"Print to PDF".
Q6: The cross-platform print and page setup dialogs come up slow,
what can be done about this?
A: Due to a bug in Java (Bug Parade 6233074),
the cross-platform print and page setup
dialogs on Windows can take as long as 10 seconds to come up the first
time if
your default printer is a network printer (the native dialogs are fast,
the cross-platform dialogs after the first time are fast, having your
default printer be a direct connect printer is fast). This bug
has been reported to Sun. We have added a J2PrinterWorks
feature to help mitigate this problem. When you call the
J2Printer14 constructor, we start a separate low priority background
thread which invisibly invokes the operations that are taking the 10
seconds. If the user invokes the print or page setup dialogs
after these 10 seconds have passed, the dialogs will appear to them to
come up right away. However, if the user invokes the print or
page setup dialogs before the 10 seconds have passed, they will have to
wait the remainder of the 10 seconds. Thus, if you are using
cross-platform dialogs, be sure to instantiate J2Printer14 early in
your application so as to get this 10 second start-up cost out of the
way.
Q7: Hitting the "Print" button on the print preview dialog
behaves differently than it used to, why?
A: Upon hitting the "Print" button on the print preview dialog,
J2PrinterWorks used to always close the print preview dialog and bring
up the
print dialog (this is the same as applications such as Excel, Wordpad,
and Photoshop). However, since the cross-platform print dialog
can take a long time to come up (see Q6 above) this behavior makes it
look like the application has died. In addition, if you hit
"Cancel" on the print dialog, you really should go back to the print
preview dialog. In the new design, by default when you hit the
"Print"
button, the print preview dialog stays up and displays a "busy"
cursor. If the user hits "Cancel" on the print dialog, then the
print preview dialog comes back to the front. If the user hits
the "OK" (or "Print") button on the print dialog, then by default the
print and print preview dialogs both go away and printing begins (this
is the same as, for example, Internet Explorer). In addition, we
have added a new J2Printer method setPrintPreviewCloseOnPrint(int)
with arguments J2Printer.BEFORE, .WAIT, and .NEVER, where BEFORE means
close the print preview before beginning the process of bringing up the
print dialog (this is the former standard J2PrinterWorks behavior),
WAIT (the new default behavior) means close the print preview dialog
only after the user hits "OK" on the print dialog (this is the behavior
of Internet Explorer), and NEVER means leave the print
preview dialog up even after hitting "OK" (or "Print") on the print
dialog (this is the same as Word, PowerPoint, Outlook, and
Netscape).
Q1: I can't change the headers, they always say EVALUATION USE
ONLY, why?
A: This is a restriction of the Free Trial Version of
J2PrinterWorks. You need to purchase a product license for
J2PrinterWorks
to enable the feature of changing the headers.
Q2: I purchased J2PrinterWorks but I still can't change the
headers, they always say EVALUATION USE ONLY, why?
A: You need to include your serial number when
calling the J2Printer (or J2Printer14) constructor, like this:
J2Printer printer = new J2Printer("your
serial number"); // or J2Printer14
Or you can call the J2Printer method setParam()
using your serial number after you instantiate your J2Printer (or
J2Printer14) instance:
J2Printer printer = new J2Printer();
// or J2Printer14
printer.setParam("your serial
number");
Q3: I purchased J2PrinterWorks and set my serial number but
my headers still say EVALUATION USE ONLY, why?
A: You must set the serial number using the J2Printer constructor or
setParam method before you instantiate any
printing components (J2TextPrinter, etc.).
Q4: Well, I'm doing all that and it still says EVALUATION USE
ONLY, why?!
A: If this is still a problem, the likely explanation is that
you also have a copy of the evaluation version somewhere earlier in
your classpath or in your IDE's required libraries or in your JRE's
/lib/ext folder, and therefore you are getting it and not the
product version when you run your application. This is all too
easy to do given the complexities of Java classpaths.
Try searching your system for all copies of J2PrinterWorks.jar.
Normally you can just double-click on J2PrinterWorks.jar to find
out what version it is, but you can't always trust this. By the rules
of Java classloading, if you have the evaluation version of
J2PrinterWorks.jar in your JRE's /lib/ext folder, you'll get
the evaluation version of the classes even if you double-click directly
on the
product version jar! This will also happen if you include the
evaluation version of J2PrinterWorks classes in a .jar of your own and
have that in the /lib/ext folder.
A way to determine the version you are really running from
inside your program is to call the J2Printer method getVersion()
,
which will return as a string the version number of the J2PrinterWorks
you are actually using (it will say, for example, "J2PrinterWorks 5.0"
for the product version but "J2PrinterWorks 5.0EVAL" for the Free
Trial Version). However, even this only reports the
version number of the J2Printer.class you are using, so there is still
an opportunity for confusion if you've somehow mixed up the
J2Printer.class from one version with other J2PrinterWorks classes from
a different version!
Q5: Can I use page numbering and/or date/time formatting in a
JLabel
header or footer?
A: Yes. Just include the same indicators
like: Page ### of @@@ or:
|||EEE, MMM d,yyyy||| anywhere in your
JLabel text. This works in either HTML or non-HTML JLabel
text.
Q6: My HTML JLabel fonts appear to be one size too big under JDK
1.3.x when compared to JDK 1.4.x and later, why?
A: This was a long-standing problem that was finally
fixed in JDK 1.4 (see
Bug Parade 4285636 ). The tag:
<font face=serif size=3>
comes out one size too big under JDK 1.3 and 1.3.1 compared to JDK
1.4 and later or compared to standard browsers. To make your
fonts come
out
consistently between JDK 1.3.x and JDK
1.4 and later, specify all your fonts in relative size:
<font face=serif size=-1>
<font face=serif size=+0>
<font face=serif size=+1>
The same also applies to HTML in JTextPane or JEditorPane. You
can also use the HTML tags <big> and
<small> to go up or down one size, respectively.
Q7: My HTML JLabel fonts appear to be SansSerif, BOLD, 12, black
under JDK 1.4 and later but Serif, PLAIN, 14, blue under JDK 1.3.x, why?
A: Java changed the default HTML JLabel font under JDK 1.4. In
addition, under JDK 1.4.x and later, you can change the default HTML
font by
first calling JLabel.setFont(), but under
JDK 1.3.x this is ignored. Therefore, you have to specify the font
face, style, size, and color in the HTML explicitly to make them come
out the same on 1.3.x vs 1.4.x and later. J2PrinterWorks includes
a
JLabel
subclass called J2Label which makes it easier to create consistent
JLabel usage across all JDKs.
Q8: If the default HTML JLabel font under JDK 1.4 and later is
bold, since
there is no "un-bold" or "plain" command in HTML, how do I get a plain
font?
A: In JDK 1.4.x and later you can call JLabel.setFont() to set a PLAIN
font, then
setText to specify your HTML. Alternatively, J2PrinterWorks includes a
JLabel subclass called J2Label which
provides a default PLAIN font under any JDK version.
Q9: Using a JLabel for the right header or footer with right
justified text, text runs over the right edge. Why?
A: This was a Java bug (see "Known Problems"), since fixed in JDK
1.5. It
primarily occurred for small, size=-3, text and for SansSerif
(= Arial = Helvetica) font. Workarounds for earlier JDK's
include: 1) use bigger font size,
2) use Serif font, or 3) if you need a sans serif font, try
alternatives such as
Lucida Sans.
<img src=imageURL>
tag works
fine, e.g.: JLabel label = new
JLabel("<html><img src=imageURL></html>");
src=imageURL
part right depends on
where you
get your image from. "<img
src=http://www.domain.com/path/image.gif>
"
"<img
src=" + ClassLoader.getSystemResource("image.gif") + ">"
To read an image from a local file, there are bugs in earlier
JDKs (e.g., Bug
Parade 4456393)
that make it difficult to use relative paths consistently across
JDKs. Instead, it is better to use an absolute path: "<img
src=file:///path/image.gif>"
To get the absolute path relative to the working directory
of your program, use code like: String path = new File(".").getAbsolutePath();
src=
argument.
In addition, remember that if
you specify your HTML in a literal
String, any such quotes need to be escaped, that is, specified
using: \"Q12: How can I get my logo to print in a header or footer and not
look "blocky"?
A: See Question #11 under J2TextPrinter below. The basic idea
is to create a high resolution image of your logo at, say, 4X the size,
then display
it using HTML in a JLabel that scales it back down to 1/4th the
size. So, for a 1"x1" logo, you would use:
<img src=288x288Logo.gif width=72
height=72>
Q1: Can J2TextPrinter print RTF documents with embedded images?
A: The current Java JTextPane implementation is not able to read RTF
documents containing embedded images. However, you can read in an
RTF document without images, and then use the method JTextPane.insertIcon(Image)
to embed a graphics images at a given position in the RTF
document. Alternatively, the J2FlowPrinter component of
J2PrinterWorks lets you print RTF in a J2TextPrinter instance, followed
immediately by a J2PanelPrinter instance containing an Image, followed
immediately by more RTF in a second J2TextPrinter instance.
Q2: Can J2TextPrinter print RTF documents with embedded tables?
A: The current Java JTextPane implementation is not able to read RTF
documents containing embedded tables. However, you can read in an
RTF document without tables, and then use the method JTextPane.insertCompoent(JTable)
to
embed a JTable at a given position in the RTF document. However,
if your JTable doesn't fit on the page, it will not be paginated neatly
on a JTable row boundary but rather on the calculated pixel
boundary. A better approach is to use the J2FlowPrinter component
of J2PrinterWorks to print the first part of your RTF in a
J2TextPrinter instance, followed immediately by
a J2TablePrinter instance for printing a JTable of any size (which will
be paginated properly on row boundaries), followed immediately by more
RTF in a second
J2TextPrinter instance.
Q3: Is there any other solution for the features JTextPane RTF
does not support?
A: There is a commercially-available
RTF converter from Novosoft which is callable from Java and can
convert RTF (including embedded graphics and tables) to the XML XSL FO
format. This package references converters which can transform
XSL FO to HTML, PDF, Postscript, and other formats. You may find
it advantageous to do a one-time conversion or even conversion
on-the-fly for your RTF content.
Q4: Can J2PrinterWorks print to a Postscript or PDF document?
A: Yes. The method printToPS in the
J2Printer14 class supports
printing your document to a Postscript file. This feature
requires JDK 1.4 or later. The method printToPDF supports printing your document to a PDF
file (this does not require JDK 1.4 or later). This method
requires that you also have the free, open
source component iText.jar available from http://www.lowagie.com/iText.
You can also use printToPS to
print to Postscript and use third-party programs to convert to PDF, see
Q5 under "J2Printer, J2Printer14, and J2PrinterWebStart" above.
Q5: Can J2PrinterWorks print a preexisting PDF
document?
A: Yes. J2PrinterWorks includes a method printPDFFile
which can print the contents of any PDF file. A method
displayPDFFile is also available which can display the contents of any
PDF file. Both of these methods require that the free Adobe
Acrobat Reader program (available from http://www.adobe.com) be
available on the user's machine. At present, this capability is
only available on Windows.
Q6: Can I embed an Image in an HTML document?
A: Due to a bug in the Java JTextPane implementation (see
Bug Parade 4671653 and Bug
Parade 4636235), you cannot embed an instance of the Java
class Image into an HTML document in a JTextPane using the method
JTextPane.insertIcon(Image). However, the HTML
document itself can contain images using the usual <IMG
SRC=image.gif> tag. Also, the J2FlowPrinter component of
J2PrinterWorks lets you print HTML in a J2TextPrinter instance,
followed immediately
by a J2PanelPrinter instance containing an Image, followed immediately
by more HTML in a second J2TextPrinter instance.
Q7: When I print, my text document appears to be scaled
smaller. Why?
A: Usually, J2TextPrinter will reflow your JTextPane to fit to the
width of the page. However, it can't do this if you have
specified setWYSIWYG(true) and have too much text on a line
for the page, or if you define an HTML document which contains objects
(like big images or HTML tables with absolute widths or using "nowrap")
with a width which
is wider than the available width of the page. In these cases,
J2TextPrinter is unable to reflow your JTextPane to fit the available
page width, and instead it will automatically shrink-to-fit the
document so
that it fits to one page wide, resulting in smaller fonts.
Q8: My HTML JTextPane fonts appear to be one size too big under
JDK 1.3.x when compared to JDK 1.4.x and later, why?
A: This was a long-standing problem prior to JDK 1.4 that was finally
fixed (see
Bug Parade 4285636 ). The tag:
<font face=serif size=3>
comes out one size too big under JDK 1.3.x compared to JDK 1.4.x and
later
or
compared to standard browsers. To make your fonts come out
consistently between JDK 1.3.x and JDK 1.4.x and later specify all your
fonts in
relative size:
<font face=serif size=-1>
<font face=serif size=+0>
<font face=serif size=+1>
You can also use the HTML tags <big> and <small>
. The same also applies
to HTML in JLabel (see discussion under J2Label).
Q9: The print preview and print dialogs for my HTML document
take 30 seconds to come up. Pages also
turn slow in print preview and gets slower for later pages. Why?
A: This can happen if your HTML document is big and all (or most) of
your HTML document is contained
within a single cell of one overall HTML table, as some HTML editors
like to do for layout purposes. In this case J2TextPrinter gets no help
from Java in determining where page breaks go and has to analyze your
document one character at a time figuring out what fits on a page.
Bringing up the print preview or print dialogs requires one complete
pass through your document to count the pages before display begins, so
that's why they are slow. The print preview dialog must reanalyze
all the pages from the beginning of the document up to the page you are
currently displaying, so that's why later pages get slower. The
solution is to remove the outer HTML table so that your top level text
is not inside an HTML table. See "Working
with HTML".
Q10: I have some bold or italic words in the middle of my text
which look right on the screen but print shifted left or right (or
clipped at the right edge). Why?
A: This was a long-standing Java bug, finally fixed in JDK 1.5, see
Bug Parade 4724061 and
Bug Parade 4352983. This was one of
the worst problems with JTextPane, making it difficult to create and
print nicely formatted documents interspersed with bold and italic
words. If you need to use a JDK prior to 1.5, we have an
elaborate but serviceable workaround for this problem, see J2TextPrinter
Known Problems.
Q11: My JTextPane contains an image which looks good on the
screen but "blocky" when printed, why?
A: This problem occurs because your image is right for screen
resolution,
say, 72 dpi, but then printed at printer resolution, say, 288
dpi. Java uses the same 72 dpi coordinate system when printing,
but it knows that the printer is at 4X higher resolution. So if
you have a 72x72 image that displays as 1"x1" on the screen, Java does
a 4X pixel replication of the 72x72 pixels to get 288x288 pixels so as
to print the same 1"x1" on the page, which results in the blocky
effect.
The solution is to provide a 288x288 image in the first place, but
then scale it down to 1/4th the size to make it come out the right in
72 dpi coordinates. Java is smart when it prints to the printer
and will use all 4X original pixels rather than pixel replication,
which eliminates the blocky effect. If your image is specified
using HTML, all you need to do is go:
<img src=288x288image.gif width=72
height=72>
If you are embedding an
Image in your JTextPane using the insertIcon method, then instead
create your Image at printer resolution, use our ImagePanel class to
display it, call the ImagePanel setScale method to shrink it back down
to 72 dpi, and embed
the ImagePanel in your JTextPane using insertComponent (see
Question #6 under J2PanelPrinter
below for sample code).
Q12: How can I force my JTextPane to repaint and/or relayout after I
make changes?
A: JTextPane sometimes doesn't want to repaint or relayout after making
changes, even if you call repaint(), invalidate(), etc., particularly
if your JTextPane contains embedded components or if your JTextPane
updates aren't made from the event dispatching thread or when the
JTextPane is initially displayed. However, a way that always
appears to update reliably is to call:
SwingUtilities.updateComponentTreeUI(parentWindowContainingJTextPane);
Q13: J2TextPrinter instances in a J2FlowPrinter do not print
back-to-back with the other Flowables, instead there's a blank line or
gap separating them, why?
A: By default, JTextPane has a white border of 3 pixels on all four
sides, so back-to-back J2TextPrinter instances will have a 6 pixel gap
separating them. To eliminate this gap, set the underlying
JTextPane border to an EmptyBorder with zero insets, i.e.
yourJTextPane.setBorder(new EmptyBorder(0,0,0,0));
For successive J2TextPrinter instances in the same font, this
will result in uniform
line spacing across the multiple instances.
Q14: When I print a J2TextPrinter, I don't want "widows" (the
first line of a new paragraph by itself at the bottom of a page).
How can I prevent this?
A: To eliminate "widows", break your JTextPane into multiple JTextPane
instances, one per paragraph (you may also wish to set all the borders
to an EmptyBorder with insets of zero, see Q13 above). Create
J2TextPrinter instances for each JTextPane. Now create a
J2FlowPrinter and use addFlowable to alternate the J2TextPrinter
instances with VerticalGap instances with a test gap of, say, 1.0 and a
regular gap of 0.0. Each VerticalGap will test whether
there is less than one inch left on the page and if so, it will skip to
the top of the next page, otherwise it will put in a gap of zero length
and the following J2TextPrinter will have at least one inch to display
multiple lines before the page break.
Q15: I get a CloningException when I print J2TextPrinter from an
applet, why?
A: It appears that under some browsers, newer JDK's regard
serialization (the underlying mechanism of J2TextPrinter cloning) as a
security access violation when performed by untrusted applets (similar
to reading or writing a file). The same problem generally does
not occur when running applets in your IDE on your local system.
The easiest fix for this problem is to call yourJ2TextPrinter.setCloningUsed(false),
since cloning is usually not necessary for printing most JTextPane
content. Alternatively, you can sign your applet.
Q16: I'm using special Unicode characters which display and print
OK but are missing when I print to PDF, what can I do?
A: We have observed this problem for characters in high-level Unicode
pages like "Geometrical Shapes", "Dingbats", and "Mathematical
Operators". Java can display and print documents that use these
characters OK, but somehow iText fails to print these characters to
PDF. This appears to be a font loading problem. We have
discovered a workaround, which is to include somewhere in your
J2TextPrinter document at least one character from certain other
character sets (ones known to work include Hebrew, Arabic, Devanagari,
etc.,). This will cause the Unicode fonts to load and now iText
will print to PDF the Geometrical Shapes, Dingbats, Mathematical
Operators, etc. characters properly. The character you include
must be a printing rather than a non-printing character (e.g., the
character ׃ = \u05c3 is a Hebrew character which can be used
as a colon).
However, we have discovered that this workaround still fails to work for some specialized Unicode characters. As a result, we have added a set of printToPDFNoFonts() methods for printing the current document to a PDF (.pdf) file with no reliance on PDF fonts. All text is instead rendered completely to pixels using iText. This ensures that all fonts, including all higher-order Unicode fonts characters, will display and print properly, but with the disadvantage that since page images are now stored as fully rendered bitmaps, the resulting PDF files are much larger.
Q16: I can't get the images referenced in my HTML file (or the HTML file itself) to print using JTextPane. What am I doing wrong?Q17: After printing, can I change the contents of my JTextPane and have the same J2TextPrinter print the new contents?
A: Yes, but you have to call setPane again for your JTextPane
before you print a second time in order to get the J2TextPrinter to
recognize the new contents. This is because J2TextPrinter copies
your JTextPane contents into an internal JTextPane so that it can
reflow the text to the printed page width without disrupting the
on-screen appearannce of your JTextPane, but it only does this the
first time you print. Calling setPane will cause the
J2TextPrinter to recopy your JTextPane and capture the new contents.
Q1: J2TablePrinter 1.x was able to print a JTable across multiple
horizontal and vertical pages in "down then over" order as well as
"over then down" order. Is this still possible?
A: No. Because the new Flowable-based printing architecture
defines a Flowable in "over then down" order, the J2TablePrinter of
J2PrinterWorks is no longer able to print in "down then over" order and
now always prints in "over then down" order.
Q2: For a JTable that paginates over multiple pages horizontally,
do the headers and footers on the FIRST page apply to all the TOP pages?
A: Yes. The FIRST header and footer settings apply to all
the TOP pages and the REST settings
apply to the non-TOP pages.
Q3: How do I control the size of my JTable column widths?
A: JTable contains clever (perhaps too clever)
logic for allocating column widths when the overall JTable size
changes. To explicitly control the size of your individual
JTable columns, it is highly advised that you first call
table.setAutoResizeMode(JTable.AUTO_RESIZE_OFF);
Then you will be able to control the size of JTable columns by calling
table.getColumnModel().getColumn(n).setPreferredWidth(numPixels);
for each column in your table. See
J2PrinterWorksTestApplication.java for examples. Also, if you
have a JTable much larger than a page width and use SHRINK_TO_FIT
scaling to fit to one page , you may find that the default font
size to be way too small once scaled down. The easiest way to
address this problem is to adjust the sizes of your JTable columns in
advance so that the overall JTable size more nearly approximates
the printed page. Alternatively, you can increase your font
sizes so that they are more in proportion to your JTable size.
Q4: How can I get multi-line text in my JTable cells?
A: The easiest solution is to define a custom table cell renderer
using a JTextArea for your multi-line text, here's how:
TableCellRenderer
textAreaRenderer =
new TableCellRenderer() {
public Component
getTableCellRendererComponent(JTable table, Object value,
boolean isSelected, boolean hasFocus, int row, int col) {
JTextArea jta = new
JTextArea(table.getValueAt(row,col).toString());
jta.setLineWrap(true);
jta.setWrapStyleWord(true);
// to autosize the
row heights to fit exactly, add the following 3 lines:
jta.setSize(table.getColumnModel().getColumn(col).getWidth(),
Integer.MAX_VALUE);
int desiredHeight = (int)
jta.getPreferredSize().getHeight();
if
(desiredHeight>table.getRowHeight(row))
table.setRowHeight(row,desiredHeight);
return jta;
}
};
Enumeration cols =
table.getColumnModel().getColumns();
while(cols.hasMoreElements()) //set the renderer for
each column
((TableColumn)cols.nextElement()).setCellRenderer(textAreaRenderer);
An excellent source of source code snippets for a wide variety of
other JTable extensions and modifications may be found
here.
Q6: I'm using a custom Look & Feel and my JTable won't print,
why?
A: Unfortunately, it is very easy to create a custom Look & Feel
that will display but not print a JTable. The problem is that the
custom Look & Feel can't produce the JTable headers at the higher
printing resolutions required. This problem only occurs if you
are using J2TablePrinter headers, which you can confirm by setting
tablePrinter.setColumnHeaderPrinting(J2TablePrinter.NO_PAGES) and
seeing if you can now print your JTable. Among the custom Look
& Feel implementations that are known to have this problem are
Kunststoff 2.0 on Windows and the Macintosh Look & Feel on OS X
under
JDK 1.3.1 (the Aqua Look & Feel on OS X under JDK 1.4.1 is
fine).
To fix the above problems, the easiest thing to do is switch your
application to the
"Metal" (Cross-Platform) Look & Feel provided in Java, which always
prints
correctly. You can switch your application to this Look &
Feel by calling either
UIManager.setLookAndFeel(UIManager.getCrossPlatformLookAndFeelClassName());
or
UIManager.setLookAndFeel("javax.swing.plaf.metal.MetalLookAndFeel");
Likewise, the Motif Look & Feel provided in Java also works
correctly, which you can use by calling
UIManager.setLookAndFeel("com.sun.java.swing.plaf.motif.MotifLookAndFeel");
If you want your application to use the custom Look & Feel for
display, you can still print using a non-custom Look & Feel for
just your JTable, or even just for a second copy of your JTable used
only for printing. In turns out there is no MetalTableUI or
MetalTableHeaderUI defined in Java, but there is a BasicTableHeaderUI
that will print correctly, so you can use:
table.getTableHeader().setUI(new
javax.swing.plaf.basic.BasicTableHeaderUI());
The 2.0.1 release of Kunststoff fixed this problem to
some extent and a JTable will now print out. However, the
resulting JTableHeader still doesn't look right, instead of a nice
gradient, you get a two-level gray appearance. But since
Kunststoff 2.0.1 comes with sources, you can make JTableHeader print
with the BasicTableHeaderUI, thereby eliminating the problem. To
do this, edit KunststoffTableHeaderUI.java and immediately after the
line:
super.paint(g, c);
insert the following line:
if (g instanceof java.awt.print.PrinterGraphics)
return;
We have also found that the WindowsLookAndFeel provided with Java prints correctly but causes printing to slow down considerably when printing JTable headers due to a bug in Java which causes Java to make hundreds of extra print callbacks to our code. This problem has been fixed in the forthcoming JDK 1.6 release (and already in the 1.6 "early access" release). For earlier JDKs, the above workarounds of using the cross-platform, Metal, or Motif Look and Feel capabilities or the BasicTableHeaderUI will also address this problem.
We
have also gotten reports of slow printing because of excessive print
callbacks as well as huge print spooling files for older JDKs on
Windows if the Windows Display Properties control panel the "Theme" is
set to other than "Windows Classic" or "Windows XP", the
"Appearance" is set to other than "Windows Classic style" for Windows
and button and other than "Windows Standard" for Color scheme, and if
under "Settings: Advanced" the DPI setting is other than "Normal size
(96 dpi)". It appears that alternatives to these settings can
cause Java to perform extensive bitmap operations when printing JTables.
Q7: When I resize my JTable row heights the fonts get smaller,
but when
when resize my column widths the font size stays the same and instead
gets
truncated with "...". Why?7
A: This behavior is inherent in Java's implementation of JTable.
Java makes the fonts smaller if the row height gets smaller, but keeps
the font size the same and truncates wtih "..." when the column width
gets smaller. If you want the font to resize in all cases, create
a
JTable subclass that overrides setSize and makes the font smaller as
the column width decreases. Alternatively, you can use a
multi-line TableCellRenderer (see Q4 above) so that the text will wrap
when you reduce your column width.
Q8: When my JTable prints, the columns,
which were exactly the right size on the screen, come out
truncated with "..." when printed, why?
A: If your column widths are specified as an
exact fit on the screen, then the mapping from screen resolution and
font sizes to printer resolution and fonts sizes (all integer values)
may not be exact. As a result, the default TableCellRenderer (a
JLabel) may be slightly too small for the string at the new font
size, and the default behavior of JLabel is that it truncates with
"..." when it is too narrow for its content. This will result in
"..." in the printed output, even though it was fine on the
screen. There are several workarounds:
table.setAutoResizeMode(JTable.AUTO_RESIZE_OFF);
then for each column call
TableColumn
column =
table.getColumnModel().getColumn(n);
column.setPreferredWidth(column.getPrefeferredWidth()+10);
2) Decrease your font size a bit after you set
the
column sizes but before you print
3) Override the default TableCellRenderer (see
Q4 above) and either use a JTextArea which will wrap your table cells
to
multiple lines, or use a JLabel whose size is increased by 5-10 pixels
over
what Java thinks is right, e.g. Dimension
dim =
label.getPreferredSize();
dim.width =
dim.width + 10;
label.setPreferredSize(dim);
4) In combination with any of the above, you
can use
table2.setModel(table1.getModel())
to make a separate JTable used just for
printing if you wish to keep your screen version the unchanged.
Q9: Can I change a TableModel within the same JTable and have
J2TablePrinter print the new contents?
A: Yes. It used to be that you had to call setTable for your
same JTable again after any change to the TableModel, but this is no
longer the case. Note, however, that you cannot change the
TableModel while printing is underway. Java printing by its
nature needs to have the complete document formed before printing
begins and it must remain unchnaged until the Java phase of printing
completes, i.e., you can only change the TableModel (or anything else
about your document) after printingDone()
is called or, equivalently,
after the "printingUnderway" event is fired with isPrintingUnderway() false.
Q10: When I print a J2TablePrinter, I don't want just the table
header or just one row to appear by itself at the bottom of a
page. How can I
prevent this?
A: Use J2FlowPrinter and add a VerticalGap with a test gap of a couple
inches and regular gap of zero right before your J2TablePrinter
instance (see J2TextPrinter Q14 which describes the same technique used
for "widow" control).
Q1: Is it possible for J2TreePrinter to print my JTree so that it
paginates horizontally?
A: No. There is no natural place to break a JTree
horizontally. Hence, J2TreePrinter automatically performs a
shrink-to-fit operation to make your JTree fit within the available
page width, then it paginates the resulting JTree vertically as needed
over multiple pages. If you are willing to paginate your JTree
broken on pixel boundaries, you can use J2PanelPrinter in TILE mode to
print your JTree across multiple pages horizontally (but it will
be broken vertically on pixel boundaries as well, rather than row/node
boundaries as in a J2TreePrinter).
Q1: Can J2PanelPrinter paginate (i.e., print over multiple pages)
a
JTextPane? a JTable? a JTree? a JList?
A: J2PanelPrinter has four pagination modes: SHRINK_TO_FIT,
SHRINK_TO_WIDTH, TILE, and BREAK_ON_COMPONENTS (see
"J2PanelPrinter"). When any of these modes needs to paginate its
contents over multiple pages, the contents are broken on calculated
pixel boundaries that may slice right through the middle of the lines
of a JTextPane, rows of a JTable, nodes of a JTree, or items of a
JList. To correctly paginate these components on their "natural"
boundaries, you need to use J2TextPrinter, J2TablePrinter,
J2TreePrinter, and J2ListPrinter, respectively. Alternatively,
the new J2ComponentPrint can print these components effectively using
BREAK_ON_COLOR mode to break on white space or JTable gridline color.
Q2: For a JPanel that paginates over multiple pages horizontally,
do the headers and footers on the FIRST page apply to just the
first page or all the "top" pages?
A: The FIRST header and footer settings apply to all the "top"
pages and the REST settings apply to the
non-top pages.
Q3: When I print a JLabel, I always get blue text, or a non-white
background, or a bold font. How do I fix this?
A: Under JDK 1.4 and later, JLabel defaults to a bold font. This
is
a
particular problem if you are using HTML to specify your JLabel since
there is no "un-bold" HTML command. Also, JDK 1.3 and later
default
to a non-opaque background. And JDK 1.3 defaults to blue text
whereas JDK 1.4 and later default to black. To control these
inconsistencies, you can instantiate your JLabel, then set the Font,
foreground Color, and background Color explicitly. The other
solution is to use the J2PrinterWorks convenience class J2Label which
is a JLabel subclass which has a default plain (and small) font using
black
text on an opaque white background.
Q4: You say J2PanelPrinter can print any Component, and a JFrame
(JDialog, JWindow, etc.) is a Component, but I can't use it to print my
JFrame (JDialog, JWindow, etc.). Why?
A: Java does not allow a Frame, JFrame, JDialog, or JWindow to appear
inside another container, which prevents
them from being printing in their entirety. However, you can
get J2PanelPrinter to print JFrame.getContentPane() and
thereby
print the contents of your JFrame (but without the outside window
frame).
Q5: I'm using a custom Look & Feel and certain Swing components
in my JPanel won't print, why?
A: See similar discussion for JTable under J2TablePrinter above.
We have since learned that JButton and other Swing components can
have a similar problem with custom Look & Feel libraries like
Kunststoff. The same workarounds can be used:
1) change your whole application to "Metal"
(cross-platform) Look & Feel using UIManager.setLookAndFeel()
2) change the Look & Feel for the particular
component (or a copy used only for printing) to "Metal" or "Basic"
using setUI()
3) in the case of Kunststoff where the source
code is available, you can modify KunststoffButtonUI.java and/or other
component renderers by adding the same "instanceof" test given in the
J2TablePrinter discussion above, causing those components to revert to
"Metal" or "Basic" Look & Feel only when printing.
Alternatively,
you can disable the use of Kunststoff gradients for all component
printing
at one time by adding the "instanceof" test as the first line in the
two
drawGradient() methods in KunststoffUtilities.java.
Q6: I'm using J2PanelPrinter to print image which looks good on
the screen but "blocky" when printed, why?
A: This problem occurs if your image is displayed at screen resolution,
for example, 72 or 100 dpi, but then printed at printer resolution, for
example, 288 or
400 dpi. When printed, Java expands your low resolution image using
pixel replication, hence the blocky or pixelated effect. The
solution
is to provide your image at printer resolution (for example, 4 times
bigger),
then scale it down to
the screen resolution size using our ImagePanel class, as in the
following code:
ImagePanel ip = new ImagePanel(new
ImageIcon("4TimesBiggerImage.gif").getImage());
ip.setScale(.25);
J2PanelPrinter panelPrinter = new J2PanelPrinter(ip);
Q7: My JLabel looks right on the screen but when J2PanelPrinter
prints it the last characters get trnncated or changed to "...", why?
A: This problem occurs when Java rescales your JLabel for
printing. Java rescales the fonts to printer resolution but
doesn't adjust the JLabel width correctly (we believe this is the same
problem as
Bug Parade 4724061 and
Bug Parade 4352983.). The easiest solution is to add a little
extra room to your JLabel preferred size, for example:
Dimension dim = label.getPreferredSize();
dim.width = dim.width + 10;
label.setPreferredSize(dim);
Q1: Can I include the same Flowable instance twice in the same
J2FlowPrinter instance?
A: No. Each Flowable instance maintains its printing
position state as it is paginated in "raster" order. At the start
of paginating each J2FlowPrinter instance, the printing position states
of all of its Flowables are reset. These states advance as the
J2FlowPrinter is printed. Therefore, the same Flowable cannot
appear at two different places in the same J2FlowPrinter
instance. However, the same Flowable can appear in two different J2FlowPrinter
instances within the same overall document.
Q2: Can I scale individual Flowables independently within a
J2FlowPrinter instance?
A: Yes. This feature was introduced in J2PrinterWorks 3.0.
Q3: Can Flowables be made to flow side-by-side (if they fit)
before they flow down the page?
A: No. However, we are considering
adding this capability in a future release, please contact
Wildcrest Associates if you are interested in this feature.
Q4: Can Flowables be used to print a two-column page layout?
A: No. However, we are considering
adding this capability in a future release, please contact
Wildcrest Associates if you are interested in this feature.
Q1: What are the limitations of the Free Trial Version of
J2PrinterWorks?
A: In the Free Trial Version of J2PrinterWorks, the left, center, or
right headers contain the message "EVALUATION USE ONLY" and Wildcrest
Associates copyright notices, and the methods for changing these are
disabled. In addition, the Free Trial Version of J2PrinterWorks
appends to the end of every printed document an extra "Thank You" page,
thanking you for trying J2PrinterWorks and inviting you to buy the
product release. All other features of J2PrinterWorks are
identical to the product release.
Q2: How to I uninstall J2PrinterWorks?
A: Simply delete the J2PrinterWorks installation folder.
J2PrinterWorks uses no hidden files, files in
system folders, or modifications to your environment variables or
the registry.
Q3: How do I determine my current version number of
J2PrinterWorks?
A: Double-click on your copy of J2PrinterWorks.jar (but
see the next question).
Q4: I'm double-clicking my current version of J2PrinterWorks.jar
but I'm getting the wrong version number (or the EVAL version), why?
A: By the rules of Java classloading, if you have an old
version of J2PrinterWorks.jar in your JRE's /lib/ext folder,
you'll get the old version of the classes even if you double-click on
the new jar! This will also happen if you include old
J2PrinterWorks classes in a
.jar of your own and have that in the /lib/ext folder.
To be assured of the correct result, you need to run J2PrinterWorks.jar
from a "clean" JRE. For more information, read the related
questions and answers in the "Headers & Footers" section, above.
Q5: How do I download the latest version of J2PrinterWorks for
which I am licensed?
A: Use your browser, go to
http://www.wildcrest.com/Product/J2PrinterWorks, and enter your
name, email address, and product serial number.
Q6: Will J2PrinterWorks work on my OS platform (e.g., Windows,
Macintosh, Solaris, Linux, OS/2, HP/UX, AIX, etc.)?
A: This depends on the quality of the Java implementation on the
particular OS and how complex your printing application is. The
Windows, Solaris, and Linux implementations from Sun are generally the
most compatible. The Mac OS X Java JDK 1.4.x releases from Apple
are also
very good.
Q7: My version of IBM's VisualAge for Java complains when it tries
to load J2PrinterWorks.jar. Why?
A: IBM's VisualAge for Java complains when you try to load
J2PrinterWorks.jar because it is unable to find the class
PrintRequestAttributeSet. This class was new in JDK 1.4 and is
only used by our J2Printer14 class. IBM's VisualAge for
Java still uses JDK 1.2.2 and doesn't know about the new JDK 1.4
classes. However, despite the error message, you will be able to
use J2PrinterWorks inside VisualAge as long as you don't use the
J2Printer14 class. Alternatively, you can simply remove J2Printer14
from J2PrinterWorks.jar using the Java jar tool (or WinZip).
Q8: Does J2PrinterWorks work under Java Web Start (using JNLP
API)?
A: Yes. This feature was introduced in J2PrinterWorks 3.0.
Q9: Are there any DLL's or native implementations in
J2PrinterWorks?
A: No. J2PrinterWorks is implemented 100% in Java and uses
nothing but official Java API's.
Q10: I am getting "EVALUATION USE ONLY" in my headers, even after
I bought the product, why?
A: See Q1-Q4 in the "Headers & Footers" section above.
Q1: Can I ship the J2PrinterWorks .class files with programs I
write without paying extra (i.e., are they "run-time royalty-free")?
A: Yes. J2PrinterWorks licensing is on a
"per developer" basis. Only developers who write code that
calls the J2PrinterWorks APIs need to be licensed for
J2PrinterWorks. Once they have purchased a J2PrinterWorks
license, these developers can write any number of applications using
J2PrinterWorks and distribute or deploy any number of copies including
copies of
the J2PrinterWorks .class files for use by their software without any
additional royalties.
Q2: Do I have to ship the whole J2PrinterWorks.jar file with
programs I write?
A: No. You can use the Java jar utility (or WinZip) to
split the J2PrinterWorks.jar file into individual classes and
distribute only the classes you need with your software, either as
"loose" classes or bundled into your own .jar file(s). In
particular, many development tools will automatically extract just the
classes your program uses and package them with your program .jar file.
Doing this allows you to reduce the size of J2PrinterWorks by
excluding development-time-only classes you don't need to run your
program, such as the "BeanInfo" and "PropertyEditor" classes, as well
as any run-time classes your program happens not to use.
Q3: What developers need licenses to use J2PrinterWorks?
A: Only developers who write Java code that calls the J2PrinterWorks
APIs need to be licensed for J2PrinterWorks. Programmers working
on other sections of your application do not need to be licensed.
Test and build engineers do not need to be licensed (unless they write
test code that calls the J2PrinterWorks APIs). Distributors and
web
site managers who deploy programs that use J2PrinterWorks do not need
to be licensed. End users of programs that include J2PrinterWorks
do not need to be licensed.
Q4: What do I do if I lose my serial number?
A: Please contact Wildcrest Associates and
provide the purchaser's name, organization, mailing address,
email address, date of purchase, and/or other order information
sufficient to allow us to locate your name in our customer records.
Q5: If I buy a J2PrinterWorks Source Code Individual License, do
I also need to buy a J2PrinterWorks Binary Individual License?
A: No. The J2PrinterWorks Source Code Individual License
comes with a
(not separately transferable) J2PrinterWorks Binary Individual License.
This Binary
License covers both the unmodified J2PrinterWorks classes and any
classes produced from modified J2PrinterWorks source code. Thus, a
J2PrinterWorks Source Code License lets the licensee modify the
J2PrinterWorks source code and ship the resulting modified .class files
(though not the source code) bundled with their software.
However, a common situation where organizations do purchase both Source Code and Binary licenses is when they want both a Source Code Individual License (so one designated developer can see and change the source code to produce modified J2PrinterWorks .class files) and a Binary Site License (so all the developers at their site can develop and ship software that uses the original or modified J2PrinterWorks .class files).
Q6: Can I distribute modified J2PrinterWorks source code to other
developers?
A: You can only distribute modified J2PrinterWorks source code to
other J2PrinterWorks Source Code Licensees. These include any
other
developers who purchased a Source Code Individual License, developers
at your company if you have a Source Code Site License,
or developers at another company which has its own Source Code Site
License.
Q7: Can I distribute .class files derived from modified
J2PrinterWorks source code to other developers?
A: You can only distribute .class files derived from modified
J2PrinterWorks source code to other J2PrinterWorks Binary
Licensees. These include any other developers who purchased a
Binary
Individual
License, developers at your company if you also have a Binary Site
License, or developers at another company which has its own Binary Site
License. Of course per Q5 above, as a Source Code Licensee,
you can freely distribute .class files derived from modified
J2PrinterWorks source code when they are bundled as part of your own
software, provided
they are only available for end user (non-programming) use.
Q1: What does "Flowable unable to make progress" mean?
A: This means that you have some portion of your content that is both
indivisible and wider or taller than the
printable area of a page.
"Flowable unable to make progress" can never
happen for J2PanelPrinter, since any of its four pagination modes
will allow the J2PanelPrinter to make progress.
J2TreePrinter will never
have a width problem since it will always shrink-to-fit within a single
page width. But "Flowable unable to make progress" can happen if
the JTree has any individual row height
taller than a page.
Likewise, J2ListPrinter will never have a width problem since it will always shrink-to-fit within a single page width, but "Flowable unable to make progress" can happen if the JList has any individual row height taller than a page.
As of J2PrinterWorks 2.1a, "Flowable unable to
make progress" can no longer happen for J2TablePrinter. Beginning
with J2PrinterWorks 2.1a, if your
JTable had individual cells wider or taller than a page, J2TablePrinter
truncated them to the size of a full page and continue with the next
row or column. Beginning with J2PrinterWorks 4.0, J2PrinterWorks
paginates (tiles) oversize cells over page boundaries.
As of J2PrinterWorks 3.0, "Flowable unable to make progress" can no longer happen for J2TextPrinter. J2TextPrinter never had a width problem since it will always shrink-to-fit within a single page width. And under J2PrinterWorks 3.0, if you have an embedded image or component or text character taller than a page, J2TextPrinter will paginate (tile) through this content on pixel boundaries.
There is one exception to the above statements, which is that
"Flowable unable to make progress" can happen for any of the above
J2Pageable subclasses if an image or other content is specified in a
header or footer that is bigger than a page.
Q1: How do I sign an applet?
A: First, you do not need to sign an applet in
order to print if you don't mind Java asking the user each time if it
is OK to print (in addition, the user can check a box saying "Don't ask
again", in which case it will not ask again until the next time the
browser is run). Otherwise, you can sign your applet
so that it can print under both Netscape Navigator and Microsoft
Internet Explorer. The Java 2 security model specifies how this
is
done. Basically the idea is that you create a single jar
containing
your applet and the J2PrinterWorks classes, then you use the Java
security
tools to sign the jar with a public key certificate obtained from a
certification authority such as VeriSign
(alternatively, you can sign both the J2PrinterWorks.jar
and your own applet jar(s) separately). The user still has to
grant
you access the first time that they run the applet, but after that the
applet
will
never again have to ask, even if the browser exits and is rerun.
Another approach is for
you (or an administrator) to modify the java.policy file that resides
in your java_home/jre/lib/security directory to add the following lines:
grant {
Copying this
modified policy file into a user's java_home/jre/lib/security folder
(or certain other
places), will grant the necessary privileges so that applets
won't have to ask permission to print even the first time.
permission java.lang.RuntimePermission
"queuePrintJob";
};
Sun has lots documentation on the Java 2 security model, check out the
following links:
Overview
http://java.sun.com/products/plugin/1.2/docs/nsobjsigning.html
http://java.sun.com/products/jdk/1.2/docs/guide/security
http://developer.java.sun.com/developer/technicalArticles/Security/Signed
http://java.sun.com/developer/codesamples/security.html
Tutorial
http://java.sun.com/docs/books/tutorial/security1.2/toolsign
Tools
http://java.sun.com/products/jdk/1.2/docs/guide/security/SecurityToolsSummary.html
Worked Examples
http://developer.java.sun.com/developer/qow/archive/99/index.html
http://java.sun.com/security/signExample12
Architecture
http://java.sun.com/j2se/1.3/docs/guide/security/spec/security-spec.doc.html
The Java security model has evolved over time. For Internet Explorer it used to be that you needed to package your applet in a specially-constructed .cab file that included your signature information. However, this was only implemented by Microsoft for JDK 1.1, since Microsoft does not support Java 2. Since J2PrinterWorks requires Java 2, and since Java 2 is available for Internet Explorer only via Sun's Java Plug-In, Sun's Java 2 security model will enable your applets to use J2PrinterWorks under Internet Explorer.
For Netscape it used to be that you needed to create a signed .jar file and include a special Netscape class called by a few lines of code in your applet. However, as of JDK 1.3, Netscape began shipping Sun's Java Plug-In to provide Java support in Navigator, allowing you to use Sun's Java 2 security model, and as of JDK 1.4 Sun dropped support for the Netscape security model so that Sun's Java 2 security model must be used. Therefore, using Sun's Java 2 security model is also the best way to sign applets so that Netscape Navigator can use J2PrinterWorks.
Q2: How do I sign a Java Web Start application?
A: The situation for signing Java Web Start applications is in many
ways similar to the situation for signing Java applets, see links cited
in the previous question. In addition, the following
documentation for signing Java Web Start applications is available:
Java Web Start
http://java.sun.com/developer/technicalArticles/JavaLP/javawebstart/
http://java.sun.com/j2se/1.5.0/docs/guide/javaws/developersguide/faq.html
Java
Web Start does not have a specific printing privilege exactly
comparable to the Java applet situation above, and it is easiest to
just grant all permissions for a trusted Java Web Start application.
In order to do this, the basic idea is to add the following
security tag to your .jnlp file:
<security>
<all-permissions/>
</security>
Also, all the jars that make up your Java Web Start application have to be signed.
It is also possible to skip the whole signing process and just put the lines:
grant {
permission java.security.AllPermission;
};
into the user's jre\lib\security\javaws.policy file in the case where you have administrative control over the user's machine.
Q3: My printing is slow and/or my print spooling
size is huge. Why is this and what can I do about it?
A: JDK 1.2.x printing was very slow, especially for any documents
that contained images. Printing could take many minutes per page
and print spooling sizes could take many
megabytes even for small documents. JDK 1.3/1.3.1 achieved a
major improvement over JDK 1.2.2 in both speed and space
requirements. In turn, JDK 1.4, 1.5, and 1.6 each achieved
further
improvements on JDK
1.3/1.3.1. So the single best thing you can do to improve your
printing
performance is run under the latest JDK runtime (note that
you do
not need to
develop under the latest JDK 1.4 or use the JDK 1.4+ printing features).
Java printing has three phases:
1) the time to call the PrinterJob printing
methods themselves (this just takes few seconds)
2) the time for Java to perform "call-backs"
on your Pageable and Printable interface to draw the pages (under JDK
1.2.2 this can take 30 seconds/page or even several minutes/page if the
page contains images)
3) the time for the OS to spool your printing
and actually print pages out on the printer (highly variable based on
printer and OS, this can be seconds to minutes).
Phase 3 is always done in a background thread of the OS, outside the control of Java. Normally, Phases 1 and 2 will be done in the Java calling thread, usually the user interface thread of the application if the user invokes a print menu item or button, so that the user has to wait until Phases 1 and 2 complete before doing anything else. The J2PrinterWorks background printing thread support moves Phase 2 to separate Java thread. This means that calls on J2PrinterWorks methods will return in just a few seconds, and the user regains interactive control.
You can turn off the J2PrinterWorks background printing thread
feature if you want printing to take place from the calling thread by
calling setSeparatePrintingThread(false) . In this
case the print method will block until it is done rather than returning
immediately. This simplifies (and speeds up slightly) the
J2PrinterWorks internal printing process and is appropriate in
server-based applications where there is no user interaction to
get back to. Of course, you can always create a separate thread
in your program different from your UI thread to call J2PrinterWorks
and achieve the same result as the background printing thread feature
of J2PrinterWorks.
Note that if you call setSeparatePrintingThread(false) and call J2PrinterWorks from your UI thread, the print progress events that are fired by J2PrinterWorks will not get through to your UI thread (which might like to show a printing progress indicator), since this thread will be blocked until printing completes.
Certain LookAndFeel and/or desktop theme settings can also lead to very slow printing and excessive spool file size under older JDKs. See Q6 under "J2TablePrinter" above.Q4: J2PrinterWorks is using a lot of memory space and I get "Out
of Memory" errors. What can I do about it?
A: This was a big problem under JDK's prior to 1.4 and is still
being improved in the more recent JDKs, so the first
thing
to do is upgrade to the latest JDK. Nonetheless, depending
on the size and content of your document and your
particular printer and printer driver, Java can take
up a considerable amount of memory when imaging your document. For
certain
printers (especially bitmap printers like inkjets, Postscript printers
aren't
as bad), Java will allocate a full array of color pixel values for as
much as your
entire page at printer resolution for rendering, and may do this for
multiple
pages without freeing up memory. In addition certain components
consume
a lot of memory when rendered, especially JTextArea, JEditorPane, and
JTextPane which create large
numbers of objects each time a line layout operation is performed (see Bug
Parade 4203712, which is fixed in JDK 1.5).
After printing, garbage collection will free these resources, but
you need enough memory
during printing (or print preview) to make it through. The
default
maximum heap size of Java is only 16MB, and Java will run out of memory
once
this limit is reached, regardless of how much actual memory your
machine
may have. Usually 16MB will only work for modest print documents.
The
solution is to allocate a much bigger maximum heap size on your java
command
line. For example,
java -mx1024m -classpath etc YourApplication
will set 1024 MB of memory as the maximum heap size. This only
specifies a maximum and will not be allocated unless needed and
available.
If you suspect you have thread-safety problems, any of the following
can be used to avoid the problem:
1) Use setSeparatePrintThread(false)
2) Make a second JTextPane, JTable, JTree, JList, or JPanel
using
the same model as your original and use it to
print, e.g.:
JTextPane pane2 = new JTextPane();
pane2.setStyledDocument(pane1.getStyledDocument());
pane2.setSize(pane2.getPreferredSize());
// setting a size is required
printer.print(new J2TextPrinter(pane2));
3) Use the J2PrinterWorks clone method
to clone your JTextPane, JTable, JTree, JList, Component, or JPanel
component (or
clone its model and use it with a new component instance) and print
using the new copy (however, due to bugs in Java in some JDK's,
some components can't be cloned or do not clone properly)
4) Create a second JTextPane, JTable, JTree, JList, Component, or
JPanel to
be used
exclusively for printing and update its contents in parallel with your
original.
Q6: Why are there differences between my printout and print preview (or between printouts on two different printers)?
A: J2PrinterWorks creates its print preview view by executing the exact
same Java graphics operations it uses when it prints to a printer.
The only difference is that the graphics context used as a target
for the rendering is an in-memory image array instead of the printer
driver. This ensures that "WYSIWYG" printing is as good as Java
can provide. However, in the case where the printer has its own
printer description language (PDL), the printer driver performs an
additional step of translating the Java graphics commands to the PDL
graphics commands. Since these two graphics systems are different
and generally have different coodinate systems, different
resolutions, different color spaces, different fonts, etc., this
translation can be imperfect, despite the goal of WYSIWYG printing.
Similar problems can arise even when printing to a bitmap
printer, since often it is the underlying OS graphics system that
renders the printer bitmap image, and comparable problems arise in the
translation from the Java graphics environment to the OS graphics
environment.
Q7: Will I get print progress events if I print with
setSeparatePrintThread(false)?
A: Not without your creating a separate thread
yourself. If you call the J2PrinterWorks print method from
your UI thread and have setSeparatePrintThread(false), then
your UI thread is blocked until printing (through "phase 2" in Q2
above) completes. However, when the print progress events fire,
they do call "yield" on their thread, so if you have created
a separate UI thread of your own, print progress events can get through
to your code.
Q8: The "Search" function in this J2PrinterWorks Documentation
appears to require that my Internet connection be working. Why?
A: Normally J2PrinterWorks uses a local copy of the J2PrinterWorks
Documentation files installed on your machine. But the "Search"
function in the J2PrinterWorks Documentation uses a special indexed
copy of the J2PrinterWorks Documentation files maintained on the
Wildcrest Associates web site using a third-party search engine (from "FreeFind ") accessed on-line from
their site. Thus, if you use the "Search" function, you Internet
connection needs to be open to get
at these resources.