Solved

java.awt.print VS javax.print

Posted on 2004-04-16
9
2,236 Views
2 Endorsements
Last Modified: 2012-08-14
Hello everyone,

I have to create a class that will print out a document that has a barcode (graphic) in it. This document will be created in the code (don't know which type of object yet) and does not come from the HD (maybe this makes a difference, i don't know).

I've been reading about different ways to acheive this and found that there are many packages that offer printing possibilities.

My question is, what's the main difference between JAVA.AWT.PRINT and JAVAX.PRINT ? Which one would be best ?

Thanks
2
Comment
Question by:mariec
  • 5
  • 4
9 Comments
 

Author Comment

by:mariec
Comment Utility
Points increased.
0
 

Author Comment

by:mariec
Comment Utility
since nobody seems to really know this, are there any examples of how to print some text with some images? Is it possible to format the elements on a page ?

0
 

Accepted Solution

by:
johnknapp earned 200 total points
Comment Utility
Well, they are not really one or the other,

javax.print.* and it supplimentary packages are for printer communications, i.e. getting the available printers, querying printer functionality, and sending print jobs, listening to print jobs, among other things

java.awt.print is used for the print code The code that generates the printing

Here is how I usuall incorporate my printing (there is some extra stuff in here, but this is also a complicated topic)

i usually start out with a base class, just to supply basic printing params and gives me a canvas to draw on

public class AbstractPrintableDocument extends JComponent implements PrintableDocument {

    protected String documentName;

    public AbstractPrintableDocument() {
   
    }

    public DocPrintJob getPrintJob(PrintService ps) throws NullPointerException {
        return (ps.createPrintJob());
    }
   
    public PrintRequestAttributeSet getPrintRequestAttributeSet() {
        return (null);
    }
   
    public Doc getDoc() {
        return (null);
    }
   
    public void print(PrintService ps) throws PrintException {}

    public void addPrintJobListener(PrintJobListener l) {}
   
    public void removePrintJobListener(PrintJobListener l) {}    

    public int print(java.awt.Graphics graphics, java.awt.print.PageFormat pageFormat, int pageIndex) {
        return (NO_SUCH_PAGE);
    }

    public void setDocumentName(String documentName) {
        this.documentName = documentName;
    }

}

and then override that with something useful like ...

public class Cheshire2UpPrintableDocument extends AbstractPrintableDocument {

    private static final boolean debug = true;

    private Dimension dimension;

    private PrintRequestAttributeSet set;
   
    private Font defaultFont;
   
    private Doc doc;

    private int currentPage = 0;

    private PrintRecord[] records;

    private int totalPages = 0;

    private Paginator paginator;

    private boolean paginated = false;

    private String dateString;

    public Cheshire2UpPrintableDocument() {
        super();
        set = _getPrintRequestAttributeSet();
        doc = _getDoc();
        dateString = _getDateString();
        defaultFont = _getDefaultFont();
        dimension = new Dimension(612, 792);
        records = new PrintRecord[0];
        paginator = new Paginator(8);
    }
   
    private String _getDateString() {
        java.util.Date d = new java.util.Date(System.currentTimeMillis());
        java.text.SimpleDateFormat format = new java.text.SimpleDateFormat("MM/dd/yyyy");
        String s = format.format(d);
        return (s);
    }

    public int print(Graphics graphics, PageFormat pageFormat, int pageIndex) { // here is the java.awt.print.Printable implementation
        if (!paginated)
            paginate((Graphics2D) graphics);
        if (pageIndex < totalPages) {
            currentPage = pageIndex;
            status("Page Index At Print: " + pageIndex);
            paintComponent(graphics);
            return (PAGE_EXISTS);
        } else {
            return (NO_SUCH_PAGE);
        }
    }

    public PrintRequestAttributeSet getPrintRequestAttributeSet() { return (set); }

    protected PrintRequestAttributeSet _getPrintRequestAttributeSet() { // tells the printer what my document will require
        PrintRequestAttributeSet mset = new HashPrintRequestAttributeSet();
        mset.add(OrientationRequested.PORTRAIT);
        mset.add(new JobName((documentName != null ? documentName : "Cheshire 2 Up Document"), null));
        MediaPrintableArea area = new MediaPrintableArea(.5f, .5f, 7.5f, 10f, MediaPrintableArea.INCH);
        mset.add(area);
        return (mset);    
    }
   
