点击上方“Python爬虫与数据挖掘”,进行关注

回复“书籍”即可获赠Python从入门到进阶共10本电子书

羌笛何须怨杨柳,春风不度玉门关。

经过两周的迭代,现在我们的 PyReadon 已经具备一般的 PDF 阅读器的基本功能:

前几版相比较,这一版优化了书籍的数据结构,支持同时阅读多本书,支持鼠标左键翻页,并通过与 sqlite3 数据库的交互来保存书库以及书籍信息(地址、页数等)。

书籍

使用 Book 类来保存书籍信息,比如元数据、页数以及阅读与否的信息。通过 __eq__ 特殊方法,来判断两个 book 实例是否为同一对象。

class Book:    def __init__(self, fname):        # 文件名        self.fname = fname        # 是否被阅读        self.flag = None        self._info = None        self._page = 0        self.get_meta_data(self.fname)    def __eq__(self, other):        if hasattr(other, 'fname'):            return self.fname == other.fname        return False            def __init__(self, fname):        # 文件名        self.fname = fname        # 是否被阅读        self.flag = None        self._info = None        self._page = 0        self.get_meta_data(self.fname)

    def __eq__(self, other):        if hasattr(other, 'fname'):            return self.fname == other.fname        return False        

同时阅读

通过内部维护一个 read_list 列表来实现同时阅读多本书。列表储存 book 对象,每个 book 对象都有一个 page 属性。这样,我们的程序就能记住每本书被翻到的页数了。

第二行代码,是对 read_list 进行初始化。book.flag 用来判断这本书上次关闭前是否处于阅读的状态。如果是,我们就把它放在阅读列表中。

self.read_list = [None]self.read_list.extend(book for book in self.booklist if book.flag)self.read_list.extend(book for book in self.booklist if book.flag)

左键翻页

我们重写 MyArea 类的 mousePressEvent 方法。event.pos() 函数用来获取鼠标的坐标,x() 用来获取横坐标。

width 为 MyArea 区域的宽度,如果点击鼠标左键,且鼠标位置的横坐标小于 1/3 区域宽度,那么向前翻页;大于 2/3 区域宽度,那么向后翻页。

# 鼠标左键翻页def mousePressEvent(self, event):    pos = event.pos().x()    width = self.size().width()    if event.button() == Qt.LeftButton:        if pos > width * 2 / 3:            self.right()        elif pos < width / 3:            self.left()def mousePressEvent(self, event):    pos = event.pos().x()    width = self.size().width()    if event.button() == Qt.LeftButton:        if pos > width * 2 / 3:            self.right()        elif pos < width / 3:            self.left()

sqlite3

sqlite3 是轻量型本地数据库,具有无服务器、零配置、速度快等特点。

PyReadon 启动时,会从数据库中读取图书信息。read_db 函数主要执行以下功能:

如果路径中不存在 PDF.db 数据库,那么就新建 PDF.db 数据库,并且创建一个 book_info 表格,该表格拥有三个属性 path, page, flag;

从 book_info 表格中读取数据,并创建 book 对象来接收这些数据,最后通过 yield 函数返回 book 对象。

book_db = 'PDF.db'book_info = namedtuple('info',  'path page flag')def read_db():    # 将路径更改为该文件所处路径    os.chdir(os.path.dirname(os.path.realpath(__file__)))    if not os.path.exists(book_db):        conn = sqlite3.connect(book_db)        conn.execute("CREATE TABLE book_info(path, page, flag)")        conn.close()    conn = sqlite3.connect(book_db)    for row in conn.execute('SELECT * FROM book_info'):        info = book_info(*row)        book = Book(info.path)        book.page = info.page        book.flag = info.flag        yield book    conn.close()  book_info = namedtuple('info',  'path page flag')

def read_db():    # 将路径更改为该文件所处路径    os.chdir(os.path.dirname(os.path.realpath(__file__)))    if not os.path.exists(book_db):        conn = sqlite3.connect(book_db)        conn.execute("CREATE TABLE book_info(path, page, flag)")        conn.close()    conn = sqlite3.connect(book_db)    for row in conn.execute('SELECT * FROM book_info'):        info = book_info(*row)        book = Book(info.path)        book.page = info.page        book.flag = info.flag        yield book

    conn.close()  

