JAVA - Printing XPS without File Name/Location Pop-up - java

So im writing a java program for my dad to print out receipts and stuff. My original intention was to print out to his Receipt Printer some info regarding each transaction he made. However, the printer has some trouble printing what i send without clipping it to an extreme point.
My next idea, which worked out quite well, was to save the "receipt" into an XPS file and then print the XPS, which would not clip it and would make everything nice. Now, i can print into an XPS file using Microsoft's XPS Document Writer PrintService. The problem is, when i do it, it always pop's up a box asking for the file name and location to save it into.
Is there anyway to set it so as to not show that pop-up at all?
Current code:
PrinterJob job = PrinterJob.getPrinterJob();
job.setPrintable(this);
try {
job.print();
} catch (PrinterException ex) {
// The job did not successfully complete
}
-
#Override
public int print(Graphics g, PageFormat pf, int page) throws PrinterException {
String temp;
if (page > 0) { /* We have only one page, and 'page' is zero-based */
return NO_SUCH_PAGE;
}
Graphics2D g2d = (Graphics2D)g;
g2d.translate(pf.getImageableX(), pf.getImageableY());
int lineSize=20;
Font testFont=new Font("Lucida Console", 0, 20);
g.setFont(testFont);
g.drawString(" Fatura/Recibo nº"+nmrRec+" ", 5, 20);
return PAGE_EXISTS;
}

You should be able to do it by setting the Destination attribute:
static void print(Printable printable, PrintService service)
throws PrintException,
IOException {
Path outputFile = Files.createTempFile(
Paths.get(System.getProperty("user.home")), null, ".xps");
Doc doc = new SimpleDoc(printable,
DocFlavor.SERVICE_FORMATTED.PRINTABLE, null);
PrintRequestAttributeSet attributes =
new HashPrintRequestAttributeSet();
attributes.add(new Destination(outputFile.toUri()));
DocPrintJob job = service.createPrintJob();
job.print(doc, attributes);
}

So i followed VGR's advice and i got it working. This was my final code, in case anyone runs into the same problem:
Date data = new Date(); //Data
DateFormat dataform = new SimpleDateFormat("dd-MM-yyyy"); //Data
PrintService service=getPrinterService("Microsoft XPS Document Writer");
if(service!=null){
try{
File outputFile = new File(dataform.format(data)+"-Recibo"+nmrRec+".xps");
Doc doc = new SimpleDoc(new myReceipt(), DocFlavor.SERVICE_FORMATTED.PRINTABLE, null);
PrintRequestAttributeSet attributes = new HashPrintRequestAttributeSet();
attributes.add(new Destination(outputFile.toURI()));
DocPrintJob job = service.createPrintJob();
job.print(doc, attributes);
} catch(Exception e){
System.out.println("kaboom"+e);
}
}
else{
System.out.println("XPS Printer not found");
}
And there's my receipt class:
class myReceipt implements Printable{
#Override
public int print(Graphics g, PageFormat pf, int page) throws PrinterException {
String temp;
if (page > 0) { /* We have only one page, and 'page' is zero-based */
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)g;
g2d.translate(pf.getImageableX(), pf.getImageableY());
int lineSize=20;
Font testFont=new Font("Lucida Console", Font.BOLD, 20);
// font name, style (0 for Plain), font size
g.setFont(testFont);
int line=20;
g.drawString(" Fatura/Recibo nº"+nmrRec+" ", 5, line);
return PAGE_EXISTS;
}
}

Related

Java Jpanel print empty page

