I'm using the following code to print some text on a thermal printer with 80mm roll paper:
public class printnow {
public static void printCard(final String bill) {
final PrinterJob job = PrinterJob.getPrinterJob();
Printable contentToPrint = new Printable() {
#Override
public int print(Graphics graphics, PageFormat pageFormat, int pageIndex) throws PrinterException {
Graphics2D g2d = (Graphics2D) graphics;
g2d.translate(pageFormat.getImageableX(), pageFormat.getImageableY());
g2d.setFont(new Font("Monospaced", Font.BOLD, 7));
pageFormat.setOrientation(PageFormat.PORTRAIT);
Paper pPaper = pageFormat.getPaper();
pPaper.setImageableArea(0, 0, pPaper.getWidth() , pPaper.getHeight() -2);
pageFormat.setPaper(pPaper);
if (pageIndex > 0)
return NO_SUCH_PAGE; //Only one page
String Bill [] = bill.split(";");
int y = 0;
for (int i = 0; i < Bill.length; i++) {
g2d.drawString(Bill[i], 0, y);
y = y + 15;
}
return PAGE_EXISTS;
}
};
boolean don = job.printDialog();
job.setPrintable(contentToPrint);
try {
job.print();
} catch (PrinterException e) {
System.err.println(e.getMessage());
}
}
}
This is printing extremely fine and is exactly what I want. But when I remove the following line to disable the print dialog box and automate the process of printing, my print messes up and the printer automatically takes some margin in the left.
boolean don = job.printDialog();
Any idea on why this is happening and how can it be solved?
After a lot of research and a applying a little brain, I found out the solution. It was a very small but silly mistake. Read the following source code:
public class printnow {
public static void printCard(final String bill ) {
final PrinterJob job = PrinterJob.getPrinterJob();
Printable contentToPrint = new Printable() {
#Override
public int print(Graphics graphics, PageFormat pageFormat, int pageIndex) throws PrinterException {
Graphics2D g2d = (Graphics2D) graphics;
g2d.translate(pageFormat.getImageableX(), pageFormat.getImageableY());
g2d.setFont(new Font("Monospaced", Font.BOLD, 7));
if (pageIndex > 0) {
return NO_SUCH_PAGE;
} //Only one page
String Bill [] = bill.split(";");
int y = 0;
for (int i = 0; i < Bill.length; i++) {
g2d.drawString(Bill[i], 0, y);
y = y + 15;
}
return PAGE_EXISTS;
}
};
PageFormat pageFormat = new PageFormat();
pageFormat.setOrientation(PageFormat.PORTRAIT);
Paper pPaper = pageFormat.getPaper();
pPaper.setImageableArea(0, 0, pPaper.getWidth() , pPaper.getHeight() -2);
pageFormat.setPaper(pPaper);
job.setPrintable(contentToPrint, pageFormat);
try {
job.print();
} catch (PrinterException e) {
System.err.println(e.getMessage());
}
}
}
In the previous source code (the wrong one), when the application triggers a print dialog box and the user clicks OK, the default printing preferences are transferred to the Java app and it prints what is required. but when we disable the print dialog box by removing this line:
boolean don = job.printDialog();
an unknow PageFormat is transferred which arises out of nowhere. The problem was not with our defined PageFormat, the problem was that the pageFormat is passed to a printing method which we were not doing initially:
job.setPrintable(contentToPrint, pageFormat);
Notice the second parameter being passed to the above method.
Hope this helps everyone. :)
Related
My java thermal printer code not able to print long receipt(more than A4 sheet size). Its work fine normally, but in case where there is too much items in cart then it generate half print. My code is under mentioned-
public PrintReceipt(Map<String,String> hm){
/*
product details code..
*/
try{
input = new FileInputStream("C:/printer.properties");
prop.load(input);
printerName=prop.getProperty("receiptPrinter");
System.out.println("Printer Name "+printerName);
}catch(Exception exception){
System.out.println("Properties file not found");
}
PrintService[] pservices = PrintServiceLookup.lookupPrintServices(null,null);
for (int i = 0; i < pservices.length; i++) {
if (pservices[i].getName().equalsIgnoreCase(printerName)) {
job = PrinterJob.getPrinterJob();
PageFormat pf = job.defaultPage();
double margin = 1.0D;
Paper paper = new Paper();
paper.setSize(216D, paper.getHeight());
paper.setImageableArea(margin, margin, paper.getWidth() - margin * 1.5D, paper.getHeight() - margin * 1.5D);
pf.setPaper(paper);
job.setCopies(1);
pf.setOrientation(1);
job.setPrintable(this, pf);
try
{
job.print();
}
catch(PrinterException ex)
{
System.out.println("Printing failed");
}
}
}
}
public int print(Graphics graphics, PageFormat pageFormat, int pageIndex)
throws PrinterException {
if(pageIndex > 0)
return 1;
Graphics2D g2d = (Graphics2D)graphics;
double width = pageFormat.getImageableWidth();
double height = pageFormat.getImageableHeight();
g2d.translate((int) pageFormat.getImageableX(),(int) pageFormat.getImageableY());
Font font = new Font("Monospaced",Font.BOLD,8);
g2d.setFont(font);
try {
/*
* Draw Image*
*/
int x=50 ;
int y=10;
int imagewidth=100;
int imageheight=50;
BufferedImage read = ImageIO.read(new File("C:/hotel.png"));
g2d.drawImage(read,x,y,imagewidth,imageheight,null); //draw image
g2d.drawString("-- * Resturant * --", 20,y+60);
g2d.drawLine(10, y+70, 180, y+70); //draw line
} catch (IOException e) {
e.printStackTrace();
}
try{
/*Draw Header*/
/*
product details code..
*/
/*Footer*/
//end of the receipt
}
catch(Exception r){
r.printStackTrace();
}
return 0;
}
Please let me know how can i generate long receipt print by correcting my code or if you have any better solution to do this.
Right here:
Paper paper = new Paper();
paper.setSize(216D, paper.getHeight());
You are creating a new Paper object and not setting its height.
Here is a link to the documentation of this class.
When creating a Paper object, it is the application's responsibility to ensure that the paper size and the imageable area are compatible
You need to set the height of the paper by calling paper.setSize(width, height) or it will use its default size property.
The dimensions are supplied in 1/72nds of an inch.
So both width and height will need to be provided in this format as doubles
DocFlavor flavor = DocFlavor.INPUT_STREAM.AUTOSENSE;
PrintRequestAttributeSet pras = new HashPrintRequestAttributeSet();
PrintService printService[] = PrintServiceLookup.lookupPrintServices(
flavor, pras);
PrintService service = findPrintService(printerName, printService);
PDDocument document = PDDocument.load(bytes);
PrinterJob job = PrinterJob.getPrinterJob();
job.setPrintService(service);
job.setPageable(new PDFPageable(document));
job.print();
if (document != null) {
document.close();
}
So I was tinkering with this code that I found http://docs.oracle.com/javase/tutorial/2d/printing/examples/PaginationExample.java
I altered the page size to 300, 400 when I tried printing to XPS the first page is always default and the following is 300,400, I want to is set all printed pages to 300,400
below is the code
package app;
import java.awt.*;
import java.awt.event.*;
import javax.swing.*;
import java.awt.print.*;
public class PaginationExample implements Printable, ActionListener {
int[] pageBreaks; // array of page break line positions.
/* Synthesise some sample lines of text */
String[] textLines;
private void initTextLines() {
if (textLines == null) {
int numLines = 200;
textLines = new String[numLines];
for (int i = 0; i < numLines; i++) {
textLines[i] = "This is line number " + i;
}
}
}
public int print(Graphics g, PageFormat pf, int pageIndex)
throws PrinterException {
pf.setPaper(paper);
Font font = new Font("Serif", Font.PLAIN, 10);
FontMetrics metrics = g.getFontMetrics(font);
int lineHeight = metrics.getHeight();
if (pageBreaks == null) {
initTextLines();
int linesPerPage = (int) (pf.getImageableHeight() / lineHeight);
int numBreaks = (textLines.length - 1) / linesPerPage;
pageBreaks = new int[numBreaks];
for (int b = 0; b < numBreaks; b++) {
pageBreaks[b] = (b + 1) * linesPerPage;
}
}
if (pageIndex > pageBreaks.length) {
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
* Since we are drawing text we
*/
Graphics2D g2d = (Graphics2D) g;
g2d.translate(pf.getImageableX(), pf.getImageableY());
/* Draw each line that is on this page.
* Increment 'y' position by lineHeight for each line.
*/
int y = 0;
int start = (pageIndex == 0) ? 0 : pageBreaks[pageIndex - 1];
int end = (pageIndex == pageBreaks.length)
? textLines.length : pageBreaks[pageIndex];
for (int line = start; line < end; line++) {
y += lineHeight;
g.drawString(textLines[line], 0, y);
}
/* tell the caller that this page is part of the printed document */
return PAGE_EXISTS;
}
public void actionPerformed(ActionEvent e) {
PrinterJob job = PrinterJob.getPrinterJob();
job.setPrintable(this);
boolean ok = job.printDialog();
if (ok) {
try {
job.print();
} catch (PrinterException ex) {
/* The job did not successfully complete */
}
}
}
private static Paper paper;
public static void main(String args[]) {
paper = new Paper();
paper.setSize(300, 400);
try {
String cn = UIManager.getSystemLookAndFeelClassName();
UIManager.setLookAndFeel(cn); // Use the native L&F
} catch (Exception cnf) {
}
JFrame f = new JFrame("Printing Pagination Example");
f.addWindowListener(new WindowAdapter() {
public void windowClosing(WindowEvent e) {
System.exit(0);
}
});
JButton printButton = new JButton("Print Pages");
printButton.addActionListener(new PaginationExample());
f.add("Center", printButton);
f.pack();
f.setVisible(true);
}
}
Try to use the Book class which is used in this thread.
Book pBook = new Book();
pBook.append(this, pPageFormat);
pPrinterJob.setPageable(pBook);
pPrinterJob.print();
I just got the printer to work in java how I need it too, but there's one last problem I need to solve. When it prints, the font's width is rather stretched, and not crisp and clear like it should be.
Here is my code my the actual drawing to the paper:
FontMetrics metrics = graphics.getFontMetrics(font);
int lineHeight = metrics.getHeight();
arrangePage(graphics, pageFormat, lineHeight);
if (page > pageBreaks.length){
return NO_SUCH_PAGE;
}
Graphics2D g = (Graphics2D) graphics;
g.translate(pageFormat.getImageableX(), pageFormat.getImageableY());
g.setFont(font);
int y = 0;
int begin = 0;
if (page == 0){
begin = 0;
}else begin = pageBreaks[page-1];
int end = 0;
if (page == pageBreaks.length){
end = lines.length;
}else end = pageBreaks[page];
for (int line = begin; line < end; line++){
y += lineHeight;
g.drawString(lines[line], 0, y);
}
string = deepCopy;
return PAGE_EXISTS;
How do I get rid of the stretching? It can be noted that this is based off this tutorial:
http://docs.oracle.com/javase/tutorial/2d/printing/set.html
Any advice or help is greatly appreciated.
The default DPI is normal 72 DPI (I believe), which, on printed paper, is pretty terrible. You need to prompt the print API to try and find a printer with a better DPI.
Basically you need to use the print services API.
Try something like...
public class PrintTest01 {
public static void main(String[] args) {
PrinterResolution pr = new PrinterResolution(300, 300, PrinterResolution.DPI);
PrintRequestAttributeSet aset = new HashPrintRequestAttributeSet();
aset.add(MediaSizeName.ISO_A4);
aset.add(pr);
aset.add(OrientationRequested.PORTRAIT);
PrinterJob pj = PrinterJob.getPrinterJob();
pj.setPrintable(new Page());
try {
pj.print(aset);
} catch (PrinterException ex) {
ex.printStackTrace();
}
}
public static class Page implements Printable {
#Override
public int print(Graphics g, PageFormat pageFormat, int pageIndex) throws PrinterException {
if (pageIndex > 0) {
return NO_SUCH_PAGE;
}
Graphics2D g2d = (Graphics2D) g;
g2d.translate(pageFormat.getImageableX(), pageFormat.getImageableY());
g.setFont(new Font("Arial", Font.PLAIN, 128));
FontMetrics fm = g.getFontMetrics();
int x = (int)(pageFormat.getWidth() - fm.stringWidth("A")) / 2;
int y = (int)((pageFormat.getHeight() - fm.getHeight()) / 2) + fm.getAscent();
g2d.drawString("A", x, y);
return PAGE_EXISTS;
}
}
}
You might find Working with Print Services and Attributes of some help...
I should warn you, this is going to print to the first print that it can find that meets the PrintRequestAttributeSet. You could also add in the print dialog to see what's it doing, but that's another level of complexity I can live without right now ;)
The above worked! To open a print dialog with it, use this:
PrinterJob job = PrinterJob.getPrinterJob();
TextDocumentPrinter document = new TextDocumentPrinter();
PrinterResolution pr = new PrinterResolution(300, 300, PrinterResolution.DPI);
PrintRequestAttributeSet aset = new HashPrintRequestAttributeSet();
aset.add(MediaSizeName.ISO_A4);
aset.add(pr);
aset.add(OrientationRequested.PORTRAIT);
job.setPrintable(document);
boolean doPrint = false;
if (showDialog){
doPrint = job.printDialog(aset);
}else doPrint = true;
if (doPrint){
try{
job.print();
}catch(PrinterException e){
e.printStackTrace();
}
}
The aset variable contains all of your new default values, and by plugging it into the printDialog, those are inputted into the printJob and consequently show up on the paper! They can be changed in the dialog, as well.
I wrote a program that generates a BufferedImage to be displayed on the screen and then printed. Part of the image includes grid lines that are 1 pixel wide. That is, the line is 1 pixel, with about 10 pixels between lines. Because of screen resolution, the image is displayed much bigger than that, with several pixels for each line. I'd like to draw it smaller, but when I scale the image (either by using Image.getScaledInstance or Graphics2D.scale), I lose significant amounts of detail.
I'd like to print the image as well, and am dealing with the same problem. In that case, I am using this code to set the resolution:
HashPrintRequestAttributeSet set = new HashPrintRequestAttributeSet();
PrinterResolution pr = new PrinterResolution(250, 250, ResolutionSyntax.DPI);
set.add(pr);
job.print(set);
which works to make the image smaller without losing detail. But the problem is that the image is cut off at the same boundary as if I hadn't set the resolution. I'm also confused because I expected a larger number of DPI to make a smaller image, but it's working the other way.
I'm using java 1.6 on Windows 7 with eclipse.
Regarding the image being cut-off on the page boundary, have you checked the clip region of the graphics? I mean try :
System.out.println(graphics.getClipBounds());
and make sure it is correctly set.
I had the same problem. Here is my solution.
First change the resolution of the print job...
PrinterJob job = PrinterJob.getPrinterJob();
// Create the paper size of our preference
double cmPx300 = 300.0 / 2.54;
Paper paper = new Paper();
paper.setSize(21.3 * cmPx300, 29.7 * cmPx300);
paper.setImageableArea(0, 0, 21.3 * cmPx300, 29.7 * cmPx300);
PageFormat format = new PageFormat();
format.setPaper(paper);
// Assign a new print renderer and the paper size of our choice !
job.setPrintable(new PrintReport(), format);
if (job.printDialog()) {
try {
HashPrintRequestAttributeSet set = new HashPrintRequestAttributeSet();
PrinterResolution pr = new PrinterResolution((int) (dpi), (int) (dpi), ResolutionSyntax.DPI);
set.add(pr);
job.setJobName("Jobname");
job.print(set);
} catch (PrinterException e) {
}
}
Now you can draw everything you like into the new high resolution paper like this !
public class PrintReport implements Printable {
#Override
public int print(Graphics g, PageFormat pf, int page) throws PrinterException {
// Convert pixels to cm to lay yor page easy on the paper...
double cmPx = dpi / 2.54;
Graphics2D g2 = (Graphics2D) g;
int totalPages = 2; // calculate the total pages you have...
if (page < totalPages) {
// Draw Page Header
try {
BufferedImage image = ImageIO.read(ClassLoader.getSystemResource(imgFolder + "largeImage.png"));
g2.drawImage(image.getScaledInstance((int) (4.8 * cmPx), -1, BufferedImage.SCALE_SMOOTH), (int) (cmPx),
(int) (cmPx), null);
} catch (IOException e) {
}
// Draw your page as you like...
// End of Page
return PAGE_EXISTS;
} else {
return NO_SUCH_PAGE;
}
}
It sounds like your problem is that you are making the grid lines part of the BufferedImage and it doesn't look good when scaled. Why not use drawLine() to produce the grid after your image has been drawn?
Code for Convert image with dimensions using Java and print the converted image.
Class: ConvertImageWithDimensionsAndPrint.java
package com.test.convert;
import java.awt.Graphics2D;
import java.awt.image.BufferedImage;
import java.io.File;
import javax.imageio.ImageIO;
public class ConvertImageWithDimensionsAndPrint {
private static final int IMAGE_WIDTH = 800;
private static final int IMAGE_HEIGHT = 1000;
public static void main(String[] args) {
try {
String sourceDir = "C:/Images/04-Request-Headers_1.png";
File sourceFile = new File(sourceDir);
String destinationDir = "C:/Images/ConvertedImages/";//Converted images save here
File destinationFile = new File(destinationDir);
if (!destinationFile.exists()) {
destinationFile.mkdir();
}
if (sourceFile.exists()) {
String fileName = sourceFile.getName().replace(".png", "");
BufferedImage bufferedImage = ImageIO.read(sourceFile);
int type = bufferedImage.getType() == 0 ? BufferedImage.TYPE_INT_ARGB : bufferedImage.getType();
BufferedImage resizedImage = new BufferedImage(IMAGE_WIDTH, IMAGE_HEIGHT, type);
Graphics2D graphics2d = resizedImage.createGraphics();
graphics2d.drawImage(bufferedImage, 0, 0, IMAGE_WIDTH, IMAGE_HEIGHT, null);//resize goes here
graphics2d.dispose();
ImageIO.write(resizedImage, "png", new File( destinationDir + fileName +".png" ));
int oldImageWidth = bufferedImage.getWidth();
int oldImageHeight = bufferedImage.getHeight();
System.out.println(sourceFile.getName() +" OldFile with Dimensions: "+ oldImageWidth +"x"+ oldImageHeight);
System.out.println(sourceFile.getName() +" ConvertedFile converted with Dimensions: "+ IMAGE_WIDTH +"x"+ IMAGE_HEIGHT);
//Print the image file
PrintActionListener printActionListener = new PrintActionListener(resizedImage);
printActionListener.run();
} else {
System.err.println(destinationFile.getName() +" File not exists");
}
} catch (Exception e) {
e.printStackTrace();
}
}
}
Reference of PrintActionListener.java
package com.test.convert;
import java.awt.Graphics;
import java.awt.image.BufferedImage;
import java.awt.print.PageFormat;
import java.awt.print.Printable;
import java.awt.print.PrinterException;
import java.awt.print.PrinterJob;
public class PrintActionListener implements Runnable {
private BufferedImage image;
public PrintActionListener(BufferedImage image) {
this.image = image;
}
#Override
public void run() {
PrinterJob printJob = PrinterJob.getPrinterJob();
printJob.setPrintable(new ImagePrintable(printJob, image));
if (printJob.printDialog()) {
try {
printJob.print();
} catch (PrinterException prt) {
prt.printStackTrace();
}
}
}
public class ImagePrintable implements Printable {
private double x, y, width;
private int orientation;
private BufferedImage image;
public ImagePrintable(PrinterJob printJob, BufferedImage image) {
PageFormat pageFormat = printJob.defaultPage();
this.x = pageFormat.getImageableX();
this.y = pageFormat.getImageableY();
this.width = pageFormat.getImageableWidth();
this.orientation = pageFormat.getOrientation();
this.image = image;
}
#Override
public int print(Graphics g, PageFormat pageFormat, int pageIndex) throws PrinterException {
if (pageIndex == 0) {
int pWidth = 0;
int pHeight = 0;
if (orientation == PageFormat.PORTRAIT) {
pWidth = (int) Math.min(width, (double) image.getWidth());
pHeight = pWidth * image.getHeight() / image.getWidth();
} else {
pHeight = (int) Math.min(width, (double) image.getHeight());
pWidth = pHeight * image.getWidth() / image.getHeight();
}
g.drawImage(image, (int) x, (int) y, pWidth, pHeight, null);
return PAGE_EXISTS;
} else {
return NO_SUCH_PAGE;
}
}
}
}
Output:
04-Request-Headers_1.png OldFile with Dimensions: 1224x1584
04-Request-Headers_1.png ConvertedFile converted with Dimensions: 800x1000
After conversion of a image a Print window will be open for printing the converted image. The window displays like below, Select the printer from Name dropdown and Click OK button.
You can use either of the following to improve the quality of the scaling. I believe BiCubic gives better results but is slower than BILINEAR.
g2d.setRenderingHint(RenderingHints.KEY_INTERPOLATION, RenderingHints.VALUE_INTERPOLATION_BICUBIC);
g2d.setRenderingHint(RenderingHints.KEY_INTERPOLATION, RenderingHints.VALUE_INTERPOLATION_BILINEAR);
I would also not use Image.getScaledInstance() as it is very slow. I'm not sure about the printing as I'm struggling with similar issues.
I have two different Panels but i have need to send them in one document in to two pages. first page print at front and the second will print at the back side can anyone please help me i have send one jpanel but how to send second with it. Here is my code
private void printCard() {
PrinterJob printjob = PrinterJob.getPrinterJob();
printjob.setJobName(" CARD ");
Printable printable = new Printable() {
public int print(Graphics pg, PageFormat pf, int pageNum) {
if (pageNum > 0) {
return Printable.NO_SUCH_PAGE;
}
Dimension imageDimension = jLayeredPane2.getSize();
BufferedImage bufferedImage = new BufferedImage(imageDimension.width, imageDimension.height, BufferedImage.TYPE_INT_RGB);
jLayeredPane2.print(bufferedImage.getGraphics());
Graphics2D g2 = (Graphics2D) pg;
g2.translate(pf.getImageableX(), pf.getImageableY());
g2.drawImage(bufferedImage, 0, 0, (int) pf.getWidth(), (int) pf.getHeight(), null);
Dimension backimage=jLayeredPane4.getSize();
BufferedImage bufferedImage1 = new BufferedImage(backimage.width, backimage.height, BufferedImage.TYPE_INT_RGB);
jLayeredPane4.print(bufferedImage1.getGraphics());
g2.drawImage(bufferedImage1, 0, 0, (int) pf.getWidth(), (int) pf.getHeight(), null);
return Printable.PAGE_EXISTS;
}
};
Paper paper = new Paper();
paper.setImageableArea(0, 0, 153, 243);
paper.setSize(243, 153);
PageFormat format = new PageFormat();
format.setPaper(paper);
format.setOrientation(PageFormat.REVERSE_LANDSCAPE);
printjob.setPrintable(printable,format);
try {
printjob.print();
} catch (PrinterException ex) {
System.out.println("Sorry No Image Found" + ex);
}
Thanks
}
Instead of using a java.awt.print.Printable, use java.awt.print.Pageable instead. This will let you specify two pages, and then print in duplex to get front and back. PrinterJob has a setPageable() function as well as a setPrintable(). To make it even easier, use a Book and just add two Printables, one for each page.