将数据存储到数据库中:

将书籍列表传给 save2db 函数,通过列表推导式创建 book 所在地址的列表。conn.executemany 函数将迭代生成器表达式,并获得 书籍地址、阅读页数、是否在阅读列表中 等信息,最后将这些信息存储在数据库中。

def save2db(booklist):    conn = sqlite3.connect(book_db)    conn.executemany("INSERT INTO book_info Values (?,?,?)",                ((book.fname, book.page, book.flag) for book in booklist))    conn.commit()    conn.close()    conn = sqlite3.connect(book_db)    conn.executemany("INSERT INTO book_info Values (?,?,?)",                ((book.fname, book.page, book.flag) for book in booklist))    conn.commit()    conn.close()

在进行存储数据之前,我们首先要将 book_info 数据库中的内容清空。

def remove_db():    conn = sqlite3.connect(book_db)    conn.execute('DELETE FROM book_info')    conn.commit()    conn.close()    conn = sqlite3.connect(book_db)    conn.execute('DELETE FROM book_info')    conn.commit()    conn.close()

查看书籍信息

书籍支持查看右键菜单,我们使用 QMessageBox.about 函数来显示书籍信息。

elif action == item3:    index = row_num * 8 + col_num    # 之后改成 book    book = self.booklist[index]    info = book.info    fmt = f'路径:{info.path}\n\n' \        f'格式:{info.format}\n\n' \        f'标题:{info.title}\n\n' \        f'作者:{info.author}\n\n' \        f'Creator:{info.creator}\n\n' \        f'Producer:{info.producer}\n\n'    QMessageBox.about(self, '文档信息', fmt)    index = row_num * 8 + col_num    # 之后改成 book    book = self.booklist[index]    info = book.info    fmt = f'路径:{info.path}\n\n' \        f'格式:{info.format}\n\n' \        f'标题:{info.title}\n\n' \        f'作者:{info.author}\n\n' \        f'Creator:{info.creator}\n\n' \        f'Producer:{info.producer}\n\n'

    QMessageBox.about(self, '文档信息', fmt)

弹窗

通过 Qt Designer 设计了一个弹窗,并与主程序绑定:

info 即为弹窗,点击工具栏中的信息栏时会弹出窗口。

info = Info()reader.infobar.triggered.connect(info.show)

以上就是本文的全部内容了,觉得不错的朋友可以点赞、或者转发支持,源代码已经上传到到我的 Github :https://github.com/cassieeric/Python-Application,感兴趣的小伙伴可以去学习一下。

------------------- End -------------------

往期精彩文章推荐:

欢迎点赞,留言,转发,转载,感谢大家的相伴与支持

想加入Python学习群请在后台回复【入群

万水千山总是情,点个【在看】行不行