    protected Doc _getDoc() {
        Doc mdoc = new SimpleDoc(this,
                                 DocFlavor.SERVICE_FORMATTED.PRINTABLE,
                                 null);
        return (mdoc);
    }

    public Doc getDoc() { return (_getDoc()); }

    protected Font _getDefaultFont() {
        javax.swing.JTextField field = new javax.swing.JTextField();
        Font font = field.getFont();
        font = font.deriveFont(Font.PLAIN, 10f); // 10's gotta work
        font = Font.getFont("Arial", font);
        font.deriveFont(Font.PLAIN, 10f);
        if (debug) System.out.println("Cheshire2UpPrintableDocument Default Font Is: " + font.getName());
        return (font);
    }

    public Dimension getMaximumSize() { return (dimension); }
   
    public Dimension getMinimumSize() { return (dimension); }
   
    public Dimension getPreferredSize() { return (dimension); }
   
    public void setPrintRecords(PrintRecord[] recs) { // sets the records this document will print
        records = new PrintRecord[recs.length];
        System.arraycopy(recs, 0, records, 0, records.length);
        if (debug) System.out.println(getClass().getName() + " setPrintRecords " + records.length);
    }
   
    public void setPrintRecords(ExportRecord[] exRecs) {
        Vector temp = new Vector();
        for (int i = 0; i < exRecs.length; i++) {
            temp.addElement(PrintRecord.derive(exRecs[i]));
        }
        Object[] arr = temp.toArray();
        PrintRecord[] recs = new PrintRecord[arr.length];
        System.arraycopy(arr, 0, recs, 0, arr.length);
        setPrintRecords(recs);
    }
   
    protected void paginate(Graphics2D g) {
        paginator.setRecords(records); // paginator is a utility class to split pages based off the number of records
        totalPages = paginator.getPages();
        paginated = true;
    }
   
    protected void paintComponent(Graphics g) { // overriden to paint the document
        super.paintComponent(g);
        paintDocument((Graphics2D) g);
    }
   
    protected void paintDocument(Graphics2D g) {
        paintBackground(g);

        status("finished painting background");

        status("start pagination");

        if (!paginated)
            paginate(g);

        status("finished pagination");

        g.setFont(defaultFont);

        g.translate(36, 36);
       
        status("finished translation");
       
        g.setColor(Color.black);
       
        g.setRenderingHint(RenderingHints.KEY_TEXT_ANTIALIASING,
                           RenderingHints.VALUE_TEXT_ANTIALIAS_ON);
       
        status("getting records");
       
        Object[] temp = paginator.getRecordsByPage(currentPage);    
        PrintRecord[] recs = new PrintRecord[temp.length];
        System.arraycopy(temp, 0, recs, 0, recs.length);
       
        status("finished records");
       
        if (debug) System.out.println("From Paginator on page " + currentPage + " recs " + recs.length);
       
        int recPos = 0;
       
        status("starting to paint records");
       
        for (int rows = 0; rows < 4; rows++) {
            for (int cols = 0; cols < 2; cols++) {
                PrintRecord rec = (recPos < recs.length ? recs[recPos] : null);
                recPos++;
                paintRecord(g, rows, cols, rec);
            }
        }
       
        status("finished painting records");
       
       
    }
   
    private void status(String msg) {
        if (debug) {
            System.out.println(getClass().getName() + ": " + msg);
        }
    }
   
    protected void paintRecord(Graphics2D g, int row, int col, PrintRecord rec) {
        if (rec == null)
            return;
        if (debug) System.out.println("Printing Record " + row + " " + col);
        Point2D point = translate(row, col);
        status("paintRecordAt(" + row + ", " + col + ")");
        FontRenderContext frc = g.getFontRenderContext();
        TextLayout layout = null;
        String[] lines = prepareRecord(rec);
        float currentY = (float) point.getY();
        String ifNull = "ifNull";
        for (int i = 0; i < lines.length; i++) {
            if (lines[i] == null || lines[i].length() == 0) {
                layout = new TextLayout(ifNull, g.getFont(), frc);
                currentY += layout.getAscent();
                // layout.draw(g, (float) point.getX(), currentY);
                currentY += layout.getDescent() + layout.getLeading();
            } else {
                layout = new TextLayout(lines[i], g.getFont(), frc);
                currentY += layout.getAscent();
                layout.draw(g, (float) point.getX(), currentY);
                currentY += layout.getDescent() + layout.getLeading();
            }
        }
    }
   
