Share My Creation PDFBoxWrapper Class Module - show PDF-document in B4J

knutf

Member
Licensed User
PDFBoxWrapper is a Class Module that use PDFBox to view PDF-documents.

The PDFBoxWrapper Class module need a Pane and a layout to show the PDF-document in the Pane. The Pane and the name of the layout must be specified as parameters to the initialize routine of the class.
The layout must contain a ScrollPane named "myScrollPane".
The layout can also optional contain:
  • Spinner for scaleing the page ,named "SpinnerZoom"
  • Spinner turning pages, named "SpinnerPageNumber"
  • Button rotate pages 90degrees clockwise, named ButtonRotate
  • Label for showing loaded PDF-document named "LabelFileName"
PDFBox need to be referred in the Project Attributes Region:
B4X:
#AdditionalJar: pdfbox-app-2.0.14.jar
The file pdfbox-app-2.0.14.jar must be in the additional libraries folder

The PDFBoxWrapper Class module and a working layout for the PDF-viewer can be obtained from the attached Example project.

To use the attached example you have to download the pdfbox-app-2.0.14.jar https://pdfbox.apache.org/download.cgi#20x and place it in the additional libraries folder.

PDFBoxWrapperExampleScreenDump.png
 

Attachments

Last edited:

Tayfur

Well-Known Member
Licensed User
PDFBoxWrapper is a Class Module that use PDFBox to view PDF-documents.

The PDFBoxWrapper Class module need a Pane and a layout to show the PDF-document in the Pane. The Pane and the name of the layout must be specified as parameters to the initialize routine of the class.
The layout must contain a ScrollPane named "myScrollPane".
The layout can also optional contain:
  • Spinner for scaleing the page ,named "SpinnerZoom"
  • Spinner turning pages, named "SpinnerPageNumber"
  • Label for showing loaded PDF-document named "LabelFileName"
PDFBox need to be referred in the Project Attributes Region:
B4X:
#AdditionalJar: pdfbox-app-2.0.14.jar
The file pdfbox-app-2.0.14.jar must be in the additional libraries folder

The PDFBoxWrapper Class module and a working layout for the PDF-viewer can be obtained from the attached Example project.

To use the attached example you have to download the pdfbox-app-2.0.14.jar https://pdfbox.apache.org/download.cgi#20x and place it in the additional libraries folder.

View attachment 77943
Great work;Thank you for sharing.
I didn't see the rotation function.If you add something similar to the following, it will be perfect.
again thank your for sharing

B4X:
Public Sub Rotate(angle As Int)
    Dim pg As JavaObject = thisDoc.RunMethodJO("getPage",Array(0))
    pg.RunMethodJO("setRotation",Array(angle))
    Repaint(1)
End Sub
 

knutf

Member
Licensed User
I didn't see the rotation function.
With help of the sugestion from Tayfur I have updated the Class module with a Rotation function. It is like this:
B4X:
Private Sub ButtonRotate_Click
    If DocIsLoaded And stopRenderingPages = False Then
        Dim page As JavaObject = thisDoc.RunMethodJO("getPage",Array(activePage))
        Dim angle As Int = page.RunMethod("getRotation",Null)
        If angle > 180 Then
            angle = 0
        Else
            angle = angle + 90
        End If
        page.RunMethodJO("setRotation",Array(angle))
        Repaint(myZoom)
    End If
End Sub
I had to do some other changes to get the pages nice placed in the scrollView when rotated.

Further I have changed the horizontal position of the pages to the middel of the scrollView. (This applies when the zoom level is so that the page width is less than the scrollView Viewport width)

The PDFBoxWrapperExample.zip in the first post is uppdated to the latest version.
 

knutf

Member
Licensed User
There was an error in my code that caused the horizontal Scrollbar in the ScrollView not working. (Details in this post) It is now fixed, and The PDFBoxWrapperExample.zip in the first post is uppdated to the latest version.
 

knutf

Member
Licensed User
In the current example it is not possible to fit the PDF document to the ScrollPane width. I have a nearly working example, but struggle finding the ScrollPane "viewport" width. I used this code:
B4X:
Dim spNative As JavaObject = myScrollPane
Dim vpWidth As Double = spNative.RunMethodJO("getViewportBounds",Null).RunMethod("getWidth",Null)
but it does not take into account the size of the vertical scrollbar. Any suggestion?
 

sdleidel

Member
Licensed User
Hi, and this ist not working ?

B4X:
    Dim spNative As JavaObject = myScrollPane
    Dim vpWidth As Double = spNative.RunMethodJO("getViewportBounds",Null).RunMethod("getWidth",Null)
    Dim vpheight As Double = spNative.RunMethodJO("getViewportBounds",Null).RunMethod("getHeight",Null)
    Log (vpWidth)
    Log(vpheight)
 