500 行代码实现 PDF 阅读器相关推荐

  1. TinyRenderer(1):500行代码实现软件渲染器

    Lsson 0 从头开始 这是一个微型软件光栅化程序,如果您正在寻找一个微型软件光线跟踪器,则可以在此处找到它. 我的源代码无关紧要.阅读本文并实现自己的渲染器.只有当您经历所有细微的细节时,您才能了 ...

  2. java mqc系统开源代码_android PDF阅读器(开源) 暴强哦

    [实例简介] 看这个下载分数就知道了 源代码我已经运行过,能用,且运行很好.) [实例截图] [核心代码] a2d1802f-1d67-4dd9-a2f5-8b9297dd4b79 └── pdfDr ...

  3. Linux下一款可以使用命令行的pdf阅读器

    Zathura是linux下一款用命令行控制打pdf阅读器,并且基本打使用方法和vim很相似.对于喜欢键盘操作的用户来说的确是一个不错的选择. ubuntu下的安装命令: sudo apt-get i ...

  4. Foxit 修复PDF阅读器中的多个代码执行漏洞

     聚焦源代码安全,网罗国内外最新资讯! 编译:代码卫士 Foxit 阅读器更新版本,修复了可导致任意代码执行后果的多个释放后使用漏洞. Foxit 向用户提供了大量功能,包括通过 JavaScript ...

  5. 阅读器护眼模式android代码,pdf阅读器如何设置护眼模式?手机app原来也可以这么强大.docx...

    pdf阅读器如何设置护眼模式?手机app原来也可以这么强大.docx 还剩 6页未读, 继续阅读 下载文档到电脑,马上远离加班熬夜! 亲,喜欢就下载吧,价低环保! 内容要点: 轻快 PDF 阅读器 w ...

  6. c 语言500行小游戏代码,500行代码使用python写个微信小游戏飞机大战游戏.pdf

    500行行代代码码使使用用python写写个个微微信信小小游游戏戏飞飞机机大大战战游游戏戏 这篇文章主要介绍了500行代码使用python写个微信小游戏飞机大战游戏,本文通过实例代码给大家介绍的非常详 ...

  7. 打造全键盘操作的PDF阅读器

    其实我只想要一个非常简单的PDF阅读器,不要很花哨的功能,只要能够: 速度够快,不要翻一页等半天: 全键盘操作,不想在鼠标和键盘之间来回倒腾: 可以改变背景色,深夜的白光好刺眼: 自由旋转页面,有些P ...

  8. RAD PDF于Web浏览器的PDF阅读器

    RAD PDF 基于Web浏览器的PDF阅读器 作为功​​能最完备的基于HTML的PDF查看器,编辑器和ASP.NET的表单填充器,提供了灵活而强大的替代常规PDF解决方案.与Adobe Acroba ...

  9. 新版超简单的PDF阅读器

    原文地址:http://blog.csdn.net/BingHongChaZuoAn/article/details/52213611 本PDF阅读器的开发是基于android23版本的,其他版本暂时 ...

最新文章

  1. vue怎么截取时间年月_Vue + Element 获取标准时间、时间戳进行转换与操作(年月日)...
  2. Qt for Android 自定义启动页(解决启动页拉伸的问题)
  3. python中格式化_Python中格式化的两种方法
  4. 没学过编程能学python吗_我没学过编程,能否学会Python?
  5. 王道考研学习笔记IP数据报格式IP数据报分片(超详细)
  6. mysql与python交互
  7. 珞珈一号影像辐射定标软件操作方法
  8. android studio for android learning (十四) android的数据的存储sharedPreferences
  9. Linux paste命令
  10. 从条件概率到贝叶斯公式
  11. 低功耗基础概念——Level Shifter cell补充
  12. 计算机二级考试office考试技巧,2017年计算机二级考试Office应试技巧
  13. 手机怎么查看视频的MD5
  14. python numpy逆_python-使用numpy的矩阵逆
  15. 60分钟搞定JAVA加解密
  16. JavaScript测试工具对决:Sinon.js vs testdouble.js
  17. python django面试题(第八章)
  18. ng bootstrap css,Angular2学习笔记-ng bootstrap中motal组件使用
  19. Spring5的WebClient使用详解
  20. 使用DOSBox-X安装使用方法及打开QBasic

热门文章

  1. 广电用户画像分析之根据客户消费内容添加标签
  2. 怎样把python和pip加到环境变量,然后可以在cmd里面启动
  3. 【大学生软件测试基础】历年学生信息查询界面 - 正交表
  4. 《2011-2012年中国嵌入式开发从业…
  5. 《Java基础入门第2版》--黑马程序员 课后答案及其详解 第7章 I/O流
  6. zedgraph控件的一些比较有用的属性(转)
  7. VBS语言错误提示:未结束的字符串常量(800A0409)和语句未结束(800A0401)
  8. asp.net Code学习一(vs code跨平台软件操作)
  9. 无法打开项目文件。 无法找到 .NET SDK。请检查确保已安装此项且 global.json 中指定的版本(如有)与所安装的版本相匹配
  10. Instantiate(生成)某重载 欧拉角 OnTriggerEnter复习 相撞2 unity笔记8