首页 > 其他分享 >基于Swing实现的PDFViewer

基于Swing实现的PDFViewer

时间:2023-09-04 11:14:53浏览次数:36  
标签:基于 scale java PDFViewer int image new Swing import

最近因项目需求,需要使用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;
	}

}

标签:基于,scale,java,PDFViewer,int,image,new,Swing,import
From: https://www.cnblogs.com/endunripe/p/17676395.html

相关文章

  • 基于jwt的token验证
    一、什么是JWTJsonwebtoken(JWT),是为了在网络应用环境间传递声明而执行的一种基于JSON的开放标准((RFC7519).该token被设计为紧凑且安全的,特别适用于分布式站点的单点登录(SSO)场景。JWT的声明一般被用来在身份提供者和服务提供者间传递被认证的用户身份信息,以便于从资源......
  • 基于智能边缘分析网关的电动车进电梯安全预警系统
    一、背景介绍随着社会的发展和科技的进步,电动车在日常生活中的使用越来越广泛。然而,一些小区和楼宇管理中出现了电动车进入电梯的安全隐患。为了解决这个问题,我们设计了一套基于智能边缘分析网关的电动车进电梯AI预警方案,旨在通过人工智能技术来实时监测电梯内的电动车,及时预警并采......
  • 基于springboot的个人云盘管理系统的设计与实现
    传统办法管理信息首先需要花费的时间比较多,其次数据出错率比较高,而且对错误的数据进行更改也比较困难,最后,检索数据费事费力。因此,在计算机上安装个人云盘管理系统软件来发挥其高效地信息处理的作用,可以规范信息管理流程,让管理工作可以系统化和程序化,同时,个人云盘管理系统的有效运用......
  • 基于springboot流浪动物管理系统
    在如今社会上,关于信息上面的处理,没有任何一个企业或者个人会忽视,如何让信息急速传递,并且归档储存查询,采用之前的纸张记录模式已经不符合当前使用要求了。所以,对流浪动物信息管理的提升,也为了对流浪动物信息进行更好的维护,流浪动物管理系统的出现就变得水到渠成不可缺少。通过对流浪......
  • 基于OpenEuler的信创国产瘦客户机软件系统 DoraOS
    DoraOS是一款瘦客户机系统软件,最新版本基于OpenEuler开发。可以将主机转化为专业的瘦客户机。目前支持x86架构的硬件。软件下载地址为: https://www.doracloud.cn/downloads/32-cn.html制作一张启动U盘,即可进行安装。DoraOS的连接窗口界面如下,界面比较简洁。左侧进入控制中心,右......
  • 我的 Kafka 旅程 - 基于账号密码的 SASL+PLAIN 认证授权 · 配置 · 创建账号 · 用户
    本文基于Kafka3.0+的KRaft模式来阐述默认的Kafka不受认证约束,可不用账号就可以连接到服务,也就是默认的PLAIN方式,不需要认证;配置了SASL认证之后,连接Kafka只能用凭证连接登录。SASL支持的认证方式有多种:GSSAPI,PLAIN,SCRAM-SHA-256,SCRAM-SHA-512,OAUTHBEARERGSSAPI......
  • 基于微信小程序的图书馆座位预约系统设计与实现-计算机毕业设计源码+LW文档
    选题意义: 该系统可以监测到图书馆座位的使用情况,便于学生查询图书馆的分布、座位多少、是否空闲等基本数据。学生可以通过手机或者计算机等终端进行座位预约,方便快捷。对于占座现象,学生可以通过系统进行反馈,方便图书馆管理人员及时处理。基于微信小程序的图书馆座位预约系统的使......
  • 基于JavaWeb实现智慧菜市场系统的设计与实现程序
    作者主页:编程指南针作者简介:Java领域优质创作者、阿里云博客专家、51CTO特邀作者、多年架构师设计经验、腾讯课堂常驻讲师主要内容:Java项目、Python项目、前端项目、人工智能与大数据、简历模板、学习资料、面试题库、技术互助收藏点赞不迷路 关注作者有好处目录一,环境介绍二,项目......
  • 【机哥】基于神经网络的图像去噪器
    鱼弦:全栈领域创作新星创作者、51CTO(Top红人+专家博主)、github开源爱好者(go-zero源码二次开发、游戏后端架构https://github.com/Peakchen)基于神经网络的图像去噪器是一种利用深度学习技术来降低图像噪声的方法。它通过训练一个神经网络模型,将含有噪声的图像作为输入,输出一张更......
  • 图解Spark Graphx基于connectedComponents函数实现连通图底层原理
    原创/朱季谦第一次写这么长的graphx源码解读,还是比较晦涩,有较多不足之处,争取改进。一、连通图说明连通图是指图中的任意两个顶点之间都存在路径相连而组成的一个子图。用一个图来说明,例如,下面这个叫graph的大图里,存在两个连通图。左边是一个连接图,该子图里每个顶点都存在路......