Solved

Print Text File to Specific Windows Printer in Java with wrap-around and multi-page

Posted on 2014-12-14
4
1,095 Views
Last Modified: 2015-01-17
I am trying to print a text file to a specific Windows printer. All I need to consider, that if the particular
line doesn't print within the margins of the page than wrapping it around to the next line starting with
non-broken "words", meaning that break the line only on space characters
and if a single printed page will not be sufficient to print out the full file it would be printed
on more than one pages.

As far a simple example for printing text files, this is all I could find, but this is for printing single pages
with truncated lines:

http://www.java2s.com/Tutorial/Java/0261__2D-Graphics/PrinterJobandPrintable.htm

Based on this, this is my code:

The main class, Printer_Test.java:

import java.awt.print.PrinterException;
import java.awt.print.PrinterJob;
import java.io.BufferedReader;
import java.io.DataInputStream;
import java.io.FileInputStream;
import java.io.InputStreamReader;
import java.util.ArrayList;
import java.util.Iterator;
import javax.swing.JOptionPane;

public class Printer_Test {
    public static void main(String[] args) {
        
        ArrayList<String> listFileContents = new ArrayList<String>();
        
               try {
                   // Get the latest file in folder,  Open the file:
                   FileInputStream fstream = new FileInputStream("input.txt");
                   
                   // Get the object of DataInputStream
                   DataInputStream in = new DataInputStream(fstream);
                   BufferedReader br = new BufferedReader(new InputStreamReader(in));
                   String strLine;
                   //Read File Line By Line
                   while ((strLine = br.readLine()) != null) {
                       listFileContents.add(strLine);
                   }
                   //Close the input stream
                   in.close();
               } catch (Exception e) {
                   System.err.println("Error: " + e.getMessage());
                   JOptionPane.showMessageDialog(null, e.getMessage(), "File I/O Error", JOptionPane.ERROR_MESSAGE);
               }
               
        printToPrinter(listFileContents);
               
    }  // End of main()
    
    
// Print to printer method uses OutputPrinter class
// it will print the contents of jtxtAreaDiagnostic text area
               private static void printToPrinter(ArrayList<String> listOfFileContents) {
                   // Calling a method for getting all diag info out of jlstDiagnostic loaded contents:
                 

                   // Make a String out of the Arraylist<String>:
                   String printData = "";
                   Iterator it =  listOfFileContents.iterator();
                   while (it.hasNext()) {
                       printData = printData + it.next();
                       printData = printData + "\r\n";
                   }

                   // Feed the data to be printed to the PrinterJob instance:
                   PrinterJob job = PrinterJob.getPrinterJob();
                   job.setPrintable(new OutputPrinter(printData));
                   boolean doPrint = job.printDialog();
                   if (doPrint) {
                       try {
                           job.print();
                       } catch (PrinterException e) {
                           // Print job did not complete.
                       }
                   }
               }
}

Open in new window


The other class OutputPrinter implements Printable:

import java.awt.Font;
import java.awt.FontMetrics;
import java.awt.Graphics;
import java.awt.Graphics2D;
import java.awt.print.PageFormat;
import java.awt.print.Printable;
import java.awt.print.PrinterException;
import java.io.BufferedReader;
import java.io.IOException;
import java.io.StringReader;

public class OutputPrinter implements Printable {
    private String printData;

    public OutputPrinter(String printDataIn) {
        this.printData = printDataIn;
    }

    public int print(Graphics g, PageFormat pf, int page) throws PrinterException {
        // Should only have one page, and page # is zero-based.
        if (page > 0) {
            return NO_SUCH_PAGE;
        }

        // Adding the "Imageable" to the x and y puts the margins on the page.
        // To make it safe for printing.
        Graphics2D g2d = (Graphics2D) g;
        int x = (int) pf.getImageableX();
        int y = (int) pf.getImageableY();
        g2d.translate(x, y);

        // Calculate the line height
        Font font = new Font("Serif", Font.PLAIN, 10);
        FontMetrics metrics = g.getFontMetrics(font);
        int lineHeight = metrics.getHeight();

        BufferedReader br = new BufferedReader(new StringReader(printData));

        // Draw the page:
        try {
            String line;
            // Just a safety net in case no margin was added.
            x += 50;
            y += 50;
            while ((line = br.readLine()) != null) {
                y += lineHeight;
                g2d.drawString(line, x, y);
            }
        } catch (IOException e) {
            //
        }
        return PAGE_EXISTS;
    }
}

