python与Electron联合编程记录之五(进程间通信)

进程间通信

  进程间通信是Electron构建程序的关键之一,主要通过ipcMainipcRenderer 这两个模块来实现,通过开发人员定义的“通道”传递消息来进行通信。
  下面展示3个进程间通信的示例。

文件格式

  在项目初始化后并安装electron运行时后,在根目录下创建文件夹html、js,并在文件夹下分别创建index.html和render.js文件。在根目录下创建preload.js文件作为预加载文件。
  具体文件结构如下图所示,后面的案例都是按照这个格式:

1、渲染进程到主进程(单向)

  这里我们通过创建一个简单的程序展示如何从渲染进程发送消息到主进程,这种应用情况很多,比如点击网页中一个按钮发送一个改变窗口大小的消息,这个点击属于渲染进程中的消息,然后消息通过渲染进程发送到主进程,主进程接收到消息后来调整窗口的大小。

index.html

  首先我们先确定网页布局,建立两个按钮,一个按钮用于最大化窗口,设置为1280×768,另一个按钮用于最小化窗口,设置大小为800×600

<!DOCTYPE html>
<html>
<head>
  <meta charset="UTF-8">
  <!-- https://developer.mozilla.org/en-US/docs/Web/HTTP/CSP -->
  <meta content="default-src 'self'; script-src 'self'" http-equiv="Content-Security-Policy">
  <title>渲染进程到主进程(单向)!</title>
</head>
<body>
<div>
  <button id="btn_maximize" type="button">最大化窗口</button>
</div>
<div>
  <button id="btn_minimize" type="button">最小化窗口</button>
</div>
<script src="../js/renderer.js"></script>
</body>
</html>

preload.js

  然后我们在预加载脚本中通过contextBridge API向渲染进程暴露两个函数window_maximize和window_minimize,这两个函数通过ipcRenderer.send API信息通道给主进程发送消息,window_maximize和window_minimize分别用于最大化窗口和最小化窗口。

const { contextBridge, ipcRenderer } = require('electron')  
  
contextBridge.exposeInMainWorld('electronAPI', {  
  window_maximize: () => ipcRenderer.send('window-maximize'),  
  window_minimize: () => ipcRenderer.send('window-minimize')  
})

renderer.js

  下一步我们需要在渲染脚本中调用这两个函数,通过ipcRenderer.send发送信道消息给主进程。

document.getElementById('btn_maximize').addEventListener('click', () => {  
  window.electronAPI.window_maximize()  
});  
document.getElementById('btn_minimize').addEventListener('click', () => {  
  window.electronAPI.window_minimize()  
});

main.js

  主进程通过ipcMain.on API在window-maximizewindow-minimize两个通道上设置IPC监听器,接收到来自渲染进程的消息后,要对BrowserWindow窗口大小进行处理,改变窗口大小的函数为BrowserWindow.SetSize(),最大化窗口的宽高设置为1200×768,最小化窗口的宽高设置为800×600。

const {app, BrowserWindow, ipcMain} = require('electron')  
const path = require('path')  
  
function createWindow () {  
  const win = new BrowserWindow({  
  webPreferences: {  
  preload: path.join(__dirname, 'preload.js'),  
  }  
  })   
  ipcMain.on('window-maximize', (event) => {  
  win.setSize(1280,768)  
 })  
  ipcMain.on('window-minimize', (event) => {  
  win.setSize(800,600)  
 })  
  win.loadFile('html/index.html').then(()=>{})  
}  
  
app.whenReady().then(() => {  
  createWindow()  
  console.log(path.join(__dirname, 'preload.js'))  
  app.on('activate', function () {  
  if (BrowserWindow.getAllWindows().length === 0) createWindow()  
  })  
})  
  
app.on('window-all-closed', function () {  
  if (process.platform !== 'darwin') app.quit()  
})

  最终效果如下所示:
在这里插入图片描述

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

  这里我们通过继续更改上面的程序展示如何从渲染进程发送消息到主进程并等待返回结果,比如点击最大化或者最小化窗口按钮后,消息通过渲染进程发送到主进程,主进程接收到消息后来调整窗口的大小,等窗口调整完成后,主进程返回一个窗口调整状态显示在程序界面上。

index.html

  我们在上述第一部分网页界面的基础上加上一个output输出框,用于显示窗口状态,设置初始的输出内容为“初始为最小化”。

<!DOCTYPE html>  
<html>  
  <head>  
  <meta charset="UTF-8">  
 <title>渲染进程到主进程(双向)!</title>  
  </head>  
 <body>  
  <div>  
  <button id="btn_maximize" type="button">最大化窗口</button>  
  </div>  
 <div>  
  <button id="btn_minimize" type="button">最小化窗口</button>  
  </div>  
 <div>  
  窗口状态:<output id="window_identity">初始为最小化</output>  
  </div>  
 <script src="../js/renderer.js"></script>  
  </body>  
</html>

