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>