knutf

Member
Licensed User
I was a bit fast. Contrary to what I wrote, the code in my last post and sdeidel's post take into account the size of the scrollbars.
 

knutf

Member
Licensed User
Thank you, I appreciate that you like the PDF file viewer.

It might be a good idea to include printing in the class.

But I'm sorry I did not have time to look into printing now, as I am a farmer and are busy on the fields in summer and at autumn.
 

Omar Moreno

Member
Licensed User
Hi.
Exactly I do not understand much about Java, between the files that I downloaded
There was an example for java, I extracted a fragment, I pasted it in its code
and with a button I called to print.

Boton_Imprimir.PNG


Thank you.
 

Omar Moreno

Member
Licensed User
Hi.
Someone has happened that in Windows 10 the zoom (image size) of the PDF is not the same as in Windows 7.

In Windows 10, 100% zoom is seen at 50%.

:(
 

Omar Moreno

Member
Licensed User
Sorry, but my query in post # 12 is incorrect. :oops:

I noticed that the library detects the old 22 ”monitor with a value of 30DPI, therefore I had to create a function to hammer at least 96DPI before the library use the values of the DPI.

B4X:
Sub SETDPI(dpi As Float) As Float
    '
    Dim MinDPI As Float = 96
    '
    If dpi < MinDPI Then
        dpi = MinDPI
    End If
    '
    Return dpi
    '
End Sub
 

knutf

Member
Licensed User
Can we load a url instead of a local file path?
I have added this sub:
B4X:
'Open PDF file
'  Stream:      inputstream E.g. from GetInputStream methode on HttpJob object
'  Zoom:      View Zoom of the document (1=100%)
'  DescriptiveName: a text to show in viewer E.g. the URL used to get inputstream from HttpJob
'returns true: no error, false: error opening file
public Sub loadDocumentFromInputStream(Stream As InputStream, Zoom As Float, DescriptiveName As String) As Boolean
- to the pdfBoxWrapper class in the attached PDFBoxWrapperExample versjon 03032020.zip in posting #1

It can be used to open URL with help of e.g. HttpJob class in jOkHttpUtils2 library like this:

B4X:
Sub ButtonOpenURL_Click
    Dim j As HttpJob
    j.Initialize("",Me)
    Dim URL As String = "http://www.africau.edu/images/default/sample.pdf"
    j.Download(URL)
    Wait For (j) JobDone(j As HttpJob)
    If j.Success Then
        PDF.loadDocumentFromInputStream(j.GetInputStream, 0.5,URL)
    End If  
End Sub
The attached example in posting #1 is updated.
 
Last edited:

Markos

Active Member
Licensed User
Thats a great work around and I appreciate the help. But sadly to keep the location secret I must not download but stream to the pdfviewing object using one of the functions that permit. If they can be added to the wrapper from pdfbox
 

knutf

Member
Licensed User
What do you mean? keeping the URL secret?

By the way, I saw you asked about password in this thread. You can open with password like this:

B4X:
public Sub loadDocumentFromInputStream(Stream As InputStream, Zoom As Float, DescriptiveName As String, pwd As String) As Boolean
    Try       
        Dim PDDocument As JavaObject
        PDDocument.InitializeStatic("org.apache.pdfbox.pdmodel.PDDocument")
        thisDoc = PDDocument.RunMethod("load",Array(Stream,pwd))
 

Markos

Active Member
Licensed User
I was premature in my response. The use of HTTPUtils will definitely do the trick as well as the use of the PDDocument.Load function to pass the pwd. I now realise I would NEVER have figured this pdf viewer on my own the amount of steps to render and redimension is staggering. Heare I thought was simple load and display.. Wow!

Thanks my friend this has put me on the road to discover all the features I may ever need for my basic pdf viewer client. Eventually I hope to be able to dynamically enable/disable the ability for the viewer to print and copy using the relevant class or functions if not already inside the PDDocument class.

Cheers
 

moster67

Expert
Licensed User
Splendid project. Great work and thanks for sharing!

Just wondering if there is a way to get the x and y coordinates in the pdf-document where I release the mouse (using the myScrollPane_MouseReleased event).

The idea is opening an existing PDF and then I'd like to drag an image onto the document so I can later embed it and save it as a new pdf. But to do this, I would need to know the coordinates. I guess I would need to take into account also the zoom and maybe also the offset of myScrollPane and the width/height of the actual pdf-document size. The idea is to use this method in PDFBox:
Java:
public void drawImage(PDImageXObject image,
                      float x,
                      float y,
                      float width,
                      float height)
               throws IOException
//Draw an image at the x,y coordinates, with the given size.
Unfortunately, math is not my strongest....

Thanks.
 
Last edited:
Top