    protected String[] prepareRecord(PrintRecord rec) {
        Vector temp = new Vector();
        String firstRec = "NAME RECORD";
        firstRec += " ";
        firstRec += dateString;
        temp.add(firstRec);
        temp.add(null);
        if (rec.getFullName() != null)
            temp.add(rec.getFullName());
        if (rec.getCompanyName() != null)
            temp.add(rec.getCompanyName());
        if (rec.getAddress() != null)
            temp.add(rec.getAddress());
        if (rec.getCity() != null && rec.getState() != null && rec.getZip() != null)
            temp.add(prepareCityStateZip(rec));
        temp.add(formatPhone("Business", rec.getPrimaryPhone()));
        temp.add(formatPhone("Home", rec.getSecondaryPhone()));
        String add1 = rec.getAdditional1();
        String add2 = rec.getAdditional2();
        if (add1 != null)
            temp.add(add1);
        if (add2 != null)
            temp.add(add2);
        temp.add(rec.getCode());
        Object[] arr = temp.toArray();
        String[] s = new String[arr.length];
        System.arraycopy(arr, 0, s, 0, s.length);
        return (s);
    }
   
    private String prepareCityStateZip(PrintRecord rec) {
        StringBuffer sb = new StringBuffer();
        sb.append(rec.getCity()).append(", ").append(rec.getState());
        sb.append(" ");
        sb.append(formatZip(rec.getZip()));
        return (sb.toString());
    }
   
    protected Point2D translate(int row, int col) {
        Point2D point = new Point2D.Float();
        switch (row) {
            case 0: point.setLocation(0, 13.0000/40.0000); break;
            case 1: point.setLocation(0, 108.0000/40.0000); break;
            case 2: point.setLocation(0, 203.0000/40.0000); break;
            case 3: point.setLocation(0, 298.0000/40.0000); break;
        }
        switch (col) {
            case 0: point.setLocation(24.0000/40.0000, point.getY()); break;
            case 1: point.setLocation(174.0000/40.0000, point.getY()); break;
        }
        Point2D act = new Point2D.Double((point.getX() * 72), (point.getY() * 72));
        status("Returning Point: " + act.getX() + ", " + act.getY());
        return (act);
    }

    private String formatPhone(String title, String phone) {
        if (phone == null || phone.length() == 0)
            return (title + ":");
        StringBuffer sb = new StringBuffer();
        char[] arr = phone.toCharArray();
        for (int i = 0; i < arr.length; i++) {
            appendIfNumeric(sb, arr[i]);
        }
        String num = sb.toString();
        sb.setLength(0);
        sb.append(title);
        sb.append(": ");
        if (num.length() == 10) {
            sb.append("(");
            sb.append(num.substring(0, 3));
            sb.append(") ");
            sb.append(num.substring(3, 6));
            sb.append("-");
            sb.append(num.substring(6, 10));
        }
        return (sb.toString());
    }
   
    private String formatZip(String zip) {
        if (zip == null || zip.length() == 0)
            return ("");
        StringBuffer sb = new StringBuffer();
        char[] arr = zip.toCharArray();
        for (int i = 0; i < arr.length; i++) {
            appendIfNumeric(sb, arr[i]);
        }
        zip = sb.toString();
        if (zip.length() == 9) {
            sb.setLength(0);
            sb.append(zip.substring(0, 5));
            sb.append("-");
            sb.append(zip.substring(5, zip.length()));
            return (sb.toString());
        } else {
            return (zip);
        }
       
    }

    private void appendIfNumeric(StringBuffer sb, char c) {
        switch (c) {
            case '0': sb.append(c); return;
            case '1': sb.append(c); return;
            case '2': sb.append(c); return;
            case '3': sb.append(c); return;
            case '4': sb.append(c); return;
            case '5': sb.append(c); return;
            case '6': sb.append(c); return;
            case '7': sb.append(c); return;
            case '8': sb.append(c); return;
            case '9': sb.append(c); return;
            default: return;
        }
    }

