Electron creating and managing windows
In Electron, windows (Window) are the core medium for interaction between the application and the user.
All visible interfaces run onRenderer Processand the creation and control of these windows is handled byMain Processresponsible.
Creating and managing windows
Electron throughBrowserWindowclass to create windows.
In the main process, a new window is defined in the following way:
Example
let mainWindow = new BrowserWindow({
width: 1200,
height: 800,
show: false, // Wait until the page is ready before displaying
webPreferences: {
preload: path.join(__dirname, 'preload.js'),
},
})
BrowserWindow configuration options
width/height: Window width and height.minWidth/minHeight: Minimum size limit.resizable: Whether resizing is allowed.fullscreen/fullscreenable: Whether to go fullscreen.frame: Whether to show the native title bar (often disabled when using a custom title bar).transparent: Transparent window (can achieve effects such as frosted glass, floating, etc.).alwaysOnTop: Whether the window is always on top.
Window size, position, and state
The window state can be controlled via the API:
mainWindow.maximize() // 最大化
mainWindow.minimize() // 最小化
mainWindow.restore() // 还原
mainWindow.setBounds({ x: 100, y: 100, width: 800, height: 600 }) // 调整位置和大小
You can also listen for window changes:
mainWindow.on('resize', () => console.log('窗口尺寸变化'))
mainWindow.on('move', () => console.log('窗口移动'))
Frameless windows and custom title bar
Settingsframe: falseAfterward, you can customize the title bar area and simulate dragging using CSS and JS:
.titlebar {
-webkit-app-region: drag;
}
Note that non-draggable areas (such as buttons) should be added with:
.titlebar {
-webkit-app-region: drag;
}
Window event listening
mainWindow.on('close', (e) => {
e.preventDefault()
mainWindow.hide()
})
Common events include:
ready-to-show: The page has finished loading and can be displayed safely.focus/blur: The window gains or loses focus.closed: The window has been destroyed.
Loading page content
Electron windows can load local HTML files or remote websites.
Load local HTML files
mainWindow.loadFile('index.html')
Load remote URL
mainWindow.loadURL('https://example.com')
Using frontend frameworks
If you use modern frameworks such as Vue, React, or Angular, you can load the built static files into the window:
mainWindow.loadFile(path.join(__dirname, 'dist/index.html'))
Or load a local service in development mode:
mainWindow.loadURL('http://localhost:5173')
Inter-window communication
In multi-window applications, you may need to pass data between windows or control behavior.
Parent-child window relationship
Can be specified when creating a new windowparent:
let child = new BrowserWindow({
parent: mainWindow,
modal: true, // 模态窗口
width: 400,
height: 300,
})
When the parent window is closed, child windows will also close automatically.
Multi-window data sharing
You can use the main process as an intermediary to pass data between different renderer processes, or use global objects oripcMain / ipcRenderer。
Window message passing
The main process can directly operate on the target window:
child.webContents.send('update-data', someData)
Receive in the child window:
const { ipcRenderer } = require('electron')
ipcRenderer.on('update-data', (event, data) => {
console.log(data)
})
Interface optimization
Splash Screen
When the main window loads slowly, you can first display a lightweight splash window:
const splash = new BrowserWindow({ width: 400, height: 300, frame: false })
splash.loadFile('splash.html')
mainWindow.once('ready-to-show', () => {
splash.close()
mainWindow.show()
})
Window display optimization
Common techniques to prevent white-screen flickering include:
- Usage
show: falseCreate a window, and after loading is complete,show()。 - Set the background color on the rendered page.
- Preload resources (icons, fonts, styles).
Techniques to prevent flickering
- Enable GPU acceleration or disable hardware acceleration (depending on the situation).
- Avoid complex animations or gradients in CSS.
- Use double-buffered rendering to reduce drawing jitter.
Multi-window Electron application (including splash page, main interface, and child windows)
Directory structure
my-electron-app/ ├── package.json ├── main.js # 主进程入口 ├── preload.js # 预加载脚本 ├── splash.html # 启动画面 ├── index.html # 主窗口页面 ├── child.html # 子窗口页面 └── renderer.js # 渲染进程逻辑
main.js (main process)
Example
const path = require('path')
let mainWindow, splash, childWindow
function createSplash() {
splash = new BrowserWindow({
width: 400,
height: 300,
frame: false,
transparent: true,
alwaysOnTop: true,
})
splash.loadFile('splash.html')
}
function createMainWindow() {
mainWindow = new BrowserWindow({
width: 1200,
height: 800,
show: false,
webPreferences: {
preload: path.join(__dirname, 'preload.js'),
},
})
mainWindow.loadFile('index.html')
// Display after page load completes
mainWindow.once('ready-to-show', () => {
if (splash) splash.close()
mainWindow.show()
})
mainWindow.on('closed', () => (mainWindow = null))
}
function createChildWindow() {
childWindow = new BrowserWindow({
parent: mainWindow,
modal: true,
width: 400,
height: 300,
webPreferences: {
preload: path.join(__dirname, 'preload.js'),
},
})
childWindow.loadFile('child.html')
}
// Inter-process communication
ipcMain.on('open-child', () => {
if (!childWindow) createChildWindow()
})
ipcMain.handle('get-app-info', () => {
return {
name: app.getName(),
version: app.getVersion(),
}
})
app.on('ready', () => {
createSplash()
setTimeout(() => createMainWindow(), 1500)
})
app.on('window-all-closed', () => {
if (process.platform !== 'darwin') app.quit()
})
preload.js(preload script)
const { contextBridge, ipcRenderer } = require('electron')
contextBridge.exposeInMainWorld('electronAPI', {
openChild: () => ipcRenderer.send('open-child'),
getAppInfo: () => ipcRenderer.invoke('get-app-info'),
})
index.html (main window)
Example
<html lang="zh">
<head>
<meta charset="UTF-8" />
<title>main window</title>
<style>
body { font-family: sans-serif; text-align: center; margin-top: 100px; }
button { padding: 10px 20px; font-size: 16px; cursor: pointer; }
</style>
</head>
<body>
<h1>Welcome to Electron Applications</h1>
<p id="info"></p>
<button id="open">Open subwindow</button>
<script src="renderer.js"></script>
</body>
</html>
child.html (child window)
Example
<html lang="zh">
<head>
<meta charset="UTF-8" />
<title>child window</title>
<style>
body { font-family: sans-serif; text-align: center; margin-top: 100px; }
</style>
</head>
<body>
<h2>This is a child window</h2>
<p>Can receive commands from the main window</p>
</body>
</html>
splash.html (Splash Screen)
Example
<html lang="zh">
<head>
<meta charset="UTF-8" />
<title>Loading...</title>
<style>
body {
display: flex;
justify-content: center;
align-items: center;
height: 100vh;
background: linear-gradient(135deg, #8EC5FC, #E0C3FC);
font-family: sans-serif;
}
h1 {
font-size: 28px;
color: #333;
}
</style>
</head>
<body>
<h1>Application is starting, please wait...</h1>
</body>
</html>
renderer.js (render logic)
Example
const btn = document.getElementById('open')
// Display application info
window.electronAPI.getAppInfo().then((appInfo) => {
info.textContent =`Application name:${appInfo.name}| Version: ${appInfo.version}`
})
// Open child window
btn.addEventListener('click', () => {
window.electronAPI.openChild()
})
The process after running is as follows:
- Show at startupSplash screen(
splash.html)。 - After loading is complete, automatically close the splash page and displaymain window。
- The main window can be opened via a buttonchild window, demonstrating IPC communication functionality.
- The main window usesPreload securely exposes APIs, preventing direct access to Node.js.
- All windows useEvent listening、Delayed displayand other optimization strategies to avoid white screens and flickering.