您的位置:首页 > 教育 > 锐评 > 微信营销手机_软件测试面试常见问题_企业站seo报价_最好用的搜索引擎

微信营销手机_软件测试面试常见问题_企业站seo报价_最好用的搜索引擎

2025/1/11 13:51:28 来源:https://blog.csdn.net/winniezhang/article/details/144998071  浏览:    关键词:微信营销手机_软件测试面试常见问题_企业站seo报价_最好用的搜索引擎
微信营销手机_软件测试面试常见问题_企业站seo报价_最好用的搜索引擎

简介

在这篇博客中,我们将深入分析一个基于 wxPython 实现的 PDF 阅读器程序。该程序支持加载 PDF 文件并显示页面内容,同时支持页面切换动画效果。

主要功能包括:

  • 加载 PDF 文件
  • 显示当前页面
  • 上一页/下一页切换
  • 页面切换动画
    C:\pythoncode\new\pdfreader.py

全部代码

import wx
import fitz  # PyMuPDF
from PIL import Image
import timeclass PDFReader(wx.Frame):def __init__(self, parent, title):super(PDFReader, self).__init__(parent, title=title, size=(800, 600))self.current_page = 0self.doc = Noneself.page_images = []self.animation_offset = 0self.is_animating = Falseself.animation_direction = 0self.next_page_idx = 0self.init_ui()self.init_timer()def init_ui(self):self.panel = wx.Panel(self)vbox = wx.BoxSizer(wx.VERTICAL)# 创建工具栏toolbar = wx.BoxSizer(wx.HORIZONTAL)open_btn = wx.Button(self.panel, label='打开PDF')prev_btn = wx.Button(self.panel, label='上一页')next_btn = wx.Button(self.panel, label='下一页')open_btn.Bind(wx.EVT_BUTTON, self.on_open)prev_btn.Bind(wx.EVT_BUTTON, self.on_prev_page)next_btn.Bind(wx.EVT_BUTTON, self.on_next_page)toolbar.Add(open_btn, 0, wx.ALL, 5)toolbar.Add(prev_btn, 0, wx.ALL, 5)toolbar.Add(next_btn, 0, wx.ALL, 5)self.pdf_panel = wx.Panel(self.panel)self.pdf_panel.SetBackgroundColour(wx.WHITE)self.pdf_panel.Bind(wx.EVT_PAINT, self.on_paint)vbox.Add(toolbar, 0, wx.EXPAND)vbox.Add(self.pdf_panel, 1, wx.EXPAND | wx.ALL, 5)self.panel.SetSizer(vbox)self.Centre()def init_timer(self):# 创建定时器用于动画self.timer = wx.Timer(self)self.Bind(wx.EVT_TIMER, self.on_timer)def on_open(self, event):with wx.FileDialog(self, "选择PDF文件", wildcard="PDF files (*.pdf)|*.pdf",style=wx.FD_OPEN | wx.FD_FILE_MUST_EXIST) as fileDialog:if fileDialog.ShowModal() == wx.ID_CANCEL:returnpdf_path = fileDialog.GetPath()self.load_pdf(pdf_path)def load_pdf(self, path):self.doc = fitz.open(path)self.current_page = 0self.page_images = []# 预加载所有页面for page in self.doc:pix = page.get_pixmap()img = Image.frombytes("RGB", [pix.width, pix.height], pix.samples)self.page_images.append(img)self.render_current_page()def render_current_page(self):if not self.doc or self.current_page >= len(self.page_images):returnpanel_size = self.pdf_panel.GetSize()# 创建背景background = Image.new('RGB', (panel_size.width, panel_size.height), 'WHITE')# 获取当前页面并调整大小current_img = self.page_images[self.current_page].resize((panel_size.width, panel_size.height), Image.LANCZOS)# 如果在动画中,需要绘制两个页面if self.is_animating:next_img = self.page_images[self.next_page_idx].resize((panel_size.width, panel_size.height), Image.LANCZOS)# 计算位置并粘贴图像if self.animation_direction > 0:  # 向右翻页background.paste(current_img, (-self.animation_offset, 0))background.paste(next_img, (panel_size.width - self.animation_offset, 0))else:  # 向左翻页background.paste(current_img, (self.animation_offset, 0))background.paste(next_img, (-panel_size.width + self.animation_offset, 0))else:# 非动画状态,直接显示当前页background.paste(current_img, (0, 0))# 转换为wx.Bitmapself.current_bitmap = wx.Bitmap.FromBuffer(panel_size.width, panel_size.height, background.tobytes())# 刷新显示self.pdf_panel.Refresh()def start_animation(self, direction):"""开始页面切换动画"""if self.is_animating:returnnext_page = self.current_page + directionif next_page < 0 or next_page >= len(self.page_images):returnself.is_animating = Trueself.animation_direction = directionself.next_page_idx = next_pageself.animation_offset = 0# 启动定时器,控制动画self.timer.Start(16)  # 约60fpsdef on_timer(self, event):"""定时器事件处理,更新动画"""if not self.is_animating:return# 更新动画偏移panel_width = self.pdf_panel.GetSize().widthstep = panel_width // 15  # 调整这个值可以改变动画速度self.animation_offset += step# 检查动画是否完成if self.animation_offset >= panel_width:self.animation_offset = 0self.is_animating = Falseself.current_page = self.next_page_idxself.timer.Stop()self.render_current_page()def on_prev_page(self, event):if self.is_animating or not self.doc:returnif self.current_page > 0:self.start_animation(-1)def on_next_page(self, event):if self.is_animating or not self.doc:returnif self.current_page < len(self.page_images) - 1:self.start_animation(1)def on_paint(self, event):if not hasattr(self, 'current_bitmap'):returndc = wx.PaintDC(self.pdf_panel)dc.DrawBitmap(self.current_bitmap, 0, 0, True)def main():app = wx.App()frame = PDFReader(None, title='PDF阅读器')frame.Show()app.MainLoop()if __name__ == '__main__':main()
代码结构

