Printing Multiple Pages with Swing - java

I am writing a program that takes my text area with already generated data and it needs to print it out. I got it to calculate how many pages its going to take to print the whole textarea but instead of printing page 1 and then page 2, it prints page 1 and then page 1 again. I can't seem to get it to work to save my life. I've been looking through all the forums and help on oracle but there must be something I am missing. If you could be so kind and take a minute to look at my code I will be so grateful. thanks. -Garrett
private void hardPrintActionPerformed(java.awt.event.ActionEvent evt)
{
int width = printOut.getWidth() ;
int height = printOut.getHeight();
System.out.println("width is "+ width);
System.out.println("Height is "+height);
String font = fontSize.getText();
int FontS = Integer.parseInt(font);
Font fonT = new Font("Monospaced", Font.PLAIN, 12);
printOut.setFont(new Font("Tahoma", Font.PLAIN, FontS));
PrinterJob pj = PrinterJob.getPrinterJob();
PageFormat pf = pj.defaultPage();
Book bk = new Book();
Paper paper = new Paper();
double margin = 18;
pj.setPageable(bk);
paper.setSize(612,792);
paper.setImageableArea(margin, margin
, paper.getWidth() -margin * 2
, paper.getHeight() - margin * 2);
int lines = printOut.getLineCount();
System.out.println("lines = "+lines);
pf.setPaper(paper);
int tall = (int) pf.getImageableHeight();
System.out.println("tall ="+tall);
System.out.println("orientation "+pf.getOrientation());
int pagenum =bk.getNumberOfPages();
System.out.println("pagenum = "+pagenum);
System.out.println("areah = "+height);
int numpages =1;
if (height >756) {
for (int i = 756; i < height;) {
numpages = numpages+1;
i= i +756;
}
}
System.out.println("numpages ="+numpages);
bk.append(new MyPrintable(), pf,numpages);
// pj.setPrintable(new MyPrintable(), pf);
if (pj.printDialog()) {
try {
printOut.setBounds(0, 0, printOut.getWidth(), printOut.getHeight());
pj.print();
} catch (PrinterException pp) {
System.out.println(pp);
}
}
}
/**
* #param args the command line arguments
*/
class MyPrintable implements Printable {
public int print(Graphics g, PageFormat pf, int pageIndex) {
//int pagenum =bk.getNumberOfPages();
int height = printOut.getHeight();
int numpages =1;
if (height >756) {
for (int i = 756; i < height;) {
numpages = numpages+1;
i= i +756;
}
}
if (pageIndex >3)
return NO_SUCH_PAGE;
else{
Graphics2D g2 = (Graphics2D) g;
g2.setFont(new Font("Monospaced", Font.PLAIN, 10));
printOut.setBounds(0, 0, printOut.getWidth(), printOut.getHeight());
// paper.getImageableWidth();
g2.translate(pf.getImageableX(), pf.getImageableY());
System.out.println("print " +pf.getImageableY());
Rectangle componentBounds = printOut.getBounds();
g2.translate(-componentBounds.x, -componentBounds.y);
g2.scale(1, 1);
boolean wasBuffered = printOut.isDoubleBuffered();
printOut.printAll(g2); //printOut is my text area.
printOut.setDoubleBuffered(wasBuffered);
return PAGE_EXISTS;
}
}
}

You need to play with the g2.translate(-componentBounds.x, -componentBounds.y);
Correct the Y with pageIndex*pageHeight

Do you really need to use printJob for that?, why don't use JasperReports to make your pdf's (as a plus, you get a library that make pdf, xls and many others formats), you cant design in IReports and then use it with jasper, or design the report from code, very effective tool :D

Related

JPanel not being printed in landscape mode by default when i call the print method of printable

