7.2 文件对话框
Electron 提供了 dialog
模块用于显示文件打开和保存对话框。
7.2.1 显示文件打开对话框
主进程代码:
const { app, BrowserWindow, ipcMain, dialog } = require('electron');
const path = require('path');let mainWindow;const createMainWindow = () => {mainWindow = new BrowserWindow({width: 800,height: 600,webPreferences: {preload: path.join(__dirname, 'preload.js'),contextIsolation: true,nodeIntegration: false}});mainWindow.loadFile('index.html');mainWindow.webContents.openDevTools();mainWindow.on('closed', () => {mainWindow = null;});
};app.on('ready', createMainWindow);
app.on('window-all-closed', () => {if (process.platform !== 'darwin') {app.quit();}
});
app.on('activate', () => {if (mainWindow === null) {createMainWindow();}
});// 处理文件打开对话框请求
ipcMain.handle('open-file-dialog', async () => {const result = await dialog.showOpenDialog({properties: ['openFile']});if (result.canceled) {return { success: false };} else {return { success: true, filePaths: result.filePaths };}
});
预加载脚本(preload.js):
const { contextBridge, ipcRenderer } = require('electron');contextBridge.exposeInMainWorld('electronAPI', {openFileDialog: () => ipcRenderer.invoke('open-file-dialog')
});
渲染进程代码:
<!DOCTYPE html>
<html>
<head><title>File Dialog Example</title>
</head>
<body><h1>Open File Dialog Example</h1><button id="openFileDialog">Open File</button><p id="filePath"></p><script>document.getElementById('openFileDialog').addEventListener('click', async () => {const result = await window.electronAPI.openFileDialog();if (result.success) {document.getElementById('filePath').innerText = 'Selected file: ' + result.filePaths[0];} else {document.getElementById('filePath').innerText = 'No file selected';}});</script>
</body>
</html>
7.2.2 显示文件保存对话框
主进程代码:
const { app, BrowserWindow, dialog } = require("electron");
const { ipcMain } = require("electron");let mainWindow;function createWindow() {mainWindow = new BrowserWindow({width: 800,height: 600,webPreferences: {nodeIntegration: true,contextIsolation: true,preload: __dirname + "/preload.js",},});mainWindow.loadFile("index.html");
}app.whenReady().then(() => {createWindow();app.on("activate", function () {if (BrowserWindow.getAllWindows().length === 0) createWindow();});// 添加ipcMain.handle处理来自渲染进程的save-file请求ipcMain.handle("save-file", async (event, options) => {try {const result = await dialog.showSaveDialog(mainWindow, options);return result.filePath; // 直接返回文件路径给renderer,无需额外的reply} catch (err) {console.error("Error showing save dialog:", err);throw err;}});
});app.on("window-all-closed", function () {if (process.platform !== "darwin") app.quit();
});
预加载脚本(preload.js):
const { contextBridge, ipcRenderer } = require("electron");// 在preload中暴露安全的API给渲染进程
contextBridge.exposeInMainWorld("api", {saveFile: (options) => {return ipcRenderer.invoke("save-file", options);},
});
渲染进程代码:
document.getElementById("saveButton").addEventListener("click", async () => {const options = {title: "Save your File",defaultPath: "untitled.txt",filters: [{ name: "Text Files", extensions: ["txt"] },{ name: "All Files", extensions: ["*"] },],};try {const filePath = await window.api.saveFile(options);if (filePath) {console.log(`File will be saved at: ${filePath}`);// 这里可以添加保存文件的具体逻辑} else {console.log("User canceled the save operation.");}} catch (error) {console.error("Error during file save operation:", error);}
});
HTML代码:
<!DOCTYPE html>
<html lang="en"><head><meta charset="UTF-8" /><meta name="viewport" content="width=device-width, initial-scale=1.0" /><title>Save File Example</title></head><body><h1>Click to Save a File</h1><button id="saveButton">Save File</button><script src="./renderer.js"></script></body>
</html>