B4J Library B4j Print JavaFX8

Here is a B4j library written in B4j to access the full Printer modules provided with JavaFX8. Full source code is available.

At it's simplest, you can print a node using:
B4X:
    Dim P As Printer = Printer_Static.GetDefaultPrinter
    Dim PJ As PrinterJob = PrinterJob_Static.CreatePrinterJob2(P)
    PJ.PrintPage(lblTest)
    PJ.EndJob

Or with dialogs:

B4X:
    Dim PJ As PrinterJob = PrinterJob_Static.CreatePrinterJob
    PJ.ShowPageSetupDialog(Null)
    PJ.ShowPrintDialog(Null)
    PJ.PrintPage(MainForm.RootPane)
    PJ.EndJob

Code to scale a view to print on a single page.
Scale output:
Sub ScaleOutput(P As Printer,N As Node) As Node
    Dim PL As PageLayout = P.GetDefaultPageLayout
    Dim ScaleX,ScaleY As Double
    Dim NJO As JavaObject = N
    Dim JO As JavaObject = N
    ScaleX = PL.GetPrintableWidth / JO.RunMethodJO("getBoundsInParent",Null).RunMethod("getWidth",Null)
    ScaleY = PL.GetPrintableHeight / JO.RunMethodJO("getBoundsInParent",Null).RunMethod("getHeight",Null)
    Dim SJO As JavaObject
    SJO.InitializeNewInstance("javafx.scene.transform.Scale",Array(ScaleX,ScaleY))
    NJO.RunMethodJO("getTransforms",Null).RunMethod("add",Array(SJO))
    Return NJO
End Sub

Usage:
    'Print with dialogs
    Dim PJ As PrinterJob = PrinterJob_Static.CreatePrinterJob
    If PJ.ShowPageSetupDialog(Null) Then
        If PJ.ShowPrintDialog(Null) Then
'            PJ.PrintPage(MainForm.RootPane)
            PJ.PrintPage(ScaleOutput(PJ.GetPrinter,MainForm.RootPane))
            PJ.EndJob
        Else
            PJ.CancelJob
        End If
    Else
        PJ.CancelJob
    End If

Reset node size after scaling:
'where N would be MainForm.Rootpane in the above example
N.As(JavaObject).Runmethod("getTransforms",Null).as(List).Clear

Depends on: JavaFX8, JavaObject

Documentation (apart from that in the library) is available here: http://docs.oracle.com/javase/8/javafx/api/index.html?javafx/print/Printer.html
Click on javafx.print in the All Classes Packages frame to see all the relevant classes.

I've ignored Enums where strings are acceptable for simplicity's sake.

V0.6 fix improperly formed XMLmessage displayed in IDE help (post #6)
V0.7 added #RaisesSynchronousEvents to PrinterJob module as described here : https://www.b4x.com/android/forum/t...ble-getting-jfx8print-dialogs-to-work.133964/
V 0.8 Released as a B4xLib Enums now return string values instead of ENum objects.

Full code is in Printer.zip if you just want to look at the project without unzipping the B4xlib
Enjoy
 

Attachments

  • jFX8Print.b4xlib
    11.1 KB · Views: 676
  • Printer.zip
    14.2 KB · Views: 383
Last edited:

stevel05

Expert
Licensed User
Longtime User
Updated to fix a small bug. Probably more of these to come.:)
 

Swissmade

Well-Known Member
Licensed User
Longtime User
Very nice and useful thanks.;);)
 

Swissmade

Well-Known Member
Licensed User
Longtime User
Hi,
I'm using this library and it is working very well but I can not see how I set the Page-layout.
I like to have the layout like
Top 0
Left 0
I need this for a Bar-code Printer.
Maybe I don't see it :(any help from somebody.
Many thanks for help.
 

stevel05

Expert
Licensed User
Longtime User
Printer.CreatePageLayout allows setting Margins as long as the selected printer supports them. If it's a requirement of the printer, the perhaps Printer.GetDefaultPageLayout will already have them set.
 

Swissmade

Well-Known Member
Licensed User
Longtime User
Printer.CreatePageLayout
Using this I get a error that the XML was improperly formatted. Please escape it if necessary
I using the test program you made. Without Library.
 

Swissmade