Here's my function to print panel, it prints in portrait mode by default and I have to change it each time to landscape, I have never done printing with java so I cant understand most of the following code
public static void Print(JPanel component){
PrinterJob pj = PrinterJob.getPrinterJob();
pj.setJobName(" Print Component ");
pj.setPrintable (new Printable() {
public int print(Graphics pg, PageFormat pf, int pageNum){
if (pageNum > 0){
return Printable.NO_SUCH_PAGE;
}
pf=pj.defaultPage();
Paper paper = pf.getPaper();
paper.setSize(8.5 * 72, 14 * 72);
paper.setImageableArea(0.5 * 72, 0.0 * 72, 8 * 72, 14 * 72);
pf.setPaper(paper);
pf.setOrientation(PageFormat.LANDSCAPE);
Book book = new Book();//java.awt.print.Book
book.append(this, pf);
pj.setPageable(book);
Graphics2D g2 = (Graphics2D) pg;
g2.translate(pf.getImageableX() + pf.getImageableWidth() / 2 - component.getWidth() / 2, pf.getImageableY() + pf.getImageableHeight() / 2 - component.getHeight() / 2);
g2.scale(pf.getImageableWidth()/component.getWidth(), pf.getImageableHeight()/component.getHeight());
component.paint(g2);
return Printable.PAGE_EXISTS;
}
});
if (pj.printDialog() == false)
return;
try {
pj.print();
} catch (PrinterException ex) {
// handle exception
}
}
Please Help, What I am doing wrong? I have tried many different things but nothing seems to work.
Hey I found the solution, Don't know much how it worked this way but I set all the paper , page format and book parameters outside the Print function and appended book with a new Printable (Passsing all the PageFormat and Paper parameters) and I got the results I wanted. Here's the code it may help someone. Printing a Jpanel on paper in Landscae Orientation by default.
public static void Print(JPanel component){
PrinterJob pj = PrinterJob.getPrinterJob();
pj.setJobName(" Print Component ");
pj.setPrintable (new Printable() {
public int print(Graphics pg, PageFormat pf, int pageNum){
if (pageNum > 0){
return Printable.NO_SUCH_PAGE;
}
Graphics2D g2 = (Graphics2D) pg;
g2.translate(pf.getImageableX() + pf.getImageableWidth() / 2 - component.getWidth() / 2, pf.getImageableY() + pf.getImageableHeight() / 2 - component.getHeight() / 2);
//g2.scale(pf.getImageableWidth()/component.getWidth(), pf.getImageableHeight()/component.getHeight());
component.paint(g2);
return Printable.PAGE_EXISTS;
}
});
PageFormat pf = pj.defaultPage();
pf = pj.defaultPage();
Paper paper = pf.getPaper();
paper.setSize(8.5 * 72, 14 * 72);
paper.setImageableArea(0.5 * 72, 0.0 * 72, 8 * 72, 14 * 72);
pf.setPaper(paper);
pf.setOrientation(PageFormat.LANDSCAPE);
Book book = new Book();//java.awt.print.Book
book.append((new Printable() {
public int print(Graphics pg, PageFormat pf, int pageNum){
if (pageNum > 0){
return Printable.NO_SUCH_PAGE;
}
Graphics2D g2 = (Graphics2D) pg;
g2.translate(pf.getImageableX() + pf.getImageableWidth() / 2 - component.getWidth() / 2, pf.getImageableY() + pf.getImageableHeight() / 2 - component.getHeight() / 2);
//g2.scale(pf.getImageableWidth()/component.getWidth(), pf.getImageableHeight()/component.getHeight());
component.paint(g2);
return Printable.PAGE_EXISTS;
}
}), pf);
pj.setPageable(book);
if (pj.printDialog() == false)
return;
try {
pj.print();
} catch (PrinterException ex) {
// handle exception
}
}

Java send screen capture to printer [duplicate]

