Multi window - PublicVar/electron-wiki GitHub Wiki
It's easier to create single window app using angular, react, etc. You don't need to worry about communicating with different windows, processes, etc.
But, let's try to create an app with several windows.
Before starting we have to understand 2 concepts Main process and Renderer process.
Electron has 2 types of processes.
- The Main process is responsible for interacting with the native GUI of your operating system and creates the GUI of your application (your application windows)
- The Renderer process is your html (with js, css included) rendered file, the window. It's the Main process that created the renderer process
The different windows (rendered processes) can't communicate directly between themselves. Indeed, a window can't have the instance of the future created window.
This is the reason why we have to go through the Main process to dispatch the messages.
To do that we use ipcMain and ipcRenderer. it's 2 objects instances of EventEmitter. As you can guess, we will use some events and listeners.
To dispatch an event from a window to the main process or to listen some events coming from the Main process, we use ipcRenderer. And from the Main process to listen or to dispatch event to rendered windows we use ipcMain.
Let's create an app with 2 windows. our app.js (electron entry point) look like this:
//app.js
const electron = require('electron')
const app = electron.app
const BrowserWindow = electron.BrowserWindow
const ipcMain = electron.ipcMain;
const path = require('path')
const url = require('url')
let mainWindow
let secondWindow
function createWindow () {
// Create 1st window
mainWindow = new BrowserWindow({width: 800, height: 600})
mainWindow.loadURL(url.format({
pathname: path.join(__dirname, 'mainWindow.html'),
protocol: 'file:',
slashes: true
}))
mainWindow.webContents.openDevTools()
mainWindow.on('closed', function () {
mainWindow = null
})
//Create 2nd window
secondWindow = new BrowserWindow({
width: 75,
height: 500,
show: false
})
secondWindow.setAlwaysOnTop(true)
secondWindow.loadURL(url.format({
pathname: path.join(__dirname, 'second.html'),
protocol: 'file:',
slashes: true
}))
}
app.on('ready', createWindow)
app.on('window-all-closed', function () {
if (process.platform !== 'darwin') {
app.quit()
}
})
app.on('activate', function () {
if (mainWindow === null) {
createWindow()
}
})
//Listen to 'show-second' event from rendered process
ipcMain.on('show-second',(event, arg)=>{
secondWindow.show()
})
As you can see, we created 2 windows mainWindow
and secondWindow
. The secondWindow
is not visible when the app starts :
//app.js
//...some codes
secondWindow = new BrowserWindow({
width: 75,
height: 500,
show: false
})
//...some codes
We want, when we click on a button in the mainWindow
it displays the secondWindow
.
Let's take a look in our mainWindow
html file and see the button and the code that allows us to communicate with the Main process.
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>Hello World!</title>
<link rel="stylesheet" type="text/css" href="css/main.css">
</head>
<body>
<button type="button" onclick="show()">Show second window</button>
</body>
<script>
const {ipcRenderer} = require('electron')
function show(){
ipcRenderer.send('show-second'); //dispatch the event 'show-second' to the main process
}
</script>
</html>
Note: for the example the event code is directly into the html file but it's better to put the code in a seperate js file and linked in the html files
If you look back to our app.js code you will notice that we already have the listener in the Main process:
//app.js
const ipcMain = electron.ipcMain;
//...some codes
//Listen to 'show-second' event from rendered process
ipcMain.on('show-second',(event, arg)=>{
secondWindow.show()//Show the second window
})
You have to do something a little bit different. You have to send the event throught the webContents
of the renderer process :
//Sending a changing color event from the main process to the secondWidow
ipcMain.on('color',(event, color)=>{
secondWindow.webContents.send('newColor',color)
})
To sum up, the windows (rendered process) can't communicate directly between themselves. They had to pass through the Main process.
Build a mini drawing app (HTML, CSS, javascript) with 2 different windows:
- One for the main drawing area
- Another one for the toolbox (color selector of the pencil, size selector, etc.)
If you don't know where to start, you can take a look at this tutorial CREATE A DRAWING APP WITH HTML5 CANVAS AND JAVASCRIPT