首页
学习
活动
专区
圈层
工具
发布
社区首页 >专栏 >基于ElectronEgg&Python,从零开始打造一款免费的PDF桌面工具

基于ElectronEgg&Python,从零开始打造一款免费的PDF桌面工具

作者头像
开源星探
发布2023-12-12 15:43:49
发布2023-12-12 15:43:49
1.4K0
举报
文章被收录于专栏:翩翩白衣少年翩翩白衣少年

昨天给大家介绍了 ElectronEgg 这款开源桌面应用开发框架。那么我们能不能搭配使用Python语言开发一套自己的工具箱呢!

这个毋庸置疑,接下来我们看看通过 ElectronEgg&Python 实现一个PDF工具箱。

前言

我们经常在使用一些好用的工具上,体验不是特别友好,很多采用命令行的方式。想有一个 GUI 界面,这样操作更方便,也便于其他不懂技术的同事使用。

现在市面上完全免费的PDF工具较少,要么收费,要么功能有诸多限制,在线的pdf工具也是一样的情况,有的在线是免费的,但是有些文档不便于上传到其他的服务器(安全敏感)。

预期实现的功能

  • • PDF合并
  • • PDF分割
  • • PDF提取图片
  • • PDF提取文本
  • • PDF转图片
  • • PDF加密
  • • PDF解密
  • • PDF添加水印
  • • PDF删除页面

技术选型

后端Python:

首先Python操作PDF的第三方API采用的是 pymupdf 库实现的。这个具体使用方法可以自行搜索,或者后续小编另写一篇文章进行介绍。

当然有条件有能力的朋友也可以使用纯Python独有的GUI库实现,比如近期文章中介绍的nicegui 开发一个界面很方便,不依赖ElectronEgg框架也是可以的。

使用Python实现功能之后,然后通过 nuitkaPython 文件打包成一个可执行文件,通过 ElectronEgg 进行调用。

前端ElectronEgg

前端GUI页面主要使用 Electron + Vue3 实现,前端和后端的通信主要使用 Node 中的 child_process 实现, 前端页面的通信使用 IPC 实现。

主要使用技术有

  • • nodejs
  • • electron
  • • vue
  • • vue-router
  • • pinia
  • • naiveui
  • • python
  • • pymupdf
  • • nuitkia 打包工具

IPC通信

ElectronEgg 中为了安全问题,不可以直接在渲染进程中调用 Nodejs中的相关操作。 默认情况下,渲染器进程没有权限访问 Node.js 和 Electron 模块。 作为应用开发者,您需要使用 contextBridge API 来选择要从预加载脚本中暴露哪些 API。

例:通过系统的默认应用打开浏览PDF文件

渲染器进程到主进程(单向)

单向通信只是渲染进程发消息到主进程,不需要主进程的返回信息。

1、在主线程中通过 ipcMain.on 监听事件

index.ts 主进程中加载脚本,设置事件监听

代码语言:javascript
复制
import { app, dialog, ipcMain, shell } from 'electron';
function createWindow () {  
    const mainWindow = new BrowserWindow({  
        webPreferences: {  
            preload: path.join(__dirname, 'preload.js')  
        }  
    })  
    mainWindow.loadFile('index.html')  
}

const openLocalPath = async (path:string) => {
   shell.openPath(path);
};

app.whenReady().then(() => {  
    ipcMain.on('shell:openPath', openLocalPath)  
    createWindow()  
})

2、通过预加载脚本暴露 ipcRenderer.send

要将消息发送到上面创建的监听器,您可以使用 ipcRenderer.send API。在您的预加载脚本中添加以下代码,向渲染器进程暴露一个全局的 window.electronAPI 变量。

代码语言:javascript
复制
const { contextBridge, ipcRenderer } = require('electron')

contextBridge.exposeInMainWorld('electronAPI', {
  openLocalPath: (path) => ipcRenderer.send('openLocalPath', path)
})

3、在渲染进程中调用

代码语言:javascript
复制
const setButton = document.getElementById('btn')
setButton.addEventListener('click', () => {
  window.electronAPI.openLocalPath(path)
})

例:打开文件夹获取里面的文件

渲染器进程到主进程(双向)

1、在主线程中通过 ipcMain.handle 监听事件

代码语言:javascript
复制
const openDirectory = async (): Promise<string> => {
    const { canceled, filePaths } = await dialog.showOpenDialog()
      if (!canceled) {
        return filePaths[0]
      }
};
    
ipcMain.handle(IPC_EVENT.EVENT_DIALOG_OPENFILE, async () =>  openDirectory(type));

2、通过预加载脚本暴露 ipcRenderer.invoke

代码语言:javascript
复制
contextBridge.exposeInMainWorld('electronAPI', {
  openDirectory: async (): Promise<string> => ipcRenderer.invoke(IPC_EVENT.EVENT_DIALOG_OPENFILE)
})

3、在渲染进程中调用

代码语言:javascript
复制
const handleOpenFile = async () => {
    const res = await window.electronAPI.openDirectory()
    // 获取打开的文件夹路径
}