Well-Known Member
Licensed User
Longtime User
A small sample can be nice.
Many thanks for helping me out here.
 

stevel05

Expert
Licensed User
Longtime User
I've updated the files, please download and try again the improperly formatted XML issue should be fixed. I don't have a printer that can support 0 margins, you would also have to choose the appropriate page size, so can't test code to post. It shouldn't be difficult though.

You can test it using the dialogs to see if it works properly.

If you still get problems, let me know.
 

Swissmade

Well-Known Member
Licensed User
Longtime User
I don't have a printer that can support 0 margins,
Marges don't have to be 0.
I only need to know how to give the Pagelayout to the Printer.
I think I do something wrong.
See some code.
B4X:
    Dim PP As Paper
    PP.Initialize()
    Dim PC As Printer
    PC.Initialize()
    Dim PL As PageLayout
    PL.Initialize()
    PP = Paper_static.A6
    PC = Printer_Static.GetDefaultPrinter

PL = PC.CreatePageLayout2(PP, PageOrientation_Static.PORTRAIT, "HARDWARE_MINIMUM")

    Dim PJ As PrinterJob
    'Print with dialogs
    PJ = PrinterJob_Static.CreatePrinterJob2(PC) 'CreatePrinterJob
 

stevel05

Expert
Licensed User
Longtime User
How are you then printing the page?
 

Swissmade

Well-Known Member
Licensed User
Longtime User
How are you then printing the page?
I think I have seen it:)
B4X:
    PJ.PrintPage(MainForm.RootPane)
    PJ.EndJob
'Must be
    PJ.PrintPage2(PL, MainForm.RootPane)
    PJ.EndJob
Let you know if it is working.
Marge must be at least 1 and not zero.
 

Swissmade

Well-Known Member
Licensed User
Longtime User
Small Questions.
How can I create my one Paper size??
I test this with Foxit Reader to create a pdf.
 

stevel05

Expert
Licensed User
Longtime User
The Constants in Paper_static are declared for convenience, you can get all of the papers that the printer says it supports using this code:

B4X:
    Dim P As Printer = Printer_Static.GetDefaultPrinter
   
    For Each PP As JavaObject In P.GetPrinterAttributes.GetSupportedPapers
        Dim PPP As Paper
        PPP.SetObject(PP)
        Log(PPP.ToString)
    Next

There may be a paper that you want listed.

There is a similar question on stack overflow here: http://stackoverflow.com/questions/19796091/javafx-print-custom-paper-size which suggests it's possible. I have to go out now, but if you don't have any luck converting it, I'll take a look when I get back. I'm not sure it will work, but may be worth a look if you need it.
 

Swissmade

Well-Known Member
Licensed User
Longtime User
Solution to Set your one Papersize
B4X:
 Dim r As Reflector
  r.Target = PP
  Log(r.GetField("width"))
    r.SetField2("width", 55)
    r.SetField2("height", 64)
    PPP.SetObject(PP)
Result a small Paper layout and Size. The Printer I test is an pdf Printer Foxit.
Maybe a option to put this in your library.
This only works when you are using.
B4X:
PC.GetPrinterAttributes.GetSupportedPapers 'Return List
'And Not with
PC.GetPrinterAttributes.GetDefaultPaper 'Return Paper
Solution Get the first Printer from SupportedPapers and change the values. Like
Width, Height and Name
 
Last edited:

Mark Zraik

Member
Licensed User
Longtime User
Hi Steve05,

Am I wrong in assuming (Hate to do that) that we should open your project in B4J, then compile it to a library and then use it in or own project?

I realize the answer might be obvious, but I like to clarify first. I'm gonna try exactly that, and hopefully I have guessed right:)
Otherwise, it's a lot of modules to include...

The project works pretty cool!

Mark

EDIT: I re-read the first post! Sorry, I forgot you had the Library already compiled!!!

I'll hopefully (No guarantees)in the future, will pay better attention.
 
Last edited:

DieterR

Member
Licensed User
Longtime User
Has anyone an idea what the reason for this runtime error is? "java.lang.ClassNotFoundException: javafx$print$Printer"
It occures always, regardless if I use the lib in my program or when I try any of the code samples of this thread.

Many thanks for any help.
DieterR
 
Top