preload.js

  双向IPC可以通过ipcRenderer.invokeipcMain.handle 搭配使用来完成,我们将第一个案例中的ipcRenderer.on替换成ipcRenderer.invoke,这样就可以异步等待结果。

const { contextBridge, ipcRenderer } = require('electron')  
contextBridge.exposeInMainWorld('electronAPI', {  
  window_maximize: () => ipcRenderer.invoke('window-maximize'),  
  window_minimize: () => ipcRenderer.invoke('window-minimize')  
})

renderer.js

  这一步,我们在addEventListener的回调函数中利用获取预加载脚本中异步函数的返回值并通过innerText 函数显示到output组件当中。

document.getElementById('btn_maximize').addEventListener('click', async () => {  
  const window_identity = await window.electronAPI.window_maximize()  
  document.getElementById('window_identity').innerText = window_identity  
});  
document.getElementById('btn_minimize').addEventListener('click', async() => {  
  const window_identity = await window.electronAPI.window_minimize()  
  document.getElementById('window_identity').innerText = window_identity  
});

main.js

  将第一个案例中的ipcMain.on替换为ipcMain.handle,用来监听ipcRenderer.invoke发出的通道信息,执行窗口的大小,并返回窗口标识window_identity

const {app, BrowserWindow, ipcMain} = require('electron')  
const path = require('path')  
let win = null  
  
function createWindow () {  
  win = new BrowserWindow({  
  webPreferences: {  
  preload: path.join(__dirname, 'preload.js'),  
  }  
  })  
  win.loadFile('html/index.html').then(()=>{})  
}  
  
app.whenReady().then(() => {  
  const window_identity = "窗口最大化"  
  ipcMain.handle('window-maximize', async(event) => {  
  await win.setSize(1280,768)  
  return window_identity  
  })  
  ipcMain.handle('window-minimize', async(event) => {  
  const window_identity = "窗口最小化"  
  await win.setSize(800,600)  
  return window_identity  
  })  
  createWindow()  
  app.on('activate', function () {  
  if (BrowserWindow.getAllWindows().length === 0) createWindow()  
  })  
})  
  
app.on('window-all-closed', function () {  
  if (process.platform !== 'darwin') app.quit()  
})

  最终效果如下所示:
在这里插入图片描述

3、主进程到渲染器进程

  这里我们通过继续更改上面的程序展示如何从主进程发送消息到渲染进程,比如点击窗口右上角的最大化按钮后,会触发窗口的一个resize事件,通过一个if语句判断窗体是否未最大化,并把消息发送到渲染进程,渲染进程接收到消息后将窗体的最大化状态显示在程序界面的output里。

index.html

  这次网页里面只留一个output用来显示窗口的最大化状态。

<!DOCTYPE html>  
<html>  
  <head>  
  <meta charset="UTF-8">  
  <!-- https://developer.mozilla.org/en-US/docs/Web/HTTP/CSP -->  
  <meta http-equiv="Content-Security-Policy" content="default-src 'self'; script-src 'self'">  
 <title>主进程到渲染进程!</title>  
  </head>  
 <body>  
  <div>  
  窗口最大化状态:<output id="window_identity">未最大化</output>  
  </div>  
 <script src="../js/renderer.js"></script>  
  </body>  
</html>

preload.js

  通过ipcRenderer.on建立maximize-identity通道

const { contextBridge, ipcRenderer } = require('electron')  
contextBridge.exposeInMainWorld('electronAPI', {  
  show_maximize_identity: (listener) => ipcRenderer.on('maximize-identity',listener)  
})

renderer.js

  在渲染进程中将output标签的内容显示为从主进程接收到的值。

window.electronAPI.show_maximize_identity((event,value)=>{  
  document.getElementById('window_identity').innerText = value  
})

main.js

  在app.whenReady()事件中建立一个win.on事件用于监听窗体的resize事件,当窗体最大化时发送"窗口已最大化"消息,当窗体非最大化时发送"窗口未最大化"消息

const {app, BrowserWindow, ipcMain} = require('electron')  
const path = require('path')  
let win = null  
  
function createWindow () {  
  win = new BrowserWindow({  
  webPreferences: {  
  preload: path.join(__dirname, 'preload.js'),  
  }  
  })  
  win.webContents.openDevTools(); //打开调试工具  
  win.loadFile('html/index.html').then(()=>{})  
}  
  
app.whenReady().then(() => {  
  createWindow()  
  win.on('resize',()=>{  
  if (win.isMaximized()){  
  win.webContents.send('maximize-identity', "窗口已最大化")  
  }else{  
  win.webContents.send('maximize-identity', "窗口未最大化")  
  }  
  })  
  app.on('activate', function () {  
  if (BrowserWindow.getAllWindows().length === 0) createWindow()  
  })  
})  
  
app.on('window-all-closed', function () {  
  if (process.platform !== 'darwin') app.quit()  
})

  最终效果如下所示:
在这里插入图片描述

  • 2
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值