The JPedal Viewer is the best Java PDF Viewer because it so easily customizable.
JPedal provides access to the underlying Swing components which allows you to extend it with custom behaviour and additional UI elements.
In this tutorial, I am going to show you how to add a chat window to the Viewer which allows users to ask a large language model questions about the document they have open.
Download a JPedal trial jar to try this yourself!
First we need to make a chat window that can be embedded in the Viewer. I won’t write the complete source code here because it is a couple hundred lines long, but you can find the full class here.
The important part is that we need some kind of callback to receive the messages the user sends.
public class ChatPanel extends JPanel {
private transient Consumer sendHandler;
…
private void sendCurrentText() {
addMessage(text, true);
if (sendHandler != null) {
try {
sendHandler.accept(text);
} catch (Exception ex) {
LogWriter.warning(ex, "Exception sending message: " + ex.getMessage());
}
}
}
}
Now we can add this to JPedal by getting a handle to the JTabbedPane which represents the side bar in the Viewer.
final Viewer viewer = new Viewer();
viewer.setupViewer();
final ChatPanel chatPanel = new ChatPanel();
final JTabbedPane sideTabBar = viewer.getSwingGUI().getSideTabBar();
sideTabBar.addTab("AI", new ImageIcon(), chatPanel);
The chat window works, but it does not do anything yet so we need to add the AI capabilities.
Again, I won’t give the full code here (you can see it on our GitHub), but essentially we can use the callback from the chat window and pass that to the AI, along with the context from the PDF.
In this example, I show how to provide the text extracted from the document, and also an image of the page which some AIs may be able to use for OCR.
chatPanel.setSendHandler(userMessage -> new Thread(() -> {
try {
final PdfDecoderInt pdfDecoder = viewer.getPdfDecoder();
final int pageNum = viewer.getSwingGUI().getValues().getCurrentPage();
// Get the text from the current page
final PdfPageData pageData = pdfDecoder.getPdfPageData();
final String pageText = pdfDecoder.getGroupingObject().extractTextInRectangle(
pageData.getMediaBoxX(pageNum),
pageData.getMediaBoxY(pageNum),
pageData.getMediaBoxWidth(pageNum),
pageData.getMediaBoxHeight(pageNum),
pageNum,
false, false);
// Get the image of the current page
final BufferedImage pageImage = pdfDecoder.getPageAsImage(pageNum);
final Optional response = gpt.ask(userMessage, pageText, pageImage);
chatPanel.addMessage(response.orElse(""), false);
} catch (Exception ex) {
chatPanel.addMessage("Error: " + ex.getMessage(), false);
}
}).start());
Here is the final result!
Resources
You can find all the source code on our GitHub page.
Find out what else you can do with JPedal.
We can help you better understand the PDF format as developers who have been working with the format for more than 2 decades!
