Finestre Multiple e Gestione Focus
Le applicazioni Electron possono avere più finestre aperte contemporaneamente, ognuna con il proprio Renderer Process. Gestire correttamente le finestre multiple è essenziale per applicazioni complesse.
Creare Finestre Multiple
const { app, BrowserWindow } = require('electron');
const path = require('node:path');
let mainWindow;
let settingsWindow;
function createMainWindow() {
mainWindow = new BrowserWindow({
width: 1200,
height: 800,
webPreferences: {
preload: path.join(__dirname, 'preload.js'),
},
});
mainWindow.loadFile('index.html');
mainWindow.on('closed', () => {
mainWindow = null;
});
}
function createSettingsWindow() {
// Evita di aprire più finestre settings
if (settingsWindow && !settingsWindow.isDestroyed()) {
settingsWindow.focus();
return;
}
settingsWindow = new BrowserWindow({
width: 600,
height: 400,
parent: mainWindow, // Finestra genitore
webPreferences: {
preload: path.join(__dirname, 'preload.js'),
},
});
settingsWindow.loadFile('settings.html');
settingsWindow.on('closed', () => {
settingsWindow = null;
});
}
Pattern Singleton per Finestre
Per assicurarsi che una finestra venga creata una sola volta:
const windows = new Map();
function getOrCreateWindow(name, options, filePath) {
// Se la finestra esiste già, portala in primo piano
if (windows.has(name)) {
const existingWindow = windows.get(name);
if (!existingWindow.isDestroyed()) {
existingWindow.focus();
return existingWindow;
}
}
// Crea una nuova finestra
const win = new BrowserWindow({
...options,
webPreferences: {
preload: path.join(__dirname, 'preload.js'),
...options.webPreferences,
},
});
win.loadFile(filePath);
win.on('closed', () => {
windows.delete(name);
});
windows.set(name, win);
return win;
}
// Uso
getOrCreateWindow('settings', { width: 600, height: 400 }, 'settings.html');
getOrCreateWindow('about', { width: 400, height: 300 }, 'about.html');
Finestre Figlie (Child Windows)
Una finestra figlia è legata alla finestra genitore: si muove con essa e viene chiusa quando il genitore viene chiuso.
function createChildWindow() {
const child = new BrowserWindow({
width: 500,
height: 400,
parent: mainWindow, // Lega alla finestra principale
webPreferences: {
preload: path.join(__dirname, 'preload.js'),
},
});
child.loadFile('child.html');
return child;
}
Gestione del Focus
// Portare una finestra in primo piano
win.focus();
// Verificare il focus
if (win.isFocused()) {
console.log('La finestra ha il focus');
}
// Ascoltare eventi di focus
win.on('focus', () => {
console.log('Focus acquisito');
// Aggiorna il menu, la barra del titolo, etc.
});
win.on('blur', () => {
console.log('Focus perso');
});
// Ottenere la finestra con il focus
const focused = BrowserWindow.getFocusedWindow();
Comunicazione tra Finestre
Le finestre comunicano tra loro passando dal Main Process:
// main.js
const { ipcMain, BrowserWindow } = require('electron');
// Broadcast a tutte le finestre
function broadcastToAll(channel, data) {
BrowserWindow.getAllWindows().forEach((win) => {
if (!win.isDestroyed()) {
win.webContents.send(channel, data);
}
});
}
// La finestra settings invia un aggiornamento
ipcMain.on('settings:changed', (_event, settings) => {
// Inoltra a tutte le altre finestre
BrowserWindow.getAllWindows().forEach((win) => {
if (win.webContents !== _event.sender && !win.isDestroyed()) {
win.webContents.send('settings:updated', settings);
}
});
});
Chiudere Tutte le Finestre
// Chiudi tutte le finestre
BrowserWindow.getAllWindows().forEach((win) => {
win.close();
});
// Oppure forza la chiusura
BrowserWindow.getAllWindows().forEach((win) => {
win.destroy();
});
Ottenere la Lista delle Finestre
// Tutte le finestre aperte
const all = BrowserWindow.getAllWindows();
console.log(`${all.length} finestre aperte`);
// Iterare sulle finestre
all.forEach((win) => {
console.log(`Finestra #${win.id}: ${win.getTitle()}`);
});
// Trovare una finestra per ID
const win = BrowserWindow.fromId(2);