Open in new window


How can you modify this to make it multi-page, and to wrap around to the next line when the last word
is reached de-limited with a white space from the next word that will not fit?

Nothing seems to work for me.
Any suggestions / good examples for Java text printing to Windows printer practically?
0
Comment
Question by:AttilaB
  • 2
4 Comments
 

Accepted Solution

by:
AttilaB earned 0 total points
ID: 40510333
Well, I came up with something that is almost a solution -  Pageable and Printable both need to be implemented:

I based this off the following examples:

http://www.javadocexamples.com/java/awt/print/Paper/setImageableArea%28double%20x,double%20y,double%20width,double%20height%29.html

http://www.java2s.com/Code/Java/2D-Graphics-GUI/PageableText.htm

http://stackoverflow.com/questions/4034491/javax-print-attribute-printrequestattributeset-options-ignored-by-printer

BUT! The user cannot set the orientation or paper size manually. Actually he / she can, but it will be printed Letter size and Landscape orientation anyhow. I wonder why.

The code:

1. The driver class with main() method:

import java.awt.print.PageFormat;
import java.awt.print.Paper;
import java.awt.print.PrinterException;
import java.awt.print.PrinterJob;
import java.io.File;
import java.io.IOException;
import javax.print.attribute.HashPrintRequestAttributeSet;
import javax.print.attribute.PrintRequestAttributeSet;
import javax.print.attribute.standard.MediaSizeName;
import javax.print.attribute.standard.OrientationRequested;

public class PageableText_Main {

    public static void main(String[] args) {
        // Get the PrinterJob object that coordinates everything about printing:
        PrinterJob job = PrinterJob.getPrinterJob();

        // Get the page format:
        PageFormat format = definePageFormat(job);
        
        // Default attributes to printer:
        PrintRequestAttributeSet attributes = new HashPrintRequestAttributeSet();
        attributes.add(OrientationRequested.LANDSCAPE);
        attributes.add(MediaSizeName.NA_LETTER);

        // Create our PageableText object, and tell the PrinterJob about it
        try {
            job.setPageable(new PageableText(new File("input.txt"), format));
        } catch (IOException ex) {
            System.out.println("Cannot load file to print");
        }

        // Ask the user to select a printer, etc., and if not canceled, print pages:
        try {
            if (job.printDialog(attributes))
                job.print();
        } catch (PrinterException e) {
            System.out.println("Cannot Select Printer");
        }
    }

    private static PageFormat definePageFormat(PrinterJob printJob) {
        PageFormat pageFormat = printJob.defaultPage();
        Paper paper = pageFormat.getPaper();
        pageFormat.setOrientation(PageFormat.LANDSCAPE);
        paper.setSize(8.5 * 72, 11 * 72);
        paper.setImageableArea(0.875 * 72, 0.625 * 72, 6.75 * 72, 9.75 * 72);
        pageFormat.setPaper(paper);
        return pageFormat;
    }
}

Open in new window


And this is the PageableText class implements Pageable, Printable interfaces:

import java.awt.*;
import java.awt.print.*;
import java.io.*;
import java.util.Vector;

public class PageableText implements Pageable, Printable {
    // Constants for font name, size, style and line spacing
    public static String FONTFAMILY = "Monospaced";
    public static int FONTSIZE = 10;
    public static int FONTSTYLE = Font.PLAIN;
    public static float LINESPACEFACTOR = 1.1f;

    PageFormat format; // The page size, margins, and orientation
    Vector lines; // The text to be printed, broken into lines
    Font font; // The font to print with
    int linespacing; // How much space between lines
    int linesPerPage; // How many lines fit on a page
    int numPages; // How many pages required to print all lines
    int baseline = -1; // The baseline position of the font.

    /** Create a PageableText object for a string of text */
    public PageableText(String text, PageFormat format) throws IOException {
        this(new StringReader(text), format);
    }

    /** Create a PageableText object for a file of text */
    public PageableText(File file, PageFormat format) throws IOException {
        this(new FileReader(file), format);
    }