例:主进程的错误信息发送给渲染进程,通过界面显示出来

主进程到渲染器进程

将消息从主进程发送到渲染器进程时,消息需要通过其 WebContents 实例发送到渲染器进程。 此 WebContents 实例包含一个 send方法,其使用方式与 ipcRenderer.send 相同。

1、在主线程中通过 mainWindow.webContents.send 发送事件

代码语言:javascript
复制
// 发送主进程的错误信息给渲染进程
mainWindow.webContents.send(IPC_EVENT.EVENT_PROCESS_ERROR, result)

2、通过预加载脚本暴露 ipcRenderer.on

代码语言:javascript
复制
export const listenError = (callback: (e: IpcRendererEvent, result: ProcessResult) => void) =>
    ipcRenderer.on(IPC_EVENT.EVENT_PROCESS_ERROR, callback);

3、在渲染进程中设置监听

代码语言:javascript
复制
onBeforeMount(() => {
    listenSuccess((__: IpcRendererEvent, _: ProcessResult) => {
        store.updateLoading(false);
        notification.success({ duration: 1500, content: '操作成功' });
    });
})

后端 和 前端 通信

通信的格式主要使用 json 字符串,通过 Nodejs 中的 child_process 调用 命令行,监听命令行的控制台的输出信息

代码语言:javascript
复制
import { spawn } from 'child_process';
//获取命令行的路径
const resourceUrl = join(dirname(app.getPath('exe')), '/resources/toolkit/');

//调用命令,传递相关的参数
child = spawn('toolkit', [cmd, config_json], {  cwd: resourceUrl });

//设置监听
child.stdout.on('data', (data) => {
    // 处理返回的数据
})

child.stderr.on('data', (data) => {
    // 错误信息
})

child.on('exit', (code) => {
    // 退出信息
})

python中主要向控制台输出信息

代码语言:javascript
复制
def process_done(cmd):
    print(json.dumps({'cmd': cmd, 'status': 'done'}))

打包可执行文件


主要是使用 nuitka 工具把 Python 文件打包成一个可执行文件

代码语言:javascript
复制
nuitka --standalone --output-dir=static toolkit.pyt

自动更新功能实现

软件的自动更新主要使用 electron-updater,主要的逻辑代码,在打包的配置文件中设置自己的更新服务器,将打包之后的文件放在自己的服务器中。

代码语言:javascript
复制
publish: [
      {
        provider: 'generic',
        url: 'https://www.examle.com/apps/pdf-toolkit',
      },
    ],

自动更新主要的监听事件

代码语言:javascript
复制
export const initUpdate = (win: BrowserWindow) => {
    autoUpdater.autoDownload = false;
    autoUpdater.autoInstallOnAppQuit = false;

      // 主进程监听检查更新事件
  ipcMain.on(IPC_EVENT.EVENT_UPDATE_CHECKFORUPDATE, () => {
    autoUpdater.checkForUpdates();
  });

  // 主进程监听开始下载事件
  ipcMain.on(IPC_EVENT.EVENT_UPDATE_DOWNLOADUPDATE, () => {
    autoUpdater.downloadUpdate();
  });

  // 检测到有可用的更新
  autoUpdater.on(IPC_EVENT.EVENT_UPDATE_UPDATEAVAILABLE, (info: UpdateInfo) => {
    win.webContents.send(IPC_EVENT.EVENT_UPDATE_UPDATEAVAILABLE, info);
  });

  // 下载更新进度
  autoUpdater.on(IPC_EVENT.EVENT_UPDATE_DOWNLOADPROGRESS, (progressObj: ProgressInfo) => {
    win.webContents.send(IPC_EVENT.EVENT_UPDATE_DOWNLOADPROGRESS, progressObj);
  });

  // 下载完成并安装
  autoUpdater.on(IPC_EVENT.EVENT_UPDATE_UPDATEDOWNLOADED, () => {
    autoUpdater.quitAndInstall();
    win.webContents.send(IPC_EVENT.EVENT_UPDATE_UPDATEDOWNLOADED);
  });
};

效果展示

写到最后

感谢您的一路陪伴,用代码构建世界,一起探索充满未知且奇妙的魔幻旅程。如果您对Python编程技巧、好玩实用的开源项目、行业新知趣事和各类技术干货等充满兴趣,那么不要错过未来我为大家奉上的精彩内容!点击关注,让您的探索学习之旅更加丰富多彩,我们一同成长,一同前行!🚀💻📚

求一键三连:点赞、转发、在看

本文参与 腾讯云自媒体同步曝光计划,分享自微信公众号。
原始发表:2023-12-12,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 Python兴趣圈 微信公众号,前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体同步曝光计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
目录
  • 前言
  • 预期实现的功能
  • 技术选型
    • 后端Python:
    • 前端ElectronEgg
  • IPC通信
    • 渲染器进程到主进程(单向)
    • 渲染器进程到主进程(双向)
    • 主进程到渲染器进程
  • 后端 和 前端 通信
  • 打包可执行文件
  • 自动更新功能实现
  • 效果展示
  • 写到最后
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档