当前位置:网站首页 > 编程语言 > 正文

pdfview和pdf的区别(pdfxview)



第三方库 PyMuPDF 在 python 环境下对 PDF 文件的操作,特别是图片和pdf之间相互转换比较方便,并且能较方便的执行一些如追加删除之类的功能。开发文档见:https://pymupdf.readthedocs.io/en/latest/。

    我写的一个查看 pdf文件demo已上传到我的资源中。界面左边栏为页面导航,点击缩略图后显示页面,按ctrl+鼠标滚轮后可缩放页面 ,使用了tkinter开发。CSDN资源下载:https://download.csdn.net/download/zhoury/。欢迎下载参考。

Tkinter 是 Python 的标准 GUI 库。Python 使用 Tkinter 可以快速的创建 GUI 应用程序。

由于 Tkinter 是内置到 python 的安装包中、只要安装好 Python 之后就能 import Tkinter 库、而且 IDLE 也是用 Tkinter 编写而成、对于简单的图形界面 Tkinter 还是能应付自如。

与pyqt5相比,tkinter中如果想要构建一个GUI界面布局,就必须自己写代码,因为Tkinter没有提供一个图形界面设计器。这是tkinter中比较烦人的一个地方。还好本例界面还是比较简单的。

在本例中,我把界面部分和程序逻辑部分做了一些分离,界面类为class MyFrame(tk.Frame),主程序类为class PdfFrame(MyFrame),从MyFrame中继承界面元素后进行事件处理。下面分几部分简要介绍一下:

1、import库

import tkinter as tk
import tkinter.font as tf
from tkinter import messagebox, filedialog, simpledialog
from tkinter import ttk    
from PIL import Image, ImageTk



import sys
import os
import os.path
import time


2、界面类

class MyFrame(tk.Frame):
    def __init__(self, master=None):
        tk.Frame.__init__(self, master) 
        self.root = master                 # root ,在主程序中 root = tk.Tk(),然后作为参数引入
        self.pack(fill=tk.BOTH, expand=True)
        self.font_en = tf.Font(self, size=14)




        self.createICO()   #初始化图标
        self.create_menu()   #创建菜单
        self.createToolbar()  #创建工具栏
        self.create_widgets()   #创建主界面


菜单、工具栏生成这里就不写了,主要介绍一下主界面中缩略图列表和内容查看两个部分吧。

2.1缩略图列表

        self.fm_left = tk.Frame(self)     # 左侧缩略图列表栏

        # LabelFrame本身不带滚动条,在LabelFrame中放置label,并带滚动条的方法:
        # 1) 先新建一个canvas,在cavas上放置滚动条,2) 然后在canvas中放置labelframe,frame的长宽,紧跟canvas。
        # 3) 最后canvas.create_window,根据labelframe创建canvas窗口
        self.fm_list_scb_ver = tk.Frame(self.fm_left,width=230)  # 缩略图列表窗口
        vsb1 = tk.Scrollbar(self.fm_list_scb_ver,width=20)    # canvas垂直滚动条
        vsb1.pack(side=tk.RIGHT,fill=tk.Y)
        self.listCanvas = tk.Canvas(self.fm_list_scb_ver,bg = 'white',yscrollcommand=vsb1.set,width=220)  # 缩略图放置canvas
        self.listCanvas.pack(side=tk.LEFT,fill=tk.BOTH, expand=True)
        vsb1.config(command=self.listCanvas.yview)







        self.fm_list_scb_ver.pack(side=tk.TOP,fill=tk.Y,expand=True)    #放置缩略图列表窗口
        self.fm_left.pack(side=tk.LEFT,fill=tk.Y)    # 放置左侧缩略图列表栏
以上只是建立了一个空的缩略图窗口,还需要在主程序中生成label列表并放置后才能显示。

2.2 图片显示组件

        self.fm_right = tk.Frame(self)    # 右侧查看窗口
        self.fm_canvas_scb_ver = tk.Frame(self.fm_right)  # canvas放置窗口
        vsb = tk.Scrollbar(self.fm_canvas_scb_ver)    # canvas滚动条
        vsb.pack(side=tk.RIGHT,fill=tk.Y) 
        hsb = tk.Scrollbar(self.fm_canvas_scb_ver,orient=tk.HORIZONTAL) 
        hsb.pack(side=tk.BOTTOM,fill=tk.X)
        # 创建canvas,并绑定滚动条
        self.cvCanvas = tk.Canvas(self.fm_canvas_scb_ver,bg = 'white',yscrollcommand=vsb.set,xscrollcommand=hsb.set,scrollregion=(0,0,1200,1200))
        self.cvCanvas.pack(fill=tk.BOTH, expand=True)
        self.cvCanvas.bind("<Control-MouseWheel>", self.canvasProcessWheel)   # 鼠标滚轮事件 CTRL + 滚轮
        vsb.config(command=self.cvCanvas.yview)
        hsb.config(command=self.cvCanvas.xview)
        self.fm_canvas_scb_ver.pack(fill=tk.BOTH, expand=True)  # 放置canvas放置窗口
        self.fm_right.pack(fill=tk.BOTH, expand=True)   # 放置右侧查看窗口












3、主程序

3.1 继承界面类

class PdfFrame(MyFrame):
    def __init__(self, master=None):
        super(PdfFrame,self).__init__(master)    # 调用父类初始化

3.2 打开pdf文件后刷新缩略图列表