    protected void paintBackground(Graphics2D g) {
        Rectangle2D rect = new Rectangle2D.Float(0f, 0f, dimension.width, dimension.height);
        g.setColor(Color.white);
        g.fill(rect);
    }
   
}

Anyway, sorry about verboseness the document prints 8 address records 4 * 2 4 rows, 2 columns

The code which is prints this document is fairly simple The complexity is kept in the printable document

    protected void printData() {
        final Cheshire2UpPrintableDocument dbs = new Cheshire2UpPrintableDocument();
        dbs.setPrintRecords(records); // obtained in another part of the code
        final PrinterJob job = PrinterJob.getPrinterJob(); // gets a printer job to create a print dialog
        boolean res = job.printDialog(dbs.getPrintRequestAttributeSet());  // returns true if user said yes to printing
        if (res) {
            job.setPrintable(dbs);
            final PrintService ps = job.getPrintService(); // gets the users chosen printer
            Runnable r = new Runnable() {
                public void run() { // always run print code in sep thread, since it is generally pretty time consuming
                    try {
                        DocPrintJob jarb = ps.createPrintJob();
                        jarb.print(dbs.getDoc(), dbs.getPrintRequestAttributeSet());
                    } catch (Exception e) {
                        showExceptionSafely(e);
                    }
                }
            };
            Thread t = new Thread(r);
            t.start();
        } else {
       
        }    
    }

So, the java.awt.print.* package is still generally the workhorse responisble for actual formatting and printing

while the javax.print.* packages are used to get the print data to the correct printer with the correct parameters.

Hope This Helps,
John
0
 

Author Comment

by:mariec
Comment Utility
Thanks, this looks like what i needed.

Is the PrintableDocument interface from the com.davidflanagan.examples.print package? If not, does is implement Pageable and Printable anyway?
0
Maximize Your Threat Intelligence Reporting

Reporting is one of the most important and least talked about aspects of a world-class threat intelligence program. Here’s how to do it right.

 

Assisted Solution

by:johnknapp
johnknapp earned 200 total points
Comment Utility
Sorry, I should have posted that also:

It isn't from the com.davidflanagan.examples.print package, but the idea of it was taken from that among other sources . . . here is the code for PrintableDocument

package com.asymm.listman.shared;

import java.awt.print.Printable;

import javax.print.PrintService;
import javax.print.DocPrintJob;
import javax.print.Doc;
import javax.print.PrintException;

import javax.print.attribute.PrintRequestAttributeSet;

import javax.print.event.PrintJobListener;

public interface PrintableDocument extends Printable  {

    /**
     * Gets a doc print job to print with the appropriate parameters set
     * @param ps The print service to print the job to
     * @return A doc print job object to print
     * @exception java.lang.NullPointerException if print service parameter is null
     */
    public DocPrintJob getPrintJob(PrintService ps) throws NullPointerException;

    /**
     * Gets the print request attribute set that this printable document will use
     * @return A print request attribute set with appropriate parameters set
     */
    public PrintRequestAttributeSet getPrintRequestAttributeSet();

    /**
     * Get doc that this will use internally
     * @return The doc
     */
    public Doc getDoc();    

    /**
     * Handles all printing for this document
     * @param ps The print service to print to
     * @exception javax.print.PrintException If an underlying print exception occurs
     */
    public void print(PrintService ps) throws PrintException;    

    public void addPrintJobListener(PrintJobListener l);
   
    public void removePrintJobListener(PrintJobListener l);

    public void setDocumentName(String documentName);

}

Sorry about not posting that again,

It has been a while since I went that deep into it again, I ususally just extend AbstractPrintableDocument for the stuff since for this current project with some 20+ printables and another 7 faxables I am trying to cut down on my work as much as possible.

0
 

Assisted Solution