private void cmdprintActionPerformed(java.awt.event.ActionEvent evt) {
PrinterJob job = PrinterJob.getPrinterJob();
job.setJobName("Outside Processing System");
job.setPrintable (new Printable() {
#Override
public int print(Graphics pg, PageFormat pf, int pageNum){
if (pageNum > 0){
return Printable.NO_SUCH_PAGE;
}
OPSPrintPanel panel = new OPSPrintPanel();
Graphics2D g2 =(Graphics2D)pg;
g2.translate(pf.getImageableX(), pf.getImageableY());
panel.paint(pg);
return Printable.PAGE_EXISTS;
}
});
boolean ok = job.printDialog();
if (ok) {
try {
job.print();
} catch (PrinterException ex) {
JOptionPane.showMessageDialog(null, ex);
}
}
}
I'm trying to print a panel and the codes seems okay but when I click print and view it to pdf its only a blank page. I tried so many codes that can print panel but it doesn't print. Even I reinstall my NetBeans and install an updated jdk it won't work.
Blank page
You didn't dispose object g2 and use try catch block when you print as pdf. First you have to print the image as it is and then try to translate it.
Try this, i hope it would works.
OPSPrintPanel panel = new OPSPrintPanel();
//print the panel to pdf
Document document = new Document();
try {
PdfWriter writer = PdfWriter.getInstance(document, new FileOutputStream("C:\\temp\\test.pdf"));
document.open();
// PdfContentByte is an object containing the user positioned text and
// graphic contents of a page. It knows how to apply the proper font encoding.
PdfContentByte contentByte = writer.getDirectContent();
PdfTemplate template = contentByte.createTemplate(500, 500);
Graphics2D g2 = template.createGraphics(500, 500);
// First print the panel as it is and then try to translate it by removing comments
// g2.translate(pf.getImageableX(), pf.getImageableY());
panel.print(g2);
g2.dispose();
// Adds a template to this content.
contentByte.addTemplate(template, 30, 300);
} catch (Exception e)
{
e.printStackTrace();
}
finally
{
if(document.isOpen())
{
document.close();
}
}

Printing JTable and other textfields in Java

I am developing a desktop app in Java for my project work. I need to print an invoice with sub total and total fields along with tabular data from JTable. I am able to print the table but not in the same page. i.e JTable prints in first page and subtotal, total prints in next page. Is there a way to print both data in the same page. I dont want to use reporting engines. Just use the inbuilt java printing services. Please guide me.
Print Format as I want:
Following figure shows the GUI
And following figure shows the report i am getting till now. Its not in correct format. Please help
Code is as follows
JLabel title = new JLabel();
title.setText("Invoice");
title.setBounds(300, 200, 80, 30);
JTextField subTotal = new JTextField();
subTotal.setText("Sub Total : Rs. " + SubTotal.getText());
subTotal.setBounds(400, 200, 150, 30);
MyPrintable prt = new MyPrintable();
prt.addComponent(title);
prt.addComponent(billTable); //billTable is the JTable
prt.addComponent(subTotal);
prt.printIt();
And below is the My Printable class
class MyPrintable implements Printable
{
private ArrayList<JComponent> items;
public MyPrintable()
{
items = new ArrayList<>();
}
#Override
public int print(Graphics g, PageFormat pf, int page) throws PrinterException
{
if(page > 0) return Printable.NO_SUCH_PAGE;
Graphics2D g2 = (Graphics2D)g;
g2.translate(pf.getImageableX(), pf.getImageableY());
for(JComponent item : items)
{
item.setLayout(null);
// item.setBounds(500, 500, 200, 200);
item.printAll(g);
g2.translate(0, item.getHeight());
}
return Printable.PAGE_EXISTS;
}
public void printIt()
{
PrintRequestAttributeSet attributes = new HashPrintRequestAttributeSet();;
PrinterJob job = PrinterJob.getPrinterJob();
try
{
job.setPrintable(this);
if(job.printDialog(attributes))
job.print(attributes);
}
catch (PrinterException e)
{
JOptionPane.showMessageDialog(null, e);
}
}
public void addComponent(JComponent component) { items.add(component); }
}
If you want to print all your stuff at the coordinates you've set, you either need to create a new panel, lay out all your component to print in this panel, and than print this panel or you need to translate all the components in your print method to the correct coordinates.
the second way will look like
public int print(Graphics g, PageFormat pf, int page) throws PrinterException
{
if(page > 0) return Printable.NO_SUCH_PAGE;
Graphics2D g2 = (Graphics2D)g;
g2.translate(pf.getImageableX(), pf.getImageableY());
for(JComponent item : items)
{
g2.translate(item.getX(), item.getY());
item.printAll(g);
g2.translate(-item.getX(), -item.getY()); // bring all back to default coordinates
}
return Printable.PAGE_EXISTS;
}

Print JFrame in Java Application (Using Netbeans)

