代码改变世界

electron 创建托盘应用

2019-08-04 19:10 龙恩0707 阅读(...) 评论(...) 编辑 收藏

在Electron中我们创建一个托盘需要如下几个文件:

1. main.js 用来存放应用代码。
2. 一张PNG格式的图片用作应用图标。
3. 一个package.json文件用来描述应用配置。

下面是我们项目的目录架构如下:

|--- electron-demo5
| |--- node_modules
| |--- app.css
| |--- app.js
| |--- main.js
| |--- icon@2x.png
| |--- index.html
| |--- package.json

index.html 是用来展示笔记的内容,如下html代码:

<html>
  <head>
    <title>tray-app-electron</title>
    <link href="./app.css" rel="stylesheet" />
  </head>
  <body>
    <h1 id="app"></h1>
    <div id="contents"></div>
    <script type="text/javascript" src="./app.js"></script>
  </body>
</html>

package.json 代码如下:

{
  "name": "tray-app-electron",
  "version": "1.0.0",
  "description": "",
  "main": "main.js",
  "scripts": {
    
  },
  "author": "kongzhi",
  "license": "ISC",
  "dependencies": {
    "electron": "^6.0.0"
  }
}

main.js 代码如下:

'use strict';

const { app, Menu, Tray, BrowserWindow } = require('electron')

let appIcon = null;
let mainWindow = null;

const notes = [
  {
    title: 'todo list',
    contents: '111111'
  },
  {
    title: 'xxxxx',
    contents: '2222'
  }
];

function displayNote (note) {
  // 使用 webContents API 向浏览器窗口发送数据来显示笔记内容
  mainWindow.webContents.send('displayNote', note);
}

function addNoteToMenu (note) {
  return {
    label: note.title,
    type: 'normal',
    click: () => {
      displayNote(note);
    }
  }
}

app.on('ready', () => {
  // 创建一个带图标的托盘应用
  appIcon = new Tray('icon@2x.png');

  // 为托盘应用创建上下文菜单,对笔记进行迭代并添加为菜单项
  let contextMenu = Menu.buildFromTemplate(notes.map(addNoteToMenu));
  appIcon.setToolTip('Notes app');

  // 将上下文菜单绑定到托盘应用上
  appIcon.setContextMenu(contextMenu);

  mainWindow = new BrowserWindow({
    width: 800,
    height: 600,
    webPreferences: {
      nodeIntegration: true
    }
  });
  // 添加如下代码 可以调试
  mainWindow.webContents.openDevTools();
  mainWindow.loadURL(`file://${__dirname}/index.html`);

  // 当应用视窗加载好后,默认显示第一个笔记内容
  mainWindow.webContents.on('dom-ready', () => {
    displayNote(notes[0]);
  });

});

如上代码就创建了一个托盘应用,以及它的菜单, 同时BrowserWindow负责显示笔记内容,当我们的菜单笔记项被单击的时候,就会调用我们的 app.js 代码如下的函数:

function displayNote(event, note) {
  document.getElementById("app").innerText = note.title;
  document.getElementById("contents").innerText = note.contents;
}

// Electron 的 ipcRenderer模块监听由后端进程触发的事件
const ipc = require('electron').ipcRenderer;

/*
 菜单项被单击或当应用加载的时候,ipcRenderer模块会接收到事件以及note对象并将其
 传递给 displayNote 函数
*/
ipc.on('displayNote', displayNote);

如上代码,会使用 electron中的ipcRenderer模块来接收displayNote事件以及由main进程传递给renderer进程的note对象。这样我们就可以在 BrowserWindow 进程中更新HTML内容了。

electron的ipcRenderer模块可以发送以及接收来自或传递给Electron main 进程的数据,在托盘应用上下文中,后端进程通过 web contents API将数据传递给浏览器视窗,因此, displayNote事件以及note对象由后端传递给前端,ipcRenderer则监听该事件。当事件触发的时候,ipcRenderer会获取到note对象并将其传递给负责将笔记内容插入到html的函数。

当我们运行 electron . 的时候,我们会在我们的mac系统顶部有一个图标,如下所示:

同时也会打开一个托盘这样的,如下图所示:

当我们点击图标的时候,它会有一个列表,如下图所示:

当我们点击 xxx 列表项的时候,托盘内容就会显示 xxxx 对应的内容了,如下图所示:

当我们切换到 todo list 列表的时候,就会显示 todo list 对应的内容了,如下图所示:

更多的系统托盘知识,请看官网API (https://electronjs.org/docs/api/tray)

github-demo 源码查看