In a program I had the need to create and display a PDF file in a Swing JPanel. To my horror there are not may tools/API’s out there which would accommodate my needs: just the display of a PDF file in a JPanel without all kind of toolbars,buttons or other tools in it.
What I was looking for is this:
- Non-Commercial API.
- With full control of the JPanel as a normal Swing component.
- No extras like creating,printing, scaling, fonts, saving, etc..
To create the PDF I used iText, but to display the created PDF I had to find something else. And luckily: I found it. It is a little older (but must have ripened) API, but it does the job I need more then the other solutions Google offered. And for free that is, I’m just a poor programmer.
Ladies and gentlemen, I present to you: PDF-Renderer.
This is the one that fulfilled my needs. For that specific project so to say ;-).
Nice, but….? there is always a butt….It must be..
Indeed. There was a but. An annoying “but” even…So “but”, it comes close to “bug”. It took me a while to find out what it was, besides the expired signing of the jar file, which was easily solved by recreating the jar file with my signature so I could deploy my application as a Jar file. (Tjeess..do I digress easily or what? 😉 ). The issue I found was when running the application on Linux, everything was fine. So were the tests. However the problem arose when testing on Windows. There it turned out that the file, when it was in 1st time displayed in the JPanel, was being locked by the OS, or at least by the JVM, since the file is unlocked when the JVM session is ended. At first I didn’t noticed, but when I would like to delete the file (as of housekeeping) and/or re-use the file name it threw an exception to me: the file could not be read..Mind: this occurred only on the Windows platform!
Sidenote: I hard-coded the file name since it is only a temporary file which I remove when the application is done. So it is much easier to debug and better to hardcode en reuse the file than create all kind of temporary clutter files on the client PC..but that is just my opinion..
Alright, alright..It is an issue..But you’ve solved this, right?
Well, yes and no. I’ve googled and found the answer hidden away in an archived post somewhere. Since I had to look a little harder than usual (must have been the stress of the deadline weighing me down 😉 ) I found it worth the trouble to write down the solution I’;ve found concerning this issue. So yes, there is a solution, and no, I do not claim the credit..I’m just putting it back out there again.. 😉
Without further a due, here is the code to compare..
First the code as we have found in the examples:
pdfFile = new File(tempDir+"/createPDF.pdf"); raf = new RandomAccessFile(pdfFile, "r"); byte b = new byte[(int)raf.length()]; ByteBuffer buf = ByteBuffer.wrap(b); PDFFile pdffile = new PDFFile(buf);
The code above is a snippet from a standard JFrame where I place the JPanel in. The crux however is in the RandomAccessFile. We need the whole PDF loaded into the buffer, then it will be released by the JVM. So we change the code a bit, and this time with a more detail. To try this out, just create a JFrame and place the JPanel in there as usual.
And this is the code which actually works:
pdfFile = new File("/tmp/createPDF.pdf"); RandomAccessFile raf = new RandomAccessFile(pdfFile, "r"); byte b = new byte[(int)raf.length()]; raf.readFully(b); // buf = ByteBuffer.wrap(b); pdfToView = new PDFFile(buf); page = pdfToView.getPage(0); pdfPanel.setSize((int)page.getBBox().getWidth(), (int)page.getBBox().getHeight()); pdfPanel.setBackground(Color.GRAY); pdfPanel.setLayout(new MigLayout("fill","grow,fill","")); JPanel pnlPDFHolder= new JPanel(); pnlPDFHolder.setBorder(BorderFactory.createLoweredBevelBorder()); pnlPDFHolder.setBackground(Color.GRAY); pdfPanel.showPage(page); pnlPDFHolder.setLayout(new MigLayout( "fill", "grow,fill", "")); pnlPDFHolder.add(pdfPanel); pdfFile.deleteOnExit();
Sidenote: As you may have noticed, I do not use the standard layout manager. I'm using Eclipse as my IDE to code, and like to use Miglayout as my layout manager. I think it is the best layout manager to use without a visual design tool.