I'm trying to print the content of JFrame but, by looking at different tutorials, I still din't have any luck... Currently Parts of code for printing are
public class View_Check extends javax.swing.JFrame implements Printable{
JFrame frameToPrint;
public int print(Graphics g, PageFormat pf, int page) throws
PrinterException {
if (page > 0) {
return NO_SUCH_PAGE;
}
Graphics2D g2d = (Graphics2D) g;
g2d.translate(pf.getImageableX(), pf.getImageableY());
frameToPrint.printAll(g);
return PAGE_EXISTS;
}
and on the click of the button (jButton2)
private void jButton2ActionPerformed(java.awt.event.ActionEvent evt) {
PrinterJob job = PrinterJob.getPrinterJob();
job.setPrintable(this);
boolean ok = job.printDialog();
if (ok) {
try {
job.print();
} catch (PrinterException ex) {
}
}
}
Im Sure something is missing, but by trying to add "JFrame f" to View_Check didn't help... and new (View_Check(f)) either as f couldn't be found ant NetBeans was turning into a christmas tree with red lines
just in case here is a
public View_Check( Model_Customer cust) {
initComponents();
lblinfo1.setVisible(false);
customer = cust;
lblname.setText(customer.GetFName());
lblsurname.setText(customer.GetLName());
lblMake.setText(customer.GetMake());
lblModel.setText(customer.GetModel());
lblEngine.setText(customer.GetEngine());
lblRegistration.setText(customer.GetRegistration());
lblMileage.setText(customer.GetMileage());
String date = new SimpleDateFormat("dd-MM-yyyy").format(new Date());
lblDate.setText(date);
lblPostcode.setText(customer.GetPostcode());
lblNumber.setText(customer.GetNumber());
}
Changed frameToPrint.printAll(g); to this.printAll(g); and worked Like a charm :) Thanks for your help
try making the JFrame frameToPrint static
See if it solves the problem.

SWT UI Thread is not Responding - Printing Error

