[Okta Webinar] Learn how to a build a cloud-first strategyRegister Now

x
  • Status: Solved
  • Priority: Medium
  • Security: Public
  • Views: 1545
  • Last Modified:

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

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
AttilaB
Asked:
AttilaB
  • 2
1 Solution
 
AttilaBAuthor Commented:
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
 
AttilaBAuthor Commented:
I agree The question should be closed.
0
 
hdhondtCommented:
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

Independent Software Vendors: We Want Your Opinion

We value your feedback.

Take our survey and automatically be enter to win anyone of the following:
Yeti Cooler, Amazon eGift Card, and Movie eGift Card!

  • 2
Tackle projects and never again get stuck behind a technical roadblock.
Join Now