In questa guida, costruiremo un’applicazione per i promemoria in Electron, vedremo argomenti come le finestre multiple e l’interscambio di dati tra finestre.
Index
Prerequisiti | Sviluppo app Electron
Do per scontato che hai delle conoscenze di base di Javascript ed HTML/CSS:
Conoscenza base di Electron
Setup del progetto | Sviluppo app Electron
I prossimi step sono necessari all’avvio della tua prima applicazione Electron
1. Crea una cartella dedicata al progetto
2. All’interno della cartella appena creata, con il comando npm init
andiamo a creare il file package.json di configurazione.
3. Installa Electron con il comandonpm install --save-dev electron
.
4. Sempre da terminale, npm install
.
Questo è il mio package.json
(ho fatto una modifica alle righe 6, 7, 8 per introdurre il comando da lanciare da terminale per l’avvio dell’applicazione)
Creazione del file index.js
A questo punto, dobbiamo andare a creare il file index.js che inizierà a contenere la parte logica dell’applicazione
const electron = require('electron'); const { app, BrowserWindow } = electron; let mainWindow; app.on('ready', () = { mainWindow = new BrowserWindow({}) })
Creazione del file main.html
<head> </head> <body> <h1>Promemoria</h1> </body>
Collegamento della view con il file index.js
Non resta che collegare la view alla logica dell’applicazione, otterremo dunque:
const electron = require('electron'); const { app, BrowserWindow} = electron; let mainWindow; app.on('ready', () => { mainWindow = new BrowserWindow({}); mainWindow.loadURL(`file://${__dirname}/main.html`); });
npm start
Infine, facciamo partire l’applicazione, da terminale, npm start
(ho fatto una minima modifica al file index.html)
Se vuoi rimuovere la barra dei menu dall’App Electron, puoi utilizzare
mainWindow.setMenuBarVisibility(false)
All’interno del file index.js
Per andare a realizzare un menu personalizzato, occorre innanzitutto importare il modulo dedicato
const { app, BrowserWindow, Menu } = electron;
per la definizione delle varie voci di menu, possimo iniziare dalla base
const menuTemplate = [ { label: 'FIle' } ];
il file index.js aggiornato risulterà quindi
const electron = require('electron'); const { app, BrowserWindow, Menu } = electron; let mainWindow; app.on('ready', () => { mainWindow = new BrowserWindow({}); mainWindow.loadURL(`file://${__dirname}/main.html`); //mainWindow.setMenuBarVisibility(false) const mainMenu = Menu.buildFromTemplate(menuTemplate); Menu.setApplicationMenu(mainMenu); }); const menuTemplate = [ { label: 'FIle' } ];
procediamo ora con l’aggiungere le funzioni del menu di cui necessita l’applicazione, aggiungiamo dunque la proprietà submenu
const menuTemplate = [ { label: 'FIle', submenu: [ { label: 'Nuovo promemoria' } ] } ];
se vi trovate su mac, molto probabilmente, vi troverete a visualizzare sotto la voce electron l’aggiunta del nuovo promemoria, ma noi vogliamo che tale voce appaia sotto file, vediamo come sia possibile avere ciò
if(process.platform === 'darwin') { menuTemplate.unshift({}); }
abbiamo aggiunto un’istruzione che individua il sistema operativo ed in base al risultato rimuove o lascia l’istruzione, potete accedere ai comandi node da terminale, digitando node e premendo invio, successivamente, per individuare il sistema operativo, sarà sufficente dare l’istruzione process.platform
creiamo ora la voce di menu che consente di chiudere l’applicazione, basterà aggiungere un’altro oggetto, avremo quindi
const menuTemplate = [ { label: 'FIle', submenu: [ { label: 'Nuovo promemoria' }, { label: 'chiudi'} ] } ];
ora colleghiamo all’oggetto appena creato un’evento di click per consentire la chiusura dell’applicazione
const menuTemplate = [ { label: 'FIle', submenu: [ { label: 'Nuovo promemoria' }, { label: 'chiudi', click(){ app.quit(); } } ] } ];
al click su chiudi, l’applicazione verrà chiusa immediatamente
possiamo anche utilizzare delle combinazioni di tasti per chiudere l’applicazione o per fare quello che vogliamo,
aggiungiamo la proprietà accelerator e distinguamo i comandi in base al sistema operativo dell’utente
const menuTemplate = [ { label: 'FIle', submenu: [ { label: 'Nuovo promemoria' }, { label: 'chiudi', accelerator: (() => { if(process.platform === 'darwin') { return 'Command+Q'; } else { return 'Ctrl+Q'; } })(), click(){ app.quit(); } } ] } ];
vediamo come utilizzare l’operatore ternario per ottenere la stessa cosa
const menuTemplate = [ { label: 'FIle', submenu: [ { label: 'Nuovo promemoria' }, { label: 'chiudi', accelerator: process.platform === 'darwin' ? 'Command+Q' : 'Ctrl+Q', click(){ app.quit(); } } ] } ];
Realizzazione del progetto | Sviluppo app Electron
Abbiamo completato il setup iniziale dell’applicazione, ora dedichiamoci alle funzioni
Creiamo una finestra per l’aggiunta di promemoria
Definiamo quindi una variabile ed una funzione che si innesca al verificarsi dell’evento click sul pulsante
function createAddWindow(){ addWindow = new BrowserWindow({ width: 300, height: 200, title: 'Aggiungi Nuovo Promemoria' }); }
definiamo l’evento di click
const menuTemplate = [ { label: 'FIle', submenu: [ { label: 'Nuovo promemoria', click(){ createAddWindow(); } }, { label: 'chiudi', accelerator: process.platform === 'darwin' ? 'Command+Q' : 'Ctrl+Q', click(){ app.quit(); } } ] } ];
Creiamo l’interfaccia per l’aggiunta di promemoria
Ora ci dedicheremo alla creazione dell’interfaccia che consente all’utente di inserire nuovi promemoria ed a noi di acquisire il dato e di gestirlo.
Creiamo dunque un nuovo file, add.html
<head> </head> <body> <form> <div> <label>Inserisci il promemoria</label> <input autofocus /> </div> <button type="submit">Aggiungi</button> </form> </body>
ora colleghiamo il file appena creato alla parte logica dell’applicazione
function createAddWindow(){ addWindow = new BrowserWindow({ width: 300, height: 200, title: 'Aggiungi Nuovo Promemoria' }); addWindow.loadURL(`file://${__dirname}/add.html`); }
Colleghiamo la chiusura dell’applicazione della finestra principale a quella dedicata all’aggiunta di promemoria
Se proviamo ad aprire la finestra dedicata all’aggiunta di promemoria e quindi a chiudere la finestra principale, ci accorgiamo che la finestra dedicata all’aggiunta di promemoria rimane aperta, questo perche ancora non abbiamo collegato l’evento di chiusura della finestra principale a quello della finestra per l’aggiunta dei promemoria.
app.on('ready', () => { mainWindow = new BrowserWindow({ width: 900, height: 700 }); mainWindow.loadURL(`file://${__dirname}/main.html`); mainWindow.on('closed', () => app.quit()); //mainWindow.setMenuBarVisibility(false) const mainMenu = Menu.buildFromTemplate(menuTemplate); Menu.setApplicationMenu(mainMenu); });
ora grazie all’istruzione appensa inserita, (mainWindow.on('closed', () => app.quit());
) al verificarsi della condizione, si chiuderà anche la finestra per l’aggiunta dei promemoria se aperta
Catturiamo l’input dell’utente
All’interno del file add.html dobbiamo catturare quello che l’utente inserisce nel campo di input, elaborarlo e spedirlo alla finestra principale dell’applicazione
<head> </head> <body> <form> <div> <label>Inserisci il promemoria</label> <input autofocus /> </div> <button type="submit">Aggiungi</button> </form> </body> <script> const electron = require('electron'); const { ipcRenderer } = electron; document.querySelector('form').addEventListener('submit', (event) => { event.preventDefault(); const value = document.querySelector('input').value; ipcRenderer.send('promemoria:add', value); }); </script>
ora quello che dobbiamo fare è catturare il dato e mostrarlo nella finestra principale, quindi, il file index.js diventerà:
const electron = require('electron'); const { app, BrowserWindow, Menu, ipcMain } = electron; let mainWindow; let addWindow; app.on('ready', () => { mainWindow = new BrowserWindow({ width: 900, height: 700, webPreferences: { nodeIntegration: true } }); mainWindow.loadURL(`file://${__dirname}/main.html`); mainWindow.on('closed', () => app.quit()); //mainWindow.setMenuBarVisibility(false) const mainMenu = Menu.buildFromTemplate(menuTemplate); Menu.setApplicationMenu(mainMenu); }); function createAddWindow(){ addWindow = new BrowserWindow({ width: 300, height: 200, title: 'Aggiungi Nuovo Promemoria', webPreferences: { nodeIntegration: true } }); addWindow.loadURL(`file://${__dirname}/add.html`); addWindow.on('closed', () => addWindow = null); } ipcMain.on('promemoria:add', (event, promemoria) => { mainWindow.webContents.send('promemoria:add', promemoria); addWindow.close(); addWindow = null; }) const menuTemplate = [ { label: 'FIle', submenu: [ { label: 'Nuovo promemoria', click(){ createAddWindow(); } }, { label: 'chiudi', accelerator: process.platform === 'darwin' ? 'Command+Q' : 'Ctrl+Q', click(){ app.quit(); } } ] } ]; if(process.platform === 'darwin') { menuTemplate.unshift({}); } if(process.env.NODE_ENV !== 'production'){ menuTemplate.push({ label: 'View', submenu: [ { label: 'Toggle Developer Tools', accelerator: process.platform === 'darwin' ? 'Command+Alt+I' : 'Ctrl+Shift+I', click(item, focusedWindow){ focusedWindow.toggleDevTools(); } } ] }) } // 'production' // 'development' // 'staging' // 'test'
Per mostrare quindi il dato, dobbiamo aggiornare anche il file main.html
<head> </head> <body> <h1>Promemoria</h1> <ul></ul> <script> const electron = require('electron'); const { ipcRenderer } = electron; ipcRenderer.on('promemoria:add', (event, promemoria) => { const li = document.createElement('li'); const text = document.createTextNode(promemoria); li.appendChild(text); document.querySelector('ul').appendChild(li); }) </script> </body>
Abbiamo dunque creato una lista e dentro stampiamo i dati che arrivano dall’input dell’utente.