I have a Print Button in my SWT TitleAreaDialog.
viewPDFButton.addSelectionListener(new SelectionAdapter() {
public void widgetSelected(SelectionEvent e) {
try {
startPdfPrintOperation();
}
catch (Exception e1) {
// TODO Auto-generated catch block
e1.printStackTrace();
}
}
});
I am getting a existing PDF filename and path from a user selection from a table.
I am then wantinf to print the pdf file out to a local printer. The user needs to be allowed to select the local printer of choice.
public void startPdfPrintOperation() throws Exception {
File file = new File(getPDFFileName());
RandomAccessFile raf;
raf = new RandomAccessFile(file, "r");
FileChannel channel = raf.getChannel();
ByteBuffer buf = channel.map(FileChannel.MapMode.READ_ONLY, 0, channel.size());
pdfFile = new PDFFile(buf);
PDFPrintPage pages = new PDFPrintPage(pdfFile);
// Create Print Job
pjob = PrinterJob.getPrinterJob();
pjob.setPrintable(new MyPrintable());
final HashPrintRequestAttributeSet attset;
attset = new HashPrintRequestAttributeSet ();
attset.add (new PageRanges (1, pdfFile.getNumPages ()));
if (pjob.printDialog (attset)) {
try {
pjob.print (attset);
}
catch (PrinterException e) {
e.printStackTrace();
}
}
}
class MyPrintable implements Printable {
public int print (Graphics g, PageFormat format, int index) throws PrinterException {
int pagenum = index+1;
if (pagenum < 1 || pagenum > pdfFile.getNumPages ())
return NO_SUCH_PAGE;
Graphics2D g2d = (Graphics2D) g;
AffineTransform at = g2d.getTransform ();
PDFPage pdfPage = pdfFile.getPage (pagenum);
Dimension dim;
dim = pdfPage.getUnstretchedSize ((int) format.getImageableWidth (),
(int) format.getImageableHeight (),
pdfPage.getBBox ());
Rectangle bounds = new Rectangle ((int) format.getImageableX (),
(int) format.getImageableY (),
dim.width,
dim.height);
PDFRenderer rend = new PDFRenderer (pdfPage, (Graphics2D) g, bounds, null, null);
try
{
pdfPage.waitForFinish ();
rend.run ();
}
catch (InterruptedException ie)
{
MessageDialog.openError(null, "PDF Error Message", "Needs");
}
g2d.setTransform (at);
g2d.draw (new Rectangle2D.Double (format.getImageableX (),
format.getImageableY (),
format.getImageableWidth (),
format.getImageableHeight ()));
return PAGE_EXISTS;
}
}
I am getting the above error from line 315
if (pjob.printDialog (attset)) {
The printer dialog opens the entire application is frozen and goes unresponsive. Then in about 30 secs, I get the above error.
I have tried to use Display.getDefault().asyncExec(new Runnable() ) in multiple spots but that did not help.
Could it be because the base dialog is SWT and the printer dialog is AWT?
Since you didn't define "in multiple spots", I would suggest you refactor the print job in its own class, extends Thread and implement starting the print job in the run method.
I'm not familiar with all classes in above code, you can try simply starting this thread and it will run in parallel with the SWT thread. Try avoiding shared ressources, this may help resolving your deadlock. If you want to have a UI response from this thread, you can wrap e.g. the SWT messagebox ("Printing done!") in a call to Display.getDefault().asyncExec(new Runnable() { ... }.
Furthermore, please test if the printing code without UI code produces the same exception. If it does, the environment may be misconfigured.

How to use embedded Fonts to call the Graphics2D.drawString(...) with iText (DefaultFontMapper?)

To generate a valid PDF/X document, it's mandatory to have all fonts embedded. Somehow it's not possible for me to use those fonts in an Graphics2D context.
This Unittests shows the problem (commented lines are some tests i made):
import java.awt.Font;
import java.awt.Graphics2D;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.PrintStream;
import java.util.Map.Entry;
import org.junit.Test;
import com.itextpdf.awt.DefaultFontMapper;
import com.itextpdf.awt.DefaultFontMapper.BaseFontParameters;
import com.itextpdf.awt.PdfGraphics2D;
import com.itextpdf.text.Document;
import com.itextpdf.text.DocumentException;
import com.itextpdf.text.Rectangle;
import com.itextpdf.text.pdf.PdfWriter;
public class TestFont
{
#Test
public void shouldBeAbleToAddFountsAndDrawOnCanvas() throws FileNotFoundException, DocumentException
{
final DefaultFontMapper mapper = new DefaultFontMapper();
mapper.insertDirectory(".");
final PrintStream out2 = new PrintStream(System.out);
for (final Entry<String, BaseFontParameters> entry : mapper.getMapper().entrySet())
{
out2.println(String.format("%s: %s", entry.getKey(), entry.getValue().fontName));
}
out2.flush();
final float width = 150;
final float height = 150;
final Document document = new Document(new Rectangle(width, height));
final PdfWriter writer = PdfWriter.getInstance(document, new FileOutputStream("fonts.pdf"));
writer.setPDFXConformance(PdfWriter.PDFX32002);
document.open();
final Graphics2D g2d = new PdfGraphics2D(writer.getDirectContent(), width, height, mapper);
g2d.setFont(new Font("Comicate", Font.PLAIN, 12));
g2d.drawString("Hello world", 5, 24);
g2d.dispose();
document.close();
}
}
It will throw an PdfXConformanceException with message: "All the fonts must be embedded. This one isn't: Helvetica.
I already browsed though the PdfGraphics2D class to check the setFont() implementation and found out, that a FontMapper will be used. I already added this to the Unittest above.
public void setFont(Font f) {
if (f == null)
return;
if (onlyShapes) {
font = f;
return;
}
if (f == font)
return;
font = f;
fontSize = f.getSize2D();
baseFont = getCachedBaseFont(f);
}
private BaseFont getCachedBaseFont(Font f) {
synchronized (baseFonts) {
BaseFont bf = (BaseFont)baseFonts.get(f.getFontName());
if (bf == null) {
bf = fontMapper.awtToPdf(f);
baseFonts.put(f.getFontName(), bf);
}
return bf;
}
}
The Unittest is based on this example from the iText in Action book. Here are some other examples about the FontMapper.
To run the Unittest you need this dependency:
<dependency>
<groupId>com.itextpdf</groupId>
<artifactId>itextpdf</artifactId>
<version>5.3.2</version>
</dependency>
The Custom Font (located in ".") you find here.
The Console Output shows me this (to identify the fontName):
Comicate: ./COMICATE.TTF
I am not sure of the exact way to correct the error in your code, but there are easy workarounds:
Workaround 1) Create a BufferedImage to do all your graphics painting to. Then you can use all normal java.awt.Graphics functions like drawString and setColor regardless of iText, and when you are done just draw the image to a PDF. WARNING you do loose quality of text when zooming, but here is an example:
//create doccument and writer
Rectangle pagesize = new Rectangle(200, 100);
Document document= new Document(pagesize);
PdfWriter writer = PdfWriter.getInstance(document, new FileOutputStream("C:\\sample.pdf"));
BufferedImage bf = new BufferedImage(BorderWidth, BorderHeight, BorderWidth);
//Do all graphics code here, draw strings and images etc
//Some code to set font (java.awt.Font)
//Some code to draw string
//Some code to draw image?
//Convert BufferedImage to Image
Image img = (Image)bf;
//draw image to PDF using writer
writer.getDirectContentUnder().addImage(img);
Workaround 2) This uses iText features to draw strings, without needing to create any graphics objects, the font is taken care of by using a BaseFont as follows:
//create doccument and writer
Rectangle pagesize = new Rectangle(200, 100);
Document document= new Document(pagesize);
PdfWriter writer = PdfWriter.getInstance(document, new FileOutputStream("C:\\sample.pdf"));
document.open();
//This sample uses the "GOTHIC.TTF" font file located in the "Template" package
BaseFont bf = BaseFont.createFont(GUI.class.getClass().getResource("/Template/GOTHIC.TTF") + "", BaseFont.WINANSI, BaseFont.EMBEDDED);
//set font type, size and color
Font font = new Font(bf, 13.5f);
PdfContentByte canvas = writer.getDirectContent();
canvas.beginText();
canvas.setFontAndSize(bf, 10);
//Method Usage: showTextAligned(Align, String, x, y, rotation);
canvas.showTextAligned(Element.ALIGN_TOP, "My Text Here", 75, 40, 0);
canvas.endText();
document.close();
I know this does not give the answer you were looking for, however if you are just drawing a small amount of text then workaround 2 works great, I have used something similar to workaround 2 before. If this does not help then I am sure Bruno will have the answer.
By defining new BaseFont(s) and implementing the interface of FontMapper() >>> public BaseFont awtToPdf(java.awt.Font font). This will apply the awt.font(s) as embedded into the pdf.
In the example below I "print" g2D (including "drawString" method), drawn in outer class. The result is exported vector pdf with embedded "ArialMT" and "Arial-BoldMT" fonts only.
preview img
PdfWriter pdfWriter = null;
try {
pdfWriter = PdfWriter.getInstance(document, new FileOutputStream(file));
document.open();
BaseFont fontRegular = BaseFont.createFont("C:\\Windows\\Fonts\\arial_0.ttf", "Cp1251", BaseFont.EMBEDDED);
BaseFont fontBold = BaseFont.createFont("C:\\Windows\\Fonts\\arialbd_0.ttf", "Cp1251", BaseFont.EMBEDDED);
FontMapper fontMapper = new FontMapper() {
#Override
public java.awt.Font pdfToAwt(BaseFont arg0, int arg1) {
// TODO Auto-generated method stub
return null;
}
#Override
public BaseFont awtToPdf(java.awt.Font font) {
if (font.equals(Fonts.getFontRegular10()) || font.equals(Fonts.getFontRegular12())){
return fontRegular;
}
else {
return fontBold;
}
}
};
PdfContentByte cb = pdfWriter.getDirectContent();
PdfTemplate template = cb.createTemplate(MainFrame.getFRAME_WIDTH(), MainFrame.getFRAME_HEIGHT());
Graphics2D g2D = new PdfGraphics2D(template, MainFrame.getFRAME_WIDTH(), MainFrame.getFRAME_HEIGHT(), fontMapper);
MainFrame.getPanel().print(g2D);
g2D.dispose();
cb.addTemplate(template, 0, 0);
}
catch (Exception e1) {
e1.printStackTrace();
}
finally {
document.close();
}

Categories

Resources