B4J Library [B4j] Javax print wrapper for UI and non-UI apps.

This is a wrap of the Javax print API. It is more complex to use than the Javafx print API but does have a few benefits such as being usable in non-UI apps and access to java Swing printable interface which makes it easy to print the content of swing nodes. The main example app contains an example of printing text from a swing jTextArea, which is automatically split into pages. There is a separate example of printing a pdf from a file which contains a minimal wrapper for Apache pdfbox and also utilises a swing node.

This is a large library and contains a fair amount of wrapper code that I hope will make it a little easier to use, but there is so much in it that it is not possible to make it simple. So if you want to try it, please read up on how it is supposed to work. I don't have the time to write a full tutorial, that would probably take a good few days on its own, but the wrapper is here if you want to try it out. As the library is so large, I cannot guarantee that everything will work first time, I have tested most of it while writing the example apps, so probably about 80% of it has been tested. Please report any errors that you find and I will try to fix them as quickly as possible.

You can take the code from the examples if it provides a function you want to use.

A big benefit of writing this wrapper was that it made me rethink the use of the Javafx print library, which is where the recent Textflow example came from. Also when digging and researching I found that the Javafx print library is already a wrapper for the javax print API, so using javax print classes in a Javafx app shouldn't use any more resources than using the Javafx print library.

The main print functions run on a thread, so cannot be used in debug mode and will raise an error if you try to do so, but there are non threaded versions if you really want to use it in debug mode and the example apps demonstrate how to do this. The printer dialogs are modal, so they will hold the UI thread and make it unresponsive. The use of threading can't do anything about this, but if your print takes a long time to finish, it will return control of the UI as soon as the last dialog is displayed, rather than holding it until the print has actually finished.

You will notice in one of the examples that a different print dialog is displayed, this is the 'Common' print dialog. I have not been able to force the display of the 'native' dialog (on windows at least) even though there is an option to do so.

As usual, I have only tested on a Windows PC, if you use it on Mac or Linux, let me know how it goes.

There are 2 example apps in this post, one is a UI app that uses Pane and buttons to provide selection, the other is a non-UI app, which has a minimal swing UI, just to make it easier to navigate. This is most definitely not required to use the library. I may post some more examples if I come across something interesting. The actual class code contained in the example apps are identical (I hope), just the methods of accessing them differ slightly from UI to non-UI.

Example apps additional dependencies:
  • none

Setup

  • Download the b4xlib file and copy it to your B4x additional libraries.
  • Download and unzip one or both of the example projects,
  • Download the zipped image files from my Googledrive and unzip them into the files folder of the project (both projects use the same files so copy them to both if you download both projects). Don't forget to sync the files folder once copied.

The example projects print to the system default printer so make sure that a virtual PDF printer is selected to save paper. Or see the commented code in the sub PrintImagePrinterJobDo to set the attributes to print to a specific printer.
 

Attachments

  • JavaxPrintUI - Text.zip
    17.5 KB · Views: 261
  • JavaxPrintNonUI - Text.zip
    16.8 KB · Views: 264
  • JavaxPrint-b4xlib.b4xlib
    62.8 KB · Views: 263
Last edited:

stevel05

Expert
Licensed User
Longtime User
Quick Overview

The Javax print api uses attribute sets to help selecting the correct printer, print job and output options for a print run these are:

  • PrintServiceAttributeSet
    • Used to select a printer based on its capabilities.
  • DocAttributeSet
    • Used to define attributes for a DocPrintJob.
  • PrintJobAttributeSet
    • Used to define attributes for a PrinterJob.
  • PrintRequestAttributeSet
    • Used to select attributes for the print output.

Not all attribute sets support all of the available Attributes, an error will be thrown if you add an unsupported attribute to a set, you can see which attributes are supported in the IDE when you add an attribute to a set.

There are two types of Print Job, the DocPrintJob and the PrinterJob.

The DocPrintJob is used to print an existing document (see the PrintImage_DocPrintJob example), you need to specify the source for the data i.e. Byte_Array, Input_Stream etc and what type of data the job should expect. I.e. Jpg, URL etc collectively known as a Flavor.

The PrinterJob is used when you are providing the formatted data to print either from a printable swing node, as is the case in the Print_TextArea example, or drawn as graphics as with most of the examples.

There are many examples of its use available on the internet along with issues you are likely to encounter. Some things don’t work the same on all platforms. The library should be similar enough to be able to port any examples you find.

If you can get the result you want using the Javafx print library, you should use that. It is much simpler to work with. This is provided for those cases where it is not available (non-UI apps) or you want to do something specific that the Javafx print library doesn’t do, or doesn’t do well.
 
Last edited:

stevel05

Expert
Licensed User
Longtime User
This is an example of printing a PDF from a file file using the Javax Print library and Apache PDFBox. The project contains a minimal wrapper for pdfbox for which you need to download the PDFBox standalone jar 2.0.27 file from their site here and copy to your B4j Additional libraries folder.

This example uses Javax print API's ability to print from a swing node to print the PDF that is first loaded into a swing PDFDocument object.

There is a ui and non-ui example.
 

Attachments

  • JavaxPrintPDF.zip
    359.9 KB · Views: 229
  • JavaxPrintPDF-NonUI.zip
    359.3 KB · Views: 224
Last edited:

behnam_tr

Active Member
Licensed User
Longtime User
thanks @stevel05

I am getting this error, can I ignore it??
What is the use of these two lines of code??

I'm using java 8

B4X:
Unrecognized option: --add-opens
Error: Could not create the Java Virtual Machine.
Error: A fatal exception has occurred. Program will exit.

And one more question
Can I print the HTML table??
 

stevel05

Expert
Licensed User
Longtime User
Yes, you need to comment out the add-opens using Java 8.

Is this a non-ui app?

I don't believe that the Javax print library will render html. You will need to find a way get the html rendered. I believe that one of the swing nodes will do it, but apparently they may not be perfect. If it does render, you can get the pageable from the node and use that as the printable.
 
Last edited:

syerif

Active Member
Licensed User
Longtime User
hi @stevel05,

it is possible to change printer, because i have two printer in my pc, and i want change the printer base on document name. if i print doc1 it will be print on printer1 and if doc2 it will print on printer2.
 

stevel05

Expert
Licensed User
Longtime User
Just create a new printer object and select the printer you want.
 
Top