by:johnknapp
johnknapp earned 200 total points
Comment Utility
Also, sorry I forgot about printing images . . . but this is esentially how I do it

    /**
     * Draws the logo
     * @param g The graphics 2d object to draw on
     * @see #drawSalesOrder
     */
    protected void drawLogo(Graphics2D g) {
        status("drawLogo(Graphics2D)");
        BufferedImage li = getLogoImage();
        if (li == null) {
               
        } else {
            g.scale(.125, .125);
            g.drawImage(li, null, 0, 0);
            g.scale(8, 8);
            ypos = li.getHeight();
        }
    }

    /** Gets the logo image specified in the logoFile */
    private BufferedImage getLogoImage() {
        BufferedImage logoImage = null;
        try {
            logoImage = ImageIO.read(logoFile);
            if (debug) System.out.println("Successfully Read in Image File");
        } catch (Exception e) {
            if (debug) System.out.println(e);
        }
        return (logoImage);
    }

The reason I scale down first by 8 is that the image is 8 times the size I want it to be . . . I did this since when I printed the normal size image at the 72 pixels / inch it printed kind of poor - some banding on the image, my printer prints at a higher res so I sized up the image so that there are more pixels per inch and it looks great.  Just remember to scale back to normal, since setting the scale on graphics will continue to keep it that scale until set to something else.

I hope that also helps.  Generally for my complicated printables they get pretty long 1000+ lines of code . . .

You can also look into generating from apache fop . . . to create adobe acrobat documents and print those after they are created.  This can help if you will eventually be faxing the same printables, or emailing pdfs.
0
 

Expert Comment

by:johnknapp
Comment Utility
By The By,

where did you get the info on the bar code stuff, which bar code is it? I have a client in which I had to use a third party software package for bar coding . . . I couldn't find the open standards, except for the really simple barcodes . . .
0
 

Expert Comment

by:johnknapp
Comment Utility
Oh and I also forgot,

If you want to print without user intervention and send the stuff to a chosen printer directly, you can bypass the whole print dialog with code similar to the following

Cheshire2UpPrintableDocument cheshDoc = new Cheshire2UpPrintableDocument(); // pretend already initialized

PrintService[] services = PrintServiceLookup.lookupPrintServices(DocFlavor.SERVICE_FORMATTED.PRINTABLE, null);

/*
 * I have a client properties thing where I keep a default printer stored, and then get the correct print service this way
 */
String dpName = ClientProperties.getString("defaultprinter", null); // gets the value specified by key defaultprinter, with null as a backup value if not found
PrintService defaultPrintService = null;
if (dpName == null) {
    // tell client no dp printer chosen
    return;
} else {
    for (int i = 0; i < services.length; i++) {
        if (serivces[i].getName().equals(dpName))
            defaultPrinterService = services[i];
    }
}

if (defaultPrinterService == null) {
    // warn user could not find default printer -maybe disconnected ? or name changed? have them rechoose
    return;
}

try {
    cheshDoc.print(defaultPrinterService); // or whichever one matches the criteria
} catch (Exception e) {
    // handle print exception
}
0
 

Author Comment

by:mariec
Comment Utility
I doubled points because this is very helpful and more than I was expecting!


The barcode stuff comes from a third party package (ww.java4less.com) that our client gave us for developing their solution. Usually it is distributed as a package but they got the source code and in it is says that it can be modified for our needs. There are many standards included.
0

Featured Post

How to improve team productivity

Quip adds documents, spreadsheets, and tasklists to your Slack experience
- Elevate ideas to Quip docs
- Share Quip docs in Slack
- Get notified of changes to your docs
- Available on iOS/Android/Desktop/Web
- Online/Offline

Join & Write a Comment

An old method to applying the Singleton pattern in your Java code is to check if a static instance, defined in the same class that needs to be instantiated once and only once, is null and then create a new instance; otherwise, the pre-existing insta…
Introduction Java can be integrated with native programs using an interface called JNI(Java Native Interface). Native programs are programs which can directly run on the processor. JNI is simply a naming and calling convention so that the JVM (Java…
Viewers learn about the scanner class in this video and are introduced to receiving user input for their programs. Additionally, objects, conditional statements, and loops are used to help reinforce the concepts. Introduce Scanner class: Importing…
Viewers will learn about basic arrays, how to declare them, and how to use them. Introduction and definition: Declare an array and cover the syntax of declaring them: Initialize every index in the created array: Example/Features of a basic arr…

744 members asked questions and received personalized solutions in the past 7 days.

Join the community of 500,000 technology professionals and ask your questions.

Join & Ask a Question

Need Help in Real-Time?

Connect with top rated Experts

17 Experts available now in Live!

Get 1:1 Help Now