整个程序由以下几个核心部分组成:

  1. 初始化 UI 界面
  2. 加载 PDF 文件
  3. 显示 PDF 页面
  4. 页面切换动画

以下是代码的详细解析。


初始化 UI 界面

代码段:

self.panel = wx.Panel(self)
vbox = wx.BoxSizer(wx.VERTICAL)# 创建工具栏
toolbar = wx.BoxSizer(wx.HORIZONTAL)open_btn = wx.Button(self.panel, label='打开PDF')
prev_btn = wx.Button(self.panel, label='上一页')
next_btn = wx.Button(self.panel, label='下一页')open_btn.Bind(wx.EVT_BUTTON, self.on_open)
prev_btn.Bind(wx.EVT_BUTTON, self.on_prev_page)
next_btn.Bind(wx.EVT_BUTTON, self.on_next_page)toolbar.Add(open_btn, 0, wx.ALL, 5)
toolbar.Add(prev_btn, 0, wx.ALL, 5)
toolbar.Add(next_btn, 0, wx.ALL, 5)self.pdf_panel = wx.Panel(self.panel)
self.pdf_panel.SetBackgroundColour(wx.WHITE)
self.pdf_panel.Bind(wx.EVT_PAINT, self.on_paint)vbox.Add(toolbar, 0, wx.EXPAND)
vbox.Add(self.pdf_panel, 1, wx.EXPAND | wx.ALL, 5)self.panel.SetSizer(vbox)
self.Centre()

解析:

  1. 创建主面板 wx.Panel 并使用 BoxSizer 布局管理组件。
  2. 创建工具栏,包括三个按钮:打开 PDF、上一页和下一页。
  3. 创建 PDF 显示区域,绑定 EVT_PAINT 事件用于页面绘制。
  4. 使用 Add 方法将工具栏和显示区域添加到垂直布局中。
加载 PDF 文件

代码段:

