基于Swing实现的PDFViewer
最近因项目需求,需要使用Swing实现PDFViewer,并且需要鼠标拖动,放大缩小等操作,一开始在网上也找到了PDF-Renderer,但是一看原理,不也就是将PDF文件转化为image而已,目前解决掉了拖动以及放大缩小的BUG问题。
如下使用apache-pdfbox转换的PDF,当然也可以替换为iText或者别的依赖
代码如下:
import java.awt.Color;
import java.awt.Cursor;
import java.awt.Graphics;
import java.awt.Graphics2D;
import java.awt.Image;
import java.awt.Toolkit;
import java.awt.event.MouseAdapter;
import java.awt.event.MouseEvent;
import java.awt.event.MouseWheelEvent;
import java.awt.event.MouseWheelListener;
import java.awt.image.BufferedImage;
import java.io.File;
import java.io.IOException;
import java.util.List;
import javax.imageio.ImageIO;
import javax.swing.JFrame;
import javax.swing.JPanel;
import javax.swing.JScrollPane;
import org.apache.pdfbox.pdmodel.PDDocument;
import org.apache.pdfbox.pdmodel.PDPage;
/**
* PDF查看器
* @author End_Unripe
*/
public class PDFViewer extends JPanel {
private static final long serialVersionUID = 1L;
private String imagePath;
// 鼠标按下时的坐标 以及 更新后的坐标
private int startX, startY;
// 当前的位置偏移
private int offsetX = 0, offsetY = 0;
// 缩放比例,默认为 1.0
private double scale = 1.0;
// 缩放基数
private double scaleRadix = 1.02;
// 拖动边距
private int margin = 100;
private Image image;
public PDFViewer(String imagePath) {
this.imagePath = imagePath;
// 添加鼠标滚轮监听器
addMouseWheelListener(new MouseWheelListener() {
@Override
public void mouseWheelMoved(MouseWheelEvent e) {
int notches = e.getWheelRotation();
// 获取画布宽高
int canvansWidth = getWidth();
int canvansHeight = getHeight();
// 获取缩放后的图片大小
int imageWidth = 0;
int imageHeight = 0;
if(notches < 0) {
imageWidth = (int) (image.getWidth(null) * scale * scaleRadix);
imageHeight = (int) (image.getHeight(null) * scale * scaleRadix);
}else {
imageWidth = (int) (image.getWidth(null) * scale / scaleRadix);
imageHeight = (int) (image.getHeight(null) * scale / scaleRadix);
}
// 计算当前image位置偏移后的位置
int leftTopX = (offsetX + (canvansWidth - imageWidth) / 2);
int leftTopY = (offsetY + (canvansHeight - imageHeight) / 2);
int leftDownX = leftTopX;
int leftDownY = leftTopY + imageHeight;
int rightTopX = leftTopX + imageWidth;
int rightTopY = leftTopY;
int rightDownX = rightTopX;
int rightDownY = leftDownY;
if(leftTopX <= canvansWidth - margin && leftDownX <= canvansWidth - margin && rightTopX >= margin && rightDownX >= margin && leftTopY < canvansHeight - margin && leftDownY >= margin && rightTopY <= canvansHeight - margin && rightDownY >= margin) {
if (notches < 0) {
// 滚轮向上,放大画布
if(scale <= 2) {
scale *= scaleRadix;
}
} else {
// 滚轮向下,缩小画布
if(scale >= 0.2) {
scale /= scaleRadix;
}
}
}
// 重新绘图
repaint();
}
});
// 为组件设置鼠标监听事件
addMouseListener(new MouseAdapter() {
// 鼠标按下
@Override
public void mousePressed(MouseEvent e) {
setCursor(new Cursor(Cursor.MOVE_CURSOR));
// 记录鼠标按下时的坐标
startX = e.getX();
startY = e.getY();
}
// 鼠标释放
@Override
public void mouseReleased(MouseEvent e) {
setCursor(new Cursor(Cursor.DEFAULT_CURSOR));
}
});
// 添加鼠标动作监听
addMouseMotionListener(new MouseAdapter() {
// 鼠标拖动
@Override
public void mouseDragged(MouseEvent e) {
// 统计本次鼠标移动的相对值
int dx = e.getX() - startX;
int dy = e.getY() - startY;
// 获取画布宽高
int canvansWidth = getWidth();
int canvansHeight = getHeight();
// 获取图片大小
int imageWidth = (int) (image.getWidth(null) * scale);
int imageHeight = (int) (image.getHeight(null) * scale);
// 计算当前image位置偏移后的位置
int leftTopX = (offsetX + (canvansWidth - imageWidth) / 2) + dx;
int leftTopY = (offsetY + (canvansHeight - imageHeight) / 2) + dy;
int leftDownX = leftTopX;
int leftDownY = leftTopY + imageHeight;
int rightTopX = leftTopX + imageWidth;
int rightTopY = leftTopY;
int rightDownX = rightTopX;
int rightDownY = leftDownY;
if(leftTopX <= canvansWidth - margin && leftDownX <= canvansWidth - margin && rightTopX >= margin && rightDownX >= margin) {
// 偏移量累加 x
offsetX += dx;
// 记录当前拖动后的位置 x
startX += dx;
}
if(leftTopY < canvansHeight - margin && leftDownY >= margin && rightTopY <= canvansHeight - margin && rightDownY >= margin) {
// 偏移量累加 y
offsetY += dy;
// 记录当前拖动后的位置 y
startY += dy;
}
// 重新绘图
repaint();
}
});
}
public void paintComponent(Graphics g) {
super.paintComponent(g);
setBackground(new Color(26, 57, 79));
// 画布进行整体偏移
Graphics2D g2 = (Graphics2D)g;
// 缩放画布
//g2.scale(scale, scale);
// 拖动画布
g2.translate(offsetX, offsetY);
// 获取图片
image = Toolkit.getDefaultToolkit().getImage(imagePath);
if(null != image) {
// 绘制图像
int imageWidth = (int) (image.getWidth(null) * scale);
int imageHeight = (int) (image.getHeight(null) * scale);
// 获取画布宽高
int canvansWidth = getWidth();
int canvansHeight = getHeight();
int x = (canvansWidth - imageWidth) / 2;
int y = (canvansHeight - imageHeight) / 2;
g2.drawImage(image, x, y, imageWidth, imageHeight, null);
}
}
public static void main(String[] args) throws IOException {
// 创建 JFrame 窗口
JFrame frame = new JFrame("Large Canvas");
// 设置窗口关闭行为 点击右上角关闭按钮 关闭窗口并退出应用
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
// 创建画布
PDFViewer canvas = new PDFViewer(pdfToImage());
// 将画布放入滚动布局
JScrollPane scrollPane = new JScrollPane(canvas);
// 将滚动布局放入窗口
frame.getContentPane().add(scrollPane);
// 窗口自适应
frame.pack();
// 窗口设置可见
frame.setVisible(true);
}
public static String pdfToImage() throws IOException{
String imagePth = "";
String sourceDir = "C:\\Users\\Administrator\\Desktop\\test.pdf";
String destinationDir = "C:\\Users\\Administrator\\Desktop\\";
File sourceFile = new File(sourceDir);
File destinationFile = new File(destinationDir);
if (!destinationFile.exists()) {
destinationFile.mkdir();
System.out.println("Folder Created -> "+ destinationFile.getAbsolutePath());
}
if (sourceFile.exists()) {
System.out.println("Images copied to Folder: "+ destinationFile.getName());
PDDocument document = PDDocument.load(sourceDir);
List<PDPage> list = document.getDocumentCatalog().getAllPages();
System.out.println("Total files to be converted -> "+ list.size());
String fileName = sourceFile.getName().replace(".pdf", "");
int pageNumber = 1;
BufferedImage image = list.get(0).convertToImage();
imagePth = destinationDir + fileName +"_"+ pageNumber +".png";
File outputfile = new File(imagePth);
System.out.println("Image Created -> "+ outputfile.getName());
ImageIO.write(image, "png", outputfile);
document.close();
System.out.println("Converted Images are saved at -> "+ imagePth);
} else {
System.err.println(sourceFile.getName() +" File not exists");
}
return imagePth;
}
}
叶子的飘落,是风的追求,还是树的不挽留.