    /** Create a PageableText object for a stream of text */
    public PageableText(Reader stream, PageFormat format) throws IOException {
        this.format = format;

        // First, read all the text, breaking it into lines.
        // This code ignores tabs, and does not wrap long lines.
        BufferedReader in = new BufferedReader(stream);
        lines = new Vector();
        String line;
        while ((line = in.readLine()) != null)
            lines.addElement(line);

        // Create the font we will use, and compute spacing between lines
        font = new Font(FONTFAMILY, FONTSTYLE, FONTSIZE);
        linespacing = (int) (FONTSIZE * LINESPACEFACTOR);

        // Figure out how many lines per page, and how many pages
        linesPerPage = (int) Math.floor(format.getImageableHeight() / linespacing);
        numPages = (lines.size() - 1) / linesPerPage + 1;
    }

    // These are the methods of the Pageable interface.
    // Note that the getPrintable() method returns this object, which means
    // that this class must also implement the Printable interface.
    public int getNumberOfPages() {
        return numPages;
    }

    public PageFormat getPageFormat(int pagenum) {
        return format;
    }

    public Printable getPrintable(int pagenum) {
        return this;
    }

    /**
     * This is the print() method of the Printable interface.
     * It does most of the printing work.
     */
    public int print(Graphics g, PageFormat format, int pagenum) {
        // Tell the PrinterJob if the page number is not a legal one.
        if ((pagenum < 0) | (pagenum >= numPages))
            return NO_SUCH_PAGE;

        // First time we're called, figure out the baseline for our font.
        // We couldn't do this earlier because we needed a Graphics object
        if (baseline == -1) {
            FontMetrics fm = g.getFontMetrics(font);
            baseline = fm.getAscent();
        }

        // Clear the background to white.  This shouldn't be necessary, but is
        // required on some systems to workaround an implementation bug
        g.setColor(Color.white);
        g.fillRect((int) format.getImageableX(), (int) format.getImageableY(), (int) format.getImageableWidth(),
                   (int) format.getImageableHeight());

        // Set the font and the color we will be drawing with.
        // Note that you cannot assume that black is the default color!
        g.setFont(font);
        g.setColor(Color.black);

        // Figure out which lines of text we will print on this page
        int startLine = pagenum * linesPerPage;
        int endLine = startLine + linesPerPage - 1;
        if (endLine >= lines.size())
            endLine = lines.size() - 1;

        // Compute the position on the page of the first line.
        int x0 = (int) format.getImageableX();
        int y0 = (int) format.getImageableY() + baseline;

        // Loop through the lines, drawing them all to the page.
        for (int i = startLine; i <= endLine; i++) {
            // Get the line
            String line = (String) lines.elementAt(i);

            // Draw the line.
            // We use the integer version of drawString(), not the Java 2D
            // version that uses floating-point coordinates. A bug in early
            // Java2 implementations prevents the Java 2D version from working.
            if (line.length() > 0)
                g.drawString(line, x0, y0);

            // Move down the page for the next line.
            y0 += linespacing;
        }

        // Tell the PrinterJob that we successfully printed the page.
        return PAGE_EXISTS;
    }
}

Open in new window

0
 

Author Comment

by:AttilaB
ID: 40546441
I agree The question should be closed.
0
 
LVL 38

Expert Comment

by:Herman D'Hondt
ID: 40554984
This question has been classified as abandoned and is closed as part of the Cleanup Program. See the recommendation for more details.
0

Featured Post

How your wiki can always stay up-to-date

Quip doubles as a “living” wiki and a project management tool that evolves with your organization. As you finish projects in Quip, the work remains, easily accessible to all team members, new and old.
- Increase transparency
- Onboard new hires faster
- Access from mobile/offline

Join & Write a Comment

By the end of 1980s, object oriented programming using languages like C++, Simula69 and ObjectPascal gained momentum. It looked like programmers finally found the perfect language. C++ successfully combined the object oriented principles of Simula w…
Are you developing a Java application and want to create Excel Spreadsheets? You have come to the right place, this article will describe how you can create Excel Spreadsheets from a Java Application. For the purposes of this article, I will be u…
Viewers learn how to read error messages and identify possible mistakes that could cause hours of frustration. Coding is as much about debugging your code as it is about writing it. Define Error Message: Line Numbers: Type of Error: Break Down…
This tutorial covers a step-by-step guide to install VisualVM launcher in eclipse.

705 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

19 Experts available now in Live!

Get 1:1 Help Now