i have an application from which i want to print an image. The image is loaded as a BufferedImage object. The problem is, when i print the image (to the postscript or to the pdf file), the quality is really poor.
When i'm using some other tools (basically any picture viewer application which can print the image) the result is significantly better.
I know there can be some problems with the DPI vs resolution but i'm not exactly sure how to compute the correct values for printing.
I tried to google and tried some methods, but nothing seems to work as i expected.
Basicaly i just want to print an image (in resolution let's say 3000x2000) to a printer (with DPI for example 600x600).
This is how i create the print job:
PrintRequestAttributeSet printAttributes = new HashPrintRequestAttributeSet();
printAttributes.add(PrintQuality.HIGH);
printAttributes.add(new PrinterResolution(600, 600 PrinterResolution.DPI));
printAttributes.add(new Destination(URI.create("file:/tmp/test.ps")));
PageFormat pf = printerJob.defaultPage();
Paper paper = pf.getPaper();
double xMargin = 0.0;
double yMargin = 0.0;
paper.setImageableArea(xMargin, yMargin, paper.getWidth() - 2 * xMargin, paper.getHeight() - 2 * yMargin);
pf.setPaper(paper);
// create new Printable for the specified image
printerJob.setPrintable(PrintableImage.get(image), pf)
if (printerJob.printDialog(printAttributes)) {
printerJob.print(printAttributes);
}
Where image is BufferedImage and PrintableImage.get returns new instance which implements Printable
Then the actual print is doing this way (i let the commented code which i tried but didn't work for me)
#Override
public int print(Graphics graphics, PageFormat pageFormat, int pageIndex) throws PrinterException {
if (image == null)
throw new PrinterException("no image specified to be printed");
// We have only one page, and 'page' is zero-based
if (pageIndex > 0) {
return NO_SUCH_PAGE;
}
// tranlate the coordinates (according to the orientations, margins, etc)
Graphics2D printerGraphics = (Graphics2D) graphics;
//g.setRenderingHint(RenderingHints.KEY_INTERPOLATION, RenderingHints.VALUE_INTERPOLATION_BICUBIC);
//g.setRenderingHint(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON);
//g.setRenderingHint(RenderingHints.KEY_RENDERING, RenderingHints.VALUE_RENDER_QUALITY);
printerGraphics.translate(pageFormat.getImageableX(), pageFormat.getImageableY());
// THIS IS A TEST - javax.printing api uses 72 DPI, but we have 600DPI set for the printer
//AffineTransform at = printerGraphics.getTransform();
//printerGraphics.scale((double)72 / (double)600, (double)72 / (double)600);
//printerGraphics.drawRenderedImage(image, null);
//printerGraphics.setTransform(at);
//if(printerGraphics != null)
//return PAGE_EXISTS;
double scale = 72.0 / 600.0;
Dimension pictureSize = new Dimension((int)Math.round(image.getWidth() / scale), (int) Math.round(image.getHeight() / scale));
// center the image horizontaly and verticaly on the page
int xMargin = (int) ((pageFormat.getImageableWidth() - image.getWidth()) / 2);
int yMargin = (int) ((pageFormat.getImageableHeight() - image.getHeight()) / 2);
xMargin = yMargin = 0;
System.out.println(String.format("page size [%.2f x %.2f], picture size [%.2f x %.2f], margins [%d x %d]", pageFormat.getImageableWidth(), pageFormat.getImageableHeight(), pictureSize.getWidth(), pictureSize.getHeight(), xMargin, yMargin));
printerGraphics.drawImage(image, xMargin, yMargin, (int)pageFormat.getWidth(), (int)pageFormat.getHeight(), null);
//printerGraphics.drawImage(image, 0, 0, null);
//printerGraphics.drawImage(image, xMargin, yMargin, pictureSize.width, pictureSize.height, null);
//printerGraphics.drawImage(image, xMargin, yMargin, (int) pageFormat.getImageableWidth(), (int) pageFormat.getImageableHeight(), 0, 0, pictureSize.width, pictureSize.height, null);
//printerGraphics.drawImage(image, 0, 0, (int) pageFormat.getWidth() - xMargin, (int) pageFormat.getHeight() - yMargin, 0, 0, pictureSize.width, pictureSize.height, null);
return PAGE_EXISTS;
}
Does anybody solves the same problem?
Any help would be appreciated.
Thanks
Matej
This is how I did it. It works smoothly. Note that this code snippet doesn't center the image.
public int print(Graphics g, PageFormat pageFormat, int pageIndex) throws PrinterException {
if (pageIndex > 0) {
return (NO_SUCH_PAGE);
} else {
double pageHeight = pageFormat.getImageableHeight(), pageWidth = pageFormat.getImageableWidth();
Graphics2D g2d = (Graphics2D) g;
g2d.translate(pageFormat.getImageableX(), pageFormat.getImageableY());
if (pageHeight < image.getHeight() || pageWidth < image.getWidth()) {
g2d.setRenderingHint(RenderingHints.KEY_INTERPOLATION,
RenderingHints.VALUE_INTERPOLATION_BILINEAR);
g2d.drawImage(image, 0, 0, (int) pageWidth, (int) pageHeight - textSize, null);
} else {
g2d.drawImage(image, 0, 0, null);
}
g2d.dispose();
return (PAGE_EXISTS);
}
}
#Viktor Fonic
Thank you for this, I was searching a lot to do this!
You're solution works perfectly, but has a small error,
textSize was not declared, so:
int textSize = (int) (pageHeight - image.getHeight()*pageWidth/image.getWidth());

Java PrintJob to DocPrintJob Not Working?

I have a class that extends from Printable, it prints fine using the standard PrintJob, but i would like to move to DocPrintJob so i can listen to the status of the print (successful print etc).
My current code looks like this to create a print job and print
// define printer
AttributeSet attributes = new HashAttributeSet();
attributes.add(new Copies(1));
// get printerJob
PrinterJob printJob = PrinterJob.getPrinterJob();
PageFormat pageFormat = printJob.defaultPage();
// sizing (standard is 72dpi, so multiple inches by this)
Double height = 8d * 72d;
Double width = 3d * 72d;
Double margin = 0.1d * 72d;
// set page size
Paper paper = pageFormat.getPaper();
paper.setSize(width, height);
paper.setImageableArea(margin, margin, width - (margin * 2), height - (margin * 2));
// set orientation and paper
pageFormat.setOrientation(PageFormat.PORTRAIT);
pageFormat.setPaper(paper);
// create a book for printing
Book book = new Book();
book.append(new EventPrint(args.getEvent()), pageFormat);
// set book to what we are printing
printJob.setPageable(book);
// set print request attributes
PrintRequestAttributeSet aset = new HashPrintRequestAttributeSet();
aset.add(OrientationRequested.PORTRAIT);
// now print
try {
printJob.print();
} catch (PrinterException e) {
e.printStackTrace();
}
Now to convert this to a DocPrintJob, i followed this link which told me how to convert from PrintJob to DocPrintJob. So now my code became this
PrintService[] services = PrinterJob.lookupPrintServices(); //list of printers
PrintService printService = services[0];
DocFlavor[] flavours = printService.getSupportedDocFlavors();
// may need to determine which printer to use
DocPrintJob printJob = printService.createPrintJob();
// get out printable
EventPrint eventPrint = new EventPrint(args.getEvent());
// convert printable to doc
Doc doc = new SimpleDoc(eventPrint, DocFlavor.SERVICE_FORMATTED.PRINTABLE, null);
// add eventlistener to printJob
printJob.addPrintJobListener(new PrintJobListener() {
#Override
public void printDataTransferCompleted(PrintJobEvent pje) {
Console.Log("Print data sent successfully");
}
#Override
public void printJobCompleted(PrintJobEvent pje) {
Console.Log("Print successful");
}
#Override
public void printJobFailed(PrintJobEvent pje) {
Console.Log("Print failed");
}
#Override
public void printJobCanceled(PrintJobEvent pje) {
Console.Log("Print cancelled");
}
#Override
public void printJobNoMoreEvents(PrintJobEvent pje) {
Console.Log("No more printJob events");
}
#Override
public void printJobRequiresAttention(PrintJobEvent pje) {
Console.Log("printJob requires attention");
}
});
PrintRequestAttributeSet aset = new HashPrintRequestAttributeSet();
aset.add(new Copies(1));
try {
printJob.print(doc, aset);
} catch (Exception e) {
}
Now for some reason, my print just keeps executing (400+ times until i close application). I am not sure if it is because maybe i have not set the paper size, like i did when i was using PrintJob? Would that cause it? If so, how can i set the paperSize of the DocPrintJob as it doesnt have the methods the normal printJob has?
Anyone else faces this problem before?
EDIT: Here is my eventPrint class and the class it inherits from
PRINTABLEBASE.JAVA
public class PrintableBase {
public Graphics2D g2d;
public float x, y, imageHeight, imageWidth, maxY;
public enum Alignment { LEFT, RIGHT, CENTER };
public void printSetup(Graphics graphics, PageFormat pageFormat) {
// user (0,0) is typically outside the imageable area, so we must translate
// by the X and Y values in the pageFormat to avoid clipping
g2d = (Graphics2D) graphics;
g2d.translate(pageFormat.getImageableX(), pageFormat.getImageableY());
// get starter X and Y
x = 0;//(float)pageFormat.getImageableX();
// do not offset vertical as pushes ticket down too much
y = 0;//(float)pageFormat.getImageableY();
// get height and width of the printable image
imageWidth = (float)pageFormat.getImageableWidth();
imageHeight = (float)pageFormat.getImageableHeight();
// maximum that we can go vertically
maxY = y;
Console.Log("imageWidth:" + imageWidth);
Console.Log("imageHeight: " + imageHeight);
Console.Log("X: " + x);
Console.Log("Y: " + y);
}
public void setFont(Font font) {
g2d.setFont(font);
}
public float addSeparatorLine(float y, float imageWidth) {
String fontName = g2d.getFont().getName();
int fontStyle = g2d.getFont().getStyle();
int fontSize = g2d.getFont().getSize();
g2d.setFont(new Font("Arial", Font.PLAIN, 10));
y = drawFirstLine(g2d, "---------------------------------------------------------------------------------------", imageWidth, 0, y, Alignment.LEFT);
// revery font
g2d.setFont(new Font(fontName, fontStyle, fontSize));
return y + 5;
}
public BufferedImage scaleImage(BufferedImage sbi, int dWidth, int dHeight) {
BufferedImage dbi = null;
if(sbi != null) {
// calculate ratio between standard size and scaled
double wRatio = (double)dWidth / (double)sbi.getWidth();
double hRatio = (double)dHeight / (double)sbi.getHeight();
// use wRatio by default
double sWidth = (double)sbi.getWidth() * wRatio;
double sHeight = (double)sbi.getHeight() * wRatio;
// if hRation is small, use that, as image will be reduced by more
if (hRatio < wRatio) {
sWidth = (double)sbi.getWidth() * hRatio;
sHeight = (double)sbi.getHeight() * hRatio;
}
double sRatio = (wRatio < hRatio) ? wRatio : hRatio;
// now create graphic, of new size
dbi = new BufferedImage((int)sWidth, (int)sHeight, BufferedImage.TYPE_INT_ARGB);
Graphics2D g = dbi.createGraphics();
AffineTransform at = AffineTransform.getScaleInstance(sRatio, sRatio);
g.drawRenderedImage(sbi, at);
}
return dbi;
}
// This function will only add the first line of text and will not wrap
// useful for adding the ticket title.
// Returns the height of the text
public float drawFirstLine(Graphics2D g2, String text, float width, float x, float y, Alignment alignment) {
AttributedString attstring = new AttributedString(text);
attstring.addAttribute(TextAttribute.FONT, g2.getFont());
AttributedCharacterIterator paragraph = attstring.getIterator();
int paragraphStart = paragraph.getBeginIndex();
int paragraphEnd = paragraph.getEndIndex();
FontRenderContext frc = g2.getFontRenderContext();
LineBreakMeasurer lineMeasurer = new LineBreakMeasurer(paragraph, frc);
// Set break width to width of Component.
float breakWidth = width;
float drawPosY = y;
// Set position to the index of the first character in the paragraph.
lineMeasurer.setPosition(paragraphStart);
// Get lines until the entire paragraph has been displayed.
if (lineMeasurer.getPosition() < paragraphEnd) {
// Retrieve next layout. A cleverer program would also cache
// these layouts until the component is re-sized.
TextLayout layout = lineMeasurer.nextLayout(breakWidth);
// Compute pen x position.
float drawPosX;
switch (alignment){
case RIGHT:
drawPosX = (float) x + breakWidth - layout.getAdvance();
break;
case CENTER:
drawPosX = (float) x + (breakWidth - layout.getAdvance())/2;
break;
default:
drawPosX = (float) x;
}
// Move y-coordinate by the ascent of the layout.
drawPosY += layout.getAscent();
// Draw the TextLayout at (drawPosX, drawPosY).
layout.draw(g2, drawPosX, drawPosY);
// Move y-coordinate in preparation for next layout.
drawPosY += layout.getDescent() + layout.getLeading();
}
return drawPosY;
}
/**
* Draw paragraph.
*
* #param g2 Drawing graphic.
* #param text String to draw.
* #param width Paragraph's desired width.
* #param x Start paragraph's X-Position.
* #param y Start paragraph's Y-Position.
* #param dir Paragraph's alignment.
* #return Next line Y-position to write to.
*/
protected float drawParagraph (String text, float width, float x, float y, Alignment alignment){
AttributedString attstring = new AttributedString(text);
attstring.addAttribute(TextAttribute.FONT, g2d.getFont());
AttributedCharacterIterator paragraph = attstring.getIterator();
int paragraphStart = paragraph.getBeginIndex();
int paragraphEnd = paragraph.getEndIndex();
FontRenderContext frc = g2d.getFontRenderContext();
LineBreakMeasurer lineMeasurer = new LineBreakMeasurer(paragraph, frc);
// Set break width to width of Component.
float breakWidth = width;
float drawPosY = y;
// Set position to the index of the first character in the paragraph.
lineMeasurer.setPosition(paragraphStart);
// Get lines until the entire paragraph has been displayed.
while (lineMeasurer.getPosition() < paragraphEnd) {
// Retrieve next layout. A cleverer program would also cache
// these layouts until the component is re-sized.
TextLayout layout = lineMeasurer.nextLayout(breakWidth);
// Compute pen x position.
float drawPosX;
switch (alignment){
case RIGHT:
drawPosX = (float) x + breakWidth - layout.getAdvance();
break;
case CENTER:
drawPosX = (float) x + (breakWidth - layout.getAdvance())/2;
break;
default:
drawPosX = (float) x;
}
// Move y-coordinate by the ascent of the layout.
drawPosY += layout.getAscent();
// Draw the TextLayout at (drawPosX, drawPosY).
layout.draw(g2d, drawPosX, drawPosY);
// Move y-coordinate in preparation for next layout.
drawPosY += layout.getDescent() + layout.getLeading();
}
return drawPosY;
}
}
EVENTPRINT.JAVA
public class EventPrint extends PrintableBase implements Printable {
private Event event;
public EventPrint(Event event) {
this.event = event;
}
#Override
public int print(Graphics graphics, PageFormat pageFormat, int pageIndex)
throws PrinterException {
// setup
super.printSetup(graphics, pageFormat);
// title
super.setFont(new Font("Tahoma", Font.BOLD, 16));
y = super.drawParagraph(event.getTitle(), imageWidth, x, y, Alignment.LEFT);
RETURN PAGE_EXISTS;
}
I would say that your problem is that you never tell the API that there are no more pages....
public int print(Graphics graphics, PageFormat pageFormat, int pageIndex)
throws PrinterException {
// setup
super.printSetup(graphics, pageFormat);
// title
super.setFont(new Font("Tahoma", Font.BOLD, 16));
y = super.drawParagraph(event.getTitle(), imageWidth, x, y, Alignment.LEFT);
RETURN PAGE_EXISTS;
}
So, assuming you only want to print a single page, you could use something like...
public int print(Graphics graphics, PageFormat pageFormat, int pageIndex)
throws PrinterException {
int result = NO_SUCH_PAGE;
if (pageIndex == 0) {
// setup
super.printSetup(graphics, pageFormat);
// title
super.setFont(new Font("Tahoma", Font.BOLD, 16));
y = super.drawParagraph(event.getTitle(), imageWidth, x, y, Alignment.LEFT);
result = PAGE_EXISTS;
}
RETURN result;
}
Otherwise the API doesn't know when to stop printing.
Bookable uses a different approach, in that each page of the book is only printed once and it will continue until all pages are printed. Printable is different, it will continue printing until you tell it to stop
Take a look at A Basic Printing Program for more details
I also encountered some issues when switching from PrinterJob to DocPrintJob. Your code seems fine to me, so maybe you are right with the page size. You can set the page size like this:
aset.add(new MediaPrintableArea(0, 0, width, height, MediaPrintableArea.MM));
But it depends on your printable object how to set this. I have created a bytearray (PDF) with iText and set the page size there. Then, I set the width and height in the above code to Integer.MAX_VALUE.
I can post my entire code when I get home. Hope it helps!

JavaFX Printable to Image very pix-elated, but perfect to printer

I have a printable object that prints perfectly fine to a printer, but when i print it to an Image, then it is very pixelated?
Here is my code to setup a printer for printing and to an image
private PageFormat setupPrinter() {
// sizing (standard is 72dpi, so multiple inches by this)
Double height = 4d * 72d;
Double width = 3d * 72d;
Double margin = 0.1d * 72d;
// now lets print it
AttributeSet attributes = new HashAttributeSet();
attributes.add(new Copies(1));
PrinterJob printJob = PrinterJob.getPrinterJob();
PageFormat pageFormat = printJob.defaultPage();
// if there are more than 10 items, up the paper size to 6inch.
// This will handle up to 24 different items
if (1 == 2) height = 6d * 72d;
// set page size
Paper paper = pageFormat.getPaper();
paper.setSize(width, height);
paper.setImageableArea(margin, margin, width - (margin * 2), height - (margin * 2));
// set orientation and paper
pageFormat.setOrientation(PageFormat.PORTRAIT);
pageFormat.setPaper(paper);
return pageFormat;
}
private void printToImage() {
MyPrintable myPrintable = new MyPrintable();
// setup our printer
PageFormat pageFormat = setupPrinter();
// set size of imageView, using the hieght and width values
double imageHeight = pageFormat.getHeight();
double imageWidth = pageFormat.getWidth();
// create our image/graphics
BufferedImage image = new BufferedImage((int)imageWidth, (int)imageHeight, BufferedImage.TYPE_INT_ARGB);
Graphics graphics = image.getGraphics();
// color background white
graphics.setColor(Color.WHITE);
((Graphics2D) graphics).fill(new Rectangle.Float(0, 0, (float)imageWidth, (float)imageHeight));
// directly call our print method, passing graphics, pageFormat and pageIndex
try {
myPrintable.print(graphics, pageFormat, 0);
} catch (PrinterException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
graphics.dispose();
// set our image
imgReport.setImage(SwingFXUtils.toFXImage(image, null));
// now lets show the preview pane
reportPane.setVisible(true);
}
public void printToPrinter(ActionEvent event) {
PrinterJob printJob = PrinterJob.getPrinterJob();
PageFormat pageFormat = setupPrinter();
printJob.setPrintable(new MyPrintable(), pageFormat);
try {
printJob.print();
} catch (Exception e) {
e.printStackTrace();
}
}
public MyPrintable() {
public int print(Graphics graphics, PageFormat pageFormat, int pageIndex) throws PrinterException {
if (pageIndex > 0) {
return NO_SUCH_PAGE;
}
// user (0,0) is typically outside the imageable area, so we must translate
// by the X and Y values in the pageFormat to avoid clipping
Graphics2D g2d = (Graphics2D) graphics;
g2d.translate(pageFormat.getImageableX(), pageFormat.getImageableY());
// add text etc here
........
}
}
Here is an example of how pixelated it is. Bit it fits in the image perfectly....
You can use a controlling rendering quality
read this:
https://docs.oracle.com/javase/tutorial/2d/advanced/quality.html
example for your code:
Graphics2D graphics = (Graphics2D)image.getGraphics();
RenderingHints rh = new RenderingHints(
RenderingHints.KEY_ANTIALIASING,
RenderingHints.VALUE_ANTIALIAS_ON);
g2.setRenderingHints(rh);
graphics.setColor(Color.WHITE);
graphics.fill(new Rectangle.Float(0, 0, (float)imageWidth, (float)imageHeight));

How can I print a custom paper size (cheques 8" x 4")?

I am trying to print a custom paper size from a Java applet. I have set the paper size but it is being ignored.
I have also tried using the book method as I have seen something about this helping to get it working but when I use that it just prints a blank page and still seems to be about A4 (I'm looking to print cheques which are obviously much smaller (8" x 4")).
I am trying to print HTML from a JEditorPane if that makes any difference.
If you have any ideas I would be very grateful, I'm tearing my hair out with this one.
I should also add that I am very much a beginner when it comes to Java.
Here is what I have so far:
Updated:
I have now got the page size right but can't seem to get the HTML page I'm loading to fit or line up with the page size.
Update:
Now I just can't get the applet to run in the browser. It works from eclipse just not the browser. I will also need to pass the URL from a parameter.
Here is the HTML applet tag I'm using and updated Java code:
<!DOCTYPE html>
<html>
<head><title>Printing Cheque</title></head>
<body>
<applet width=100 height=100 code="HTMLPrinter"
archive="cheque_print.jar">
</applet>
</body>
</html>
package com.yunatech.pns.chequeprint;
import java.applet.Applet;
import java.awt.Graphics;
import java.awt.Graphics2D;
import java.awt.print.Book;
import java.awt.print.PageFormat;
import java.awt.print.Paper;
import java.awt.print.Printable;
import java.awt.print.PrinterException;
import java.awt.print.PrinterJob;
import javax.swing.JEditorPane;
public class HTMLPrinter extends Applet {
/**
*
*/
private static final long serialVersionUID = 8065834484717197790L;
private static JEditorPane editor;
public HTMLPrinter() {
try {
editor = new JEditorPane();
editor.setPage("http://localhost/print_test/test.html");
PrinterJob pj = PrinterJob.getPrinterJob();
if (pj.printDialog()) {
PageFormat pf = pj.defaultPage();
Paper paper = pf.getPaper();
double width = 8d * 72d;
double height = 4d * 72d;
double margin = 1d * 72d;
paper.setSize(width, height);
paper.setImageableArea(
margin,
0,
width - (margin * 2),
height);
System.out.println("Before- " + dump(paper));
pf.setOrientation(PageFormat.PORTRAIT);
pf.setPaper(paper);
System.out.println("After- " + dump(paper));
System.out.println("After- " + dump(pf));
dump(pf);
PageFormat validatePage = pj.validatePage(pf);
System.out.println("Valid- " + dump(validatePage));
Book pBook = new Book();
pBook.append(new Page(), pf);
pj.setPageable(pBook);
try {
pj.print();
} catch (PrinterException ex) {
ex.printStackTrace();
}
}
} catch (Exception exp) {
exp.printStackTrace();
}
}
protected static String dump(Paper paper) {
StringBuilder sb = new StringBuilder(64);
sb.append(paper.getWidth()).append("x").append(paper.getHeight())
.append("/").append(paper.getImageableX()).append("x").
append(paper.getImageableY()).append(" - ").append(paper
.getImageableWidth()).append("x").append(paper.getImageableHeight());
return sb.toString();
}
protected static String dump(PageFormat pf) {
Paper paper = pf.getPaper();
return dump(paper);
}
public static class Page implements Printable {
public int print(Graphics graphics, PageFormat pageFormat, int pageIndex) {
if (pageIndex >= 1) return Printable.NO_SUCH_PAGE;
Graphics2D g2d = (Graphics2D)graphics;
g2d.translate((int)pageFormat.getImageableX(), (int)pageFormat.getImageableY());
editor.setSize((int)pageFormat.getImageableWidth(), (int)pageFormat.getImageableHeight());
editor.print(g2d);
return Printable.PAGE_EXISTS;
}
}
}
Thanks in advance for any help you can offer.
Printing is designed to work in pixels per inch. The base print API uses a DPI of 72.
You need to convert your measurements accordingly...
double paperWidth = 8 * 72d;
double paperHeight = 4 * 72d;
double margin = 1 * 72d;
UPDATED with example
g2d.setClip(0, 0, (int)pageFormat.getImageableWidth(), (int)pageFormat.getImageableHeight()); is ill adviced, dangerous and generally, not required, besides which, you've used the wrong width and height values. The imageable parameters take into account the margins, but you've not translated the graphics, which will more then likely cut of the bottom, left portion of the area you do have to print to...
I'd just avoid using clipping
public class TestPrinting01 {
public static void main(String[] args) {
PrinterJob pj = PrinterJob.getPrinterJob();
if (pj.printDialog()) {
PageFormat pf = pj.defaultPage();
Paper paper = pf.getPaper();
double width = 8d * 72d;
double height = 4d * 72d;
double margin = 1d * 72d;
paper.setSize(width, height);
paper.setImageableArea(
margin,
margin,
width - (margin * 2),
height - (margin * 2));
System.out.println("Before- " + dump(paper));
pf.setOrientation(PageFormat.LANDSCAPE);
pf.setPaper(paper);
System.out.println("After- " + dump(paper));
System.out.println("After- " + dump(pf));
dump(pf);
PageFormat validatePage = pj.validatePage(pf);
System.out.println("Valid- " + dump(validatePage));
Book pBook = new Book();
pBook.append(new Page(), pf);
pj.setPageable(pBook);
try {
pj.print();
} catch (PrinterException ex) {
ex.printStackTrace();
}
}
}
protected static String dump(Paper paper) {
StringBuilder sb = new StringBuilder(64);
sb.append(paper.getWidth()).append("x").append(paper.getHeight())
.append("/").append(paper.getImageableX()).append("x").
append(paper.getImageableY()).append(" - ").append(paper
.getImageableWidth()).append("x").append(paper.getImageableHeight());
return sb.toString();
}
protected static String dump(PageFormat pf) {
Paper paper = pf.getPaper();
return dump(paper);
}
public static class Page implements Printable {
public int print(Graphics graphics, PageFormat pageFormat, int pageIndex) {
if (pageIndex >= 1) {
return Printable.NO_SUCH_PAGE;
}
Graphics2D g2d = (Graphics2D) graphics;
// Be careful of clips...
g2d.translate((int) pageFormat.getImageableX(), (int) pageFormat.getImageableY());
double width = pageFormat.getImageableWidth();
double height = pageFormat.getImageableHeight();
g2d.drawRect(0, 0, (int)pageFormat.getImageableWidth() - 1, (int)pageFormat.getImageableHeight() - 1);
FontMetrics fm = g2d.getFontMetrics();
String text = "top";
g2d.drawString(text, 0, fm.getAscent());
text = "bottom";
double x = width - fm.stringWidth(text);
double y = (height - fm.getHeight()) + fm.getAscent();
g2d.drawString(text, (int)x, (int)y);
return Printable.PAGE_EXISTS;
}
}
}
UPDATED
When printing components, you become responsible for it's layout.
public class TestPrinting01 {
private static JEditorPane editor;
public static void main(String[] args) {
try {
editor = new JEditorPane();
editor.setPage(new File("C:/hold/search.htm").toURI().toURL());
PrinterJob pj = PrinterJob.getPrinterJob();
if (pj.printDialog()) {
PageFormat pf = pj.defaultPage();
Paper paper = pf.getPaper();
double width = 8d * 72d;
double height = 4d * 72d;
double margin = 1d * 72d;
paper.setSize(width, height);
paper.setImageableArea(
margin,
margin,
width - (margin * 2),
height - (margin * 2));
System.out.println("Before- " + dump(paper));
pf.setOrientation(PageFormat.LANDSCAPE);
pf.setPaper(paper);
System.out.println("After- " + dump(paper));
System.out.println("After- " + dump(pf));
dump(pf);
PageFormat validatePage = pj.validatePage(pf);
System.out.println("Valid- " + dump(validatePage));
Book pBook = new Book();
pBook.append(new Page(), pf);
pj.setPageable(pBook);
try {
pj.print();
} catch (PrinterException ex) {
ex.printStackTrace();
}
}
} catch (Exception exp) {
exp.printStackTrace();
}
}
protected static String dump(Paper paper) {
StringBuilder sb = new StringBuilder(64);
sb.append(paper.getWidth()).append("x").append(paper.getHeight())
.append("/").append(paper.getImageableX()).append("x").
append(paper.getImageableY()).append(" - ").append(paper
.getImageableWidth()).append("x").append(paper.getImageableHeight());
return sb.toString();
}
protected static String dump(PageFormat pf) {
Paper paper = pf.getPaper();
return dump(paper);
}
public static class Page implements Printable {
public int print(Graphics graphics, PageFormat pageFormat, int pageIndex) {
if (pageIndex >= 1) {
return Printable.NO_SUCH_PAGE;
}
Graphics2D g2d = (Graphics2D) graphics;
// Be careful of clips...
// g2d.setClip(0, 0, (int) pageFormat.getWidth(), (int) pageFormat.getHeight());
g2d.translate((int) pageFormat.getImageableX(), (int) pageFormat.getImageableY());
double width = pageFormat.getImageableWidth();
double height = pageFormat.getImageableHeight();
System.out.println("width = " + width);
System.out.println("height = " + height);
editor.setLocation(0, 0);
editor.setSize((int)width, (int)height);
editor.printAll(g2d);
g2d.setColor(Color.BLACK);
g2d.draw(new Rectangle2D.Double(0, 0, width, height));
return Printable.PAGE_EXISTS;
}
}
}

Categories

Resources