def on_open(self, event):with wx.FileDialog(self, "选择PDF文件", wildcard="PDF files (*.pdf)|*.pdf",style=wx.FD_OPEN | wx.FD_FILE_MUST_EXIST) as fileDialog:if fileDialog.ShowModal() == wx.ID_CANCEL:returnpdf_path = fileDialog.GetPath()self.load_pdf(pdf_path)def load_pdf(self, path):self.doc = fitz.open(path)self.current_page = 0self.page_images = []# 预加载所有页面for page in self.doc:pix = page.get_pixmap()img = Image.frombytes("RGB", [pix.width, pix.height], pix.samples)self.page_images.append(img)self.render_current_page()

解析:

  1. 使用 wx.FileDialog 打开文件对话框,选择 PDF 文件。
  2. 调用 fitz.open 加载 PDF 文件,存储为 self.doc
  3. 遍历 PDF 页面的每一页,使用 get_pixmap 提取页面图像,并转换为 PIL 图像对象,存储到 self.page_images 列表中。
  4. 调用 render_current_page 渲染第一页。
显示 PDF 页面

代码段:

def render_current_page(self):if not self.doc or self.current_page >= len(self.page_images):returnpanel_size = self.pdf_panel.GetSize()# 创建背景background = Image.new('RGB', (panel_size.width, panel_size.height), 'WHITE')# 获取当前页面并调整大小current_img = self.page_images[self.current_page].resize((panel_size.width, panel_size.height), Image.LANCZOS)if self.is_animating:next_img = self.page_images[self.next_page_idx].resize((panel_size.width, panel_size.height), Image.LANCZOS)if self.animation_direction > 0:  # 向右翻页background.paste(current_img, (-self.animation_offset, 0))background.paste(next_img, (panel_size.width - self.animation_offset, 0))else:  # 向左翻页background.paste(current_img, (self.animation_offset, 0))background.paste(next_img, (-panel_size.width + self.animation_offset, 0))else:background.paste(current_img, (0, 0))self.current_bitmap = wx.Bitmap.FromBuffer(panel_size.width, panel_size.height, background.tobytes())self.pdf_panel.Refresh()

解析:

  1. 检查当前文档和页面索引的有效性。
  2. 创建一个与显示区域大小一致的白色背景。
  3. 将当前页面图像调整为显示区域的大小。
  4. 如果处于动画状态,还需要绘制下一页面,并根据动画方向和偏移量计算粘贴位置。
  5. 将结果图像转换为 wx.Bitmap,刷新显示区域。
页面切换动画

代码段:

def start_animation(self, direction):if self.is_animating:returnnext_page = self.current_page + directionif next_page < 0 or next_page >= len(self.page_images):returnself.is_animating = Trueself.animation_direction = directionself.next_page_idx = next_pageself.animation_offset = 0self.timer.Start(16)  # 约60fpsdef on_timer(self, event):if not self.is_animating:returnpanel_width = self.pdf_panel.GetSize().widthstep = panel_width // 15self.animation_offset += stepif self.animation_offset >= panel_width:self.animation_offset = 0self.is_animating = Falseself.current_page = self.next_page_idxself.timer.Stop()self.render_current_page()

解析:

  1. start_animation 初始化动画参数并启动定时器,控制动画帧率。
  2. on_timer 事件处理器更新动画偏移量,并检查动画是否完成。
  3. 动画完成后,更新当前页面索引并停止定时器。

运行效果

在这里插入图片描述

总结

这段代码展示了如何结合 wxPython 和 PyMuPDF 构建一个功能齐全的 PDF 阅读器。它不仅实现了基本的 PDF 加载和显示功能,还加入了平滑的页面切换动画,提升了用户体验。通过合理的模块化设计和事件绑定,代码逻辑清晰,便于扩展。

版权声明:

本网仅为发布的内容提供存储空间,不对发表、转载的内容提供任何形式的保证。凡本网注明“来源:XXX网络”的作品,均转载自其它媒体,著作权归作者所有,商业转载请联系作者获得授权,非商业转载请注明出处。

我们尊重并感谢每一位作者,均已注明文章来源和作者。如因作品内容、版权或其它问题,请及时与我们联系,联系邮箱:809451989@qq.com,投稿邮箱:809451989@qq.com