3.2.1 读pdf页面,生成label列表
        for i in range(0, self.nPages):
            page = self.docDoc[i]  # 当前页
            zoom = int(100)    # mupdf输出页面缩放,100表示默认大小
            rotate = int(0)
            trans = fitz.Matrix(zoom / 100.0, zoom / 100.0).preRotate(rotate)
            pix = page.getPixmap(matrix=trans, alpha=False)    # 生成pixmap图片
            # set the mode depending on alpha
            mode = "RGBA" if pix.alpha else "RGB"
            w = 210    
            h = 297 
            img = Image.frombytes(mode, [pix.width, pix.height], pix.samples).resize((w,h))    # 生成当前页图
            merge_img = Image.new('RGB', (210, 297), 0xffffff)     # 空白缩略图
            merge_img.paste(img, (0, 0))    # 将图片贴到空白缩略图中












            global My_Global_List_Imgs     # 一定要用global,否则canvas不显示图片
            My_Global_List_Imgs.append(ImageTk.PhotoImage(merge_img))          
            lb = tk.Label(self.labelframe, height=297, width=210 ,image=My_Global_List_Imgs[i])    # 产生缩略图label
            lb.bind("<Double-Button-1>",self.handlerAdaptor(self.clickList,curr=i))   # 绑定鼠标双击,传递参数curr为当前页码
            self.labelList.append(lb)



3.2.2  放置并显示

        canvasHeight = 0  # 列表高度
        self.lbpageList = []    # 缩略图label列表,显示页码
        for j in range(0, self.nPages):
            l = self.labelList[j]        # 放置缩略图label
            l.pack()
            canvasHeight = canvasHeight + 297   # 计算缩略图高度
            lbpage = tk.Label(self.labelframe,text="第"+ str(j+1) + "页")    # 缩略图页码
            lbpage.pack()
            self.lbpageList.append(lbpage)
            canvasHeight = canvasHeight + 28    # 计算页码显示高度(默认行高)








        self.listCanvas.config(scrollregion=(0,0,100,canvasHeight))    # 列表滚动区域
        self.listCanvas.create_window((110, int(canvasHeight/2)), window=self.labelframe)  # create_window
        self.fm_list_scb_ver.pack(side=tk.TOP,fill=tk.Y,expand=True)    # 只允许上下扩展
        self.btnShow.config(image=self.imgleft)       # 缩略图栏目缩放按钮图标
        self.listCanvas.update()  # force screen redraw/update
        time.sleep(0.25)    # pause, but don't block gui
3.3 显示当前页
        page = self.docDoc[self.nCurr]
        zoom = int(200)
        rotate = int(0)
        trans = fitz.Matrix(zoom / 100.0, zoom / 100.0).preRotate(rotate)
        pix = page.getPixmap(matrix=trans, alpha=False)  # 得到当前页










        # set the mode depending on alpha
        mode = "RGBA" if pix.alpha else "RGB"
        self.m_pixmap = Image.frombytes(mode, [pix.width, pix.height], pix.samples)
        self.pixmapw = pix.width
        self.pixmaph = pix.height
        global My_Global_CanVas_Pic    # 要用global变量,否则canvas不显示图片
        My_Global_CanVas_Pic = ImageTk.PhotoImage(self.m_pixmap.resize((self.pixmapw,self.pixmaph)))
        self.cvCanvas.create_image(int(self.pixmapw/2),int(self.pixmaph/2),image=My_Global_CanVas_Pic)
        self.cvCanvas.config(scrollregion=(0,0,self.pixmapw,self.pixmaph))  # canvas滚动范围
        self.fm_canvas_scb_ver.pack(fill=tk.BOTH, expand=True)  # 放置canvas放置窗口
        self.cvCanvas.update()  # force screen redraw/update
        time.sleep(0.25)    # pause, but don't block gui










在开发中,界面布局代码虽然繁琐,这种编码只是重复劳动,一旦熟练后问题不是很大,最大的问题是性能问题,在本例中主要是canvas刷新比较慢。

在本例中有一个功能是使用ctrl+滚轮缩放页面,前段时间使用pyqt5写了个pymupdf的demo(见https://blog.csdn.net/zhoury/article/details/),相同功能两者比较,pyqt5缩放很流畅,而tkinter有很明显的拖沓,特别是打开文件页数一多、查看的图片放大后,刷新更是有数量级的差距,感觉鼠标滚轮的事件都堵在队列中了。使用self.cvCanvas.update() 强制刷新,效果稍好点,但仍不是很理想,和pyqt5有明显差距。

目前没有找到好方法,如果哪位高手有解决方法,希望不吝赐教,多谢了!

 

到此这篇pdfview和pdf的区别(pdfxview)的文章就介绍到这了,更多相关内容请继续浏览下面的相关推荐文章,希望大家都能在编程的领域有一番成就!

版权声明


相关文章:

  • linux dos2unix安装(linux怎么安装sudo安装包)2025-08-05 16:09:06
  • 网页传输文件工具(传文件的网页)2025-08-05 16:09:06
  • 发送验证码失败是怎么回事呢(发送验证码失败是什么原因)2025-08-05 16:09:06
  • 苹果定位打开了无法获取位置(iphone定位打开但是无法定位)2025-08-05 16:09:06
  • pdf文档如何查找内容(pdf文件怎么快速查找内容)2025-08-05 16:09:06
  • Tp9930(tp9930芯片功能)2025-08-05 16:09:06
  • win7虚拟机配置要求(win7虚拟机需要多大空间)2025-08-05 16:09:06
  • 单片机 课程(单片机课程感受)2025-08-05 16:09:06
  • m301h刷机包下载(m301h刷机固件)2025-08-05 16:09:06
  • k8s 更新pod(k8s中pod)2025-08-05 16:09:06
  • 全屏图片