I. Introduction▲
Ce tutoriel va nous expliquer rapidement comment utiliser SwingX pour créer son propre Visualiseur PDF. Le but de ce tutoriel est de créer un effet sur les fichiers PDF, un peu comme ceux que l'on peut voir sur Mac OS X lorsque l'on ouvre un dossier contenant des fichiers PDF.
II. Première étape : utiliser le PDF Renderer▲
L'équipe SwingLabs a récemment sorti un PDF Renderer, une API qui ne permet pas de créer des PDF, mais d'afficher leur contenu.
Pour plus d'informations sur cette librairie, on peut se rendre sur le site officiel du projet.
L'utilisation de cette librairie est très simple. Tout ce qu'il y a à faire est d'ouvrir le fichier PDF, stocker ce fichier dans un ByteBuffer et créer un PDFFile depuis ce buffer. Le site officiel donne les principaux exemples d'utilisation : Exporter une PDFPage dans une BufferedImage, ou encore dans un Graphics.
Dans notre premier exemple plus bas, nous allons utiliser un JXPanel (du projet SwingX) pour simplement afficher la première page de notre fichier PDF en tant qu'image.
public
class
PdfRendererTester extends
JXFrame {
private
static
final
long
serialVersionUID =
1
L;
public
PdfRendererTester
(
) {
setTitle
(
"PDF Renderer Tester"
);
setDefaultCloseOperation
(
JFrame.DISPOSE_ON_CLOSE);
String url =
"/Users/flo/Documents/pdf/PaintingEffects.pdf"
;
// this one above is not working.
//String url = "/Users/flo/Documents/pdf/TS-3414.pdf";
Image pdfImage;
JLabel lbl =
new
JLabel
(
);
try
{
pdfImage =
getImageFromPdf
(
url);
Image tmbPdfImage =
GraphicsUtilities.createThumbnail
((
BufferedImage)pdfImage, 400
);
lbl.setIcon
(
new
ImageIcon
(
tmbPdfImage));
}
catch
(
IOException e) {
e.printStackTrace
(
);
lbl.setText
(
e.toString
(
));
}
add
(
lbl);
pack
(
);
}
public
Image getImageFromPdf
(
String fileUrl) throws
IOException {
//load a pdf from a byte buffer
File file =
new
File
(
fileUrl);
RandomAccessFile raf =
new
RandomAccessFile
(
file, "r"
);
FileChannel channel =
raf.getChannel
(
);
ByteBuffer buf =
channel.map
(
FileChannel.MapMode.READ_ONLY, 0
, channel.size
(
));
PDFFile pdffile =
new
PDFFile
(
buf);
// draw the first page to an image
PDFPage page =
pdffile.getPage
(
0
);
//get the width and height for the doc at the default zoom
Rectangle rect =
new
Rectangle
(
0
,0
,
(
int
)page.getBBox
(
).getWidth
(
),
(
int
)page.getBBox
(
).getHeight
(
));
//generate the image
Image result =
page.getImage
(
rect.width, rect.height, //width & height
rect, // clip rect
null
, // null for the ImageObserver
true
, // fill background with white
true
// block until drawing is done
);
return
result;
}
public
static
void
main
(
String[] args) {
SwingUtilities.invokeLater
(
new
Runnable
(
) {
public
void
run
(
) {
new
PdfRendererTester
(
).setVisible
(
true
);
}}
);
}
}
On obtient finalement ce résultat :
Certains fichiers PDF provoquent des erreurs OutOfMemoryError ou autres. Pour l'instant l'équipe Singlabs ne prend pas en compte toutes les fonctionnalités des PDF et donc, certaines peuvent ne pas être rendues correctement.
III. Seconde étape : ajouter un effet de reliure en spirale▲
On va maintenant utiliser les SwingX Painters pour créer l'effet de reliure sur la gauche de l'image pour ajouter un effet plus réaliste.
Comme rien d'équivalent n'existe dans SwingX pour créer un tel effet, nous allons implémenter le nôtre. Nous avons donc créé une classe utilitaire PDFUtil qui va s'occuper de créer notre effet à partir d'une BufferedImage existante. Cette méthode dessine au-dessus de l'image existante un effet de gloss puis un ensemble de lignes pour faire une pseudoreliure. L'appel à la méthode createSpiralBinding() est fait depuis notre méthode getImageFromPdf()
createSpiralBinding
(
GraphicsUtilities.createThumbnail
(
result, newSize));
IV. Étape finale : mixer le tout▲
CompoundPainter est utilisé ici pour assembler les différents Painter :
- celui contenant l'image PDF ;
- celui contenant l'effet d'ombre.
img =
PdfUtil.getImageFromPdf
(
url, imgSize.width, imgSize.height);
ImagePainter pdfPainter =
new
ImagePainter
(
img);
ShadowRenderer shadowRndr =
new
ShadowRenderer
(
);
shadowRndr.setOpacity
(
0.9
f);
shadowRndr.setSize
(
10
);
BufferedImage shadowImg =
shadowRndr.createShadow
(
img);
ImagePainter shadowPainter =
new
ImagePainter
(
shadowImg);
CompoundPainter cp =
new
CompoundPainter
(
shadowPainter, pdfPainter);
JXLabel lbl =
new
JXLabel
(
);
lbl.setBackgroundPainter
(
cp);
Maintenant, on peut exécuter le tout pour voir le résultat.
V. Aller plus loin▲
SwingX Painters sur DeveloperLife qui m'a inspiré pour écrire cet article.
Le site du projet PDFRenderer où on trouvera les sources du projet ainsi que des exemples.
SwingLabs qui met à disposition un ensemble de composants Swing améliorés.
VI. Téléchargements▲
Les sources du projet.