I cannot seem to figure out how to view a PDF Page using PDFBox and its PDFPagePanel component.
So it seems that using PDFBox my options are to either create a List of PDPage objects or PDDocument objects, I've gone with the PDPage list (as opposed to using Splitter() for PDDocument objects)
The following code creates a PDPage object named testPage
File PDF_Path = new File("C:\\PDF.PDF");
PDDocument inputPDF = PDDocument.load(PDF_Path);
List<PDPage> allPages = inputPDF.getDocumentCatalog().getAllPages();
inputPDF.close();
PDPage testPage = (PDPage)allPages.get(0);
From here I would like to create a PDFPagePanel and use its setPage() method to place the PDPage into the component. From here I want to add the component to a JFrame. When I do this I just see whitespace.
JFrame testFrame = new JFrame();
testFrame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
PDFPagePanel pdfPanel = new PDFPagePanel();
pdfPanel.setPage(testPage);
testFrame.add(pdfPanel);
testFrame.setBounds(40, 40, pdfPanel.getWidth(), pdfPanel.getHeight());
testFrame.setVisible(true);
I found one 'solution' which suggest converting the PDF to an image and displaying it as a buffered image, and while this works it doesn't seem like the correct way to do this. Am I incorrect in trying to use PDFBox's PDFPagePanel as a means to displaying a PDF?
When I comment out the inputPDF.close call, it works okay. What if you move the close to after you are finished displaying the pdf? Something like this...
testFrame.setDefaultCloseOperation(JFrame.DO_NOTHING_ON_CLOSE);
testFrame.addWindowListener(new WindowAdapter() {
#Override
public void windowClosing(WindowEvent e) {
try {
inputPDF.close();
testFrame.setVisible(false);
} catch (IOException e1) {
// TODO: implement error handling
e1.printStackTrace();
}
}
});
For the record, I also implemented a PDFBox viewer as a BufferedImage wrapped in a Component wrapped in a JPanel. Then, I was able to customize the panel with additional buttons to change pages, change documents, "zoom" or resize the image, etc.
Related
I am using OpenViewerFX (JPedal) to display PDF files in a JavaFX application. Some files are displayed well, others only show not printable characters (in documents created by myself and also documents from other people).
See for example this one:
This is my code:
private final PdfDecoderFX pdf = new PdfDecoderFX();
private Group group;
#Override
public void start(Stage stage) {
BorderPane bp = new BorderPane();
Scene scene = new Scene(bp, 400, 400);
stage.setScene(scene);
stage.show();
group = new Group();
group.getChildren().add(pdf);
bp.setCenter(group);
Platform.runLater(() -> {
try {
pdf.openPdfFile("D:\\Dokument1.pdf");
decodePage();
} catch (PdfException e) {
e.printStackTrace();
System.out.println(e.getMessage());
}
});
}
private void decodePage() {
try {
pdf.setPageParameters(2.0f, 0);
pdf.decodePage(1);
pdf.waitForDecodingToFinish();
} catch (final Exception e) {
e.printStackTrace();
System.out.println(e.getMessage());
}
}
The PDF file was created from a Word document with Adobe PDF printer. I used the standard font and only standard characters. I tested several settings when creating the file, including
Compatibility "PDF 1.3" to "PDF 1.7"
Enable/Disable web optimization
Include all fonts
Include Open-Type fonts
but always the same result.
What could I be doing wrong?
Seems like a font issue to me. The debugging output helped me in the past - at least I saw some error message in there. I'm not quite sure what the correct option was but try the following:
Did you try to enable jpedal logging?
//debug code
LogWriter.log_name="/yourpath/log.txt";
LogWriter.setupLogFile(true,0,"1.0","v",false);
What does the org.jpedal.PdfDecoder.getPageDecodeStatus(int type)state where type is any value Defined in org.jpedal.parser.DecodeStatus
We use a patched version of the ViewerFX - can you try that one?
Are you sure you specified the correct path to the fonts?
To add a whole directory of fonts via JVM flag set the JVM flag -Dorg.jpedal.fontdirs=dirList where dirList is a comma-separated list of possible directories.
What is your OS? Windows or Linx?
Did you also try the -Dorg.jpedal.inclusiveLogFilter= "memory,error"JVM option?
Try to set -Dverbose=true
Call GUI.debugFX=true; see here.
In my vaadin application I have a Table with an additional column containing a print Button. The Button calls the following util method to create a pdf and open it in a new window (ui parameter is the button):
public static void printPDF(Offer offer, AbstractComponent ui) throws IOException, DocumentException, TemplateException {
// ... create PDF
FileResource resource = new FileResource(pdfFile);
BrowserWindowOpener opener = new BrowserWindowOpener(resource);
opener.setFeatures("");
opener.extend(ui);
}
Now clicking the button the first time does not work. Clicking it the second time works. Clicking it the third time, opens two windows. This increases on every further click.
I also want to open the pdf using the context menu e.g.
table.addActionHandler(new Handler()...
There I don't even have a button to extend. I would prefer to, not use the .extend() part and just open a new window. How can I do that?
EDIT: This blocks the button from opening mulitple instances, still not a nice solution and the first click does not work.
Collection<Extension> extensions = ui.getExtensions();
for (Extension e : extensions) {
if (e instanceof BrowserWindowOpener) {
((BrowserWindowOpener) e).setResource(resource);
return;
}
}
I guess I would need to create a BrowserWindowOpener for every print Button in my Table.
Not a very clean solution, the table may contain lots of rows which would create a lot of BrowserWindowOpener instances which will never be used. The context menu problem would not be solved as well.
EDIT2: This is the other solution I tried:
ResourceReference rr = ResourceReference.create(resource, ui, "print");
Page.getCurrent().open(rr.getURL(), "blank_");
Here I get the following error:
Button (175) did not handle connector request for
print/2016_9090_R_1634500091131558445.pdf
You can use the FileDownloader to achieve what you want.
FileResource resource = new FileResource(pdfFile);
FileDownloader downloader = new FileDownloader(resource);
Button pdf= new Button("Download PDF");
downloader.extend(pdf);
Use this code
Window window = new Window();
((VerticalLayout) window.getContent()).setSizeFull();
window.setResizable(true);
window.setCaption("Exemplo PDF");
window.setWidth("800");
window.setHeight("600");
window.center();
StreamSource s = new StreamResource.StreamSource() {
#Override
public InputStream getStream() {
try {
File f = new File("C:/themes/repy.pdf");
FileInputStream fis = new FileInputStream(f);
return fis;
} catch (Exception e) {
e.printStackTrace();
return null;
}
}
};
StreamResource r = new StreamResource(s, "repy.pdf", mainLayout.getApplication());
Embedded e = new Embedded();
e.setSizeFull();
e.setType(Embedded.TYPE_BROWSER);
r.setMIMEType("application/pdf");
e.setSource(r);
window.addComponent(e);
getMainWindow().addWindow(window);
I am currently building a word processor for use in a multi-window media annotation tool, written in Java. It is for film students to write essays and embed them with links to multimedia clips.
I want the user to be able to highlight text in an rtf document and create a link to a media file in the project. When clicked the link will display the media in its associated window.
I would like to know if it is possible to dynamically create hyperlinks in rtf documents in Java? As is possible in Word, for example.
At the moment I am using a JEditorPane with the Advanced RTF Editor Kit (http://java-sl.com/advanced_rtf_editor_kit.html). I am struggling to find any sort of a solution.
Any help or pointers greatly appreciated.
Thanks
Edit:
code, with parts 1 & 3 from # Eric's answer added
`item3.addActionListener(new ActionListener() {
#Override
public void actionPerformed(java.awt.event.ActionEvent e) {
//use FX thread to open FileChooser
Platform.runLater(new Runnable() {
#Override
public void run() {
FileChooser fileChooser = new FileChooser();
fileChooser.setTitle("create link");
String startDirectory = System.getProperty("user.home") + File.separator + "Pictures";
fileChooser.setInitialDirectory(new File(startDirectory));
FileChooser.ExtensionFilter extFilter = new FileChooser.ExtensionFilter("JPEG files (*.jpg)", "*.jpg");
FileChooser.ExtensionFilter extFilter2 = new FileChooser.ExtensionFilter("PNG files (*.png)", "*.png");
FileChooser.ExtensionFilter extFilter3 = new FileChooser.ExtensionFilter("JPG files (*.jpeg)", "*.jpeg");
fileChooser.getExtensionFilters().addAll(extFilter,extFilter2, extFilter3);
File imageFile = fileChooser.showOpenDialog(stage);
if(imageFile != null){
Image image = ImageViewerController.getImage();
try {
image = new Image(imageFile.toURI().toURL().toExternalForm().toString());
int start = textArea.getSelectionStart();
int end = textArea.getSelectionEnd();
textArea.getDocument().remove(start, end);
String newString = "{\field{\*\fldinst HYPERLINK 'http://www.google.com/'}{\fldrslt http://www.google.com}}";
textArea.getDocument().insertString(start, newString , null);
textArea.addHyperlinkListener(new HyperlinkListener() {
#Override
public void hyperlinkUpdate(HyperlinkEvent hle) {
if (HyperlinkEvent.EventType.ACTIVATED.equals(hle.getEventType())) {
System.out.println(hle.getURL());
Desktop desktop = Desktop.getDesktop();
try {
desktop.browse(hle.getURL().toURI());
} catch (Exception ex) {
ex.printStackTrace();
}
}
}
});
} catch (Exception e1) {
e1.printStackTrace();
}
}
}
});`
I think there are various parts in your question:
1. Replace selected text in a Document:
Get the selected range with:
int start = editorpane.getSelectionStart();
int end = editorpane.getSelectionEnd();
Replace the text with:
editorpane.getDocument().remove(start,end);
editorpane.getDocument().insertString(start, newString, null);
Note: replace null with actual attribute set if needed.
2. Create a RTF-formatted hyperlink. I think this post has everything.
3. React to hyperlink clicks: As explained in the docs, you must add a HyperlinkListener to the editor pane to open the corresponding media. However a condition for this to work is that the editor kit generates HyperlinkEvents when hyperlinks are clicked. This is definitely the case for HTML documents, but since you are using a 3rd party library, I cannot confirm it will work the same way...
In a GEF editor, I have the following EditPart:
public class MyLabelEditPart extends AbstractGraphicalEditPart {
#Override
protected IFigure createFigure() {
return new Label();
}
#Override
protected void refreshVisuals() {
MyModel model = (MyModel) getModel();
Label figure = (Label) getFigure();
EditPart parent = getParent();
Font font = new Font(Display.getCurrent(), "sansserif", 11, SWT.BOLD);
figure.setFont(font);
figure.setForegroundColor(ColorConstants.darkGray);
figure.setText(model.getValueString());
parent.refresh();
}
All works fine with most models, but - you will have spotted the error already - I never dispose of the font. So, with a large-ish model of 10k+ tokens, this throws an org.eclipse.swt.SWTError: No more handles. At least I think (hope) this is what causes the error.
Now I cannot figure out how to dispose the font, as the figure for the EditPart is a Draw2D Label, not an SWT Widget. How can I make sure the dreaded error can be circumvented?
Apart from Baz' solution to make the font a static field, a good solution is to use a JFace FontRegistry, as detailed in this strangeoptics blog post.
If you want to keep and reuse all your resources ( images, fonts, colors..etc) at one point rather than using registries, follow this windows builder class
http://code.google.com/p/goclipse/source/browse/trunk/goclipse-n/src/org/eclipse/wb/swt/SWTResourceManager.java?r=445
We are trying to render both HTML and plain text using JTextPane. Basically the actual content is hosted on remote server, this content can contain some degree of HTML tags or none at all. In my JTextPane I have it defined as shown:
JTextPane jText = new JTextPane();
jText.setEditable(false);
jText.setContentType("text/html");
String content = "Please view article <a href=mydomain.com/content.txt>Link..</a>";
jText.setText(content);
And then using HyperlinkListener wants to be able to render the content when the link is clicked. I am doing so using the syntax below;
jText.addHyperlinkListener(new HyperlinkListener()
{
public void hyperlinkUpdate(final HyperlinkEvent he)
{
//Render the page
try{
setPage(he.getURL()); //Error on this line
}catch(Exception e){e.printStackTrace();}
}
});
Unfurtunately when we click on the link to render the content, we end up with the exception:
java.lang.IllegalArgumentException: Must be StyledEditorKit
at javax.swing.JTextPane.setEditorKit(JTextPane.java:474)
at javax.swing.JEditorPane.setContentType(JEditorPane.java:888)
at javax.swing.JEditorPane.getStream(JEditorPane.java:713)
at javax.swing.JEditorPane.setPage(JEditorPane.java:408)
This looks like when the content has no HTML tag available. Can someone help us resolve this issue so we can render both plain text and HTML.
Thanks in advance.
EDITED.
It sounds like what you're saying is that since you want to support both HTML and plain-text from your JTextPane as input, then not receiving a URL isn't really considered a problem. In that case, you should consider logging/eating the exception:
jText.addHyperlinkListener(new HyperlinkListener()
{
public void hyperlinkUpdate(final HyperlinkEvent he)
{
try {
//Render the page
setPage(he.getURL()); //Error on this line
} catch (IllegalArgumentException e) {
// either log the argument here, or just eat it and do nothing with it. logger.error() recommended
}
}
});