第4章:Electron主窗口与子窗口管理

4.1 创建主窗口

主窗口是 Electron 应用启动后显示的第一个窗口,通常用来承载应用的主界面。我们使用 BrowserWindow 类来创建主窗口。

4.1.1 创建主窗口的基础代码

// 引入 Electron 模块和 Node.js 的 path 模块
const { app, BrowserWindow } = require('electron');
const path = require('path');// 定义一个变量用于存储主窗口对象
let mainWindow;// 创建主窗口的函数
const createMainWindow = () => {// 实例化 BrowserWindow 对象mainWindow = new BrowserWindow({width: 800, // 窗口宽度height: 600, // 窗口高度webPreferences: {preload: path.join(__dirname, 'preload.js'), // 指定预加载脚本contextIsolation: true, // 启用上下文隔离nodeIntegration: false // 禁用 Node.js 集成}});// 加载主窗口的 HTML 文件mainWindow.loadFile('index.html');// 打开开发者工具(仅在开发阶段使用)mainWindow.webContents.openDevTools();// 监听主窗口的关闭事件mainWindow.on('closed', () => {// 当窗口被关闭时,将 mainWindow 设置为 nullmainWindow = null;});
};// 当 Electron 完成初始化并准备创建浏览器窗口时,调用 createMainWindow 函数
app.on('ready', createMainWindow);// 当所有窗口关闭时,退出应用(除非在 macOS 上)
app.on('window-all-closed', () => {if (process.platform !== 'darwin') {app.quit();}
});// 当应用被激活时(例如在 macOS 上单击应用图标),重新创建主窗口
app.on('activate', () => {if (mainWindow === null) {createMainWindow();}
});

4.2 创建子窗口

子窗口用于显示辅助内容或执行辅助任务。与主窗口类似,子窗口也是通过 BrowserWindow 类创建的。

4.2.1 创建子窗口的示例代码

// 创建子窗口的函数
const createChildWindow = () => {// 实例化 BrowserWindow 对象let childWindow = new BrowserWindow({parent: mainWindow, // 设置父窗口为主窗口modal: true, // 设置为模态窗口width: 400, // 窗口宽度height: 300, // 窗口高度webPreferences: {preload: path.join(__dirname, 'preload.js'), // 指定预加载脚本contextIsolation: true, // 启用上下文隔离nodeIntegration: false // 禁用 Node.js 集成}});// 加载子窗口的 HTML 文件childWindow.loadFile('child.html');// 监听子窗口的关闭事件childWindow.on('closed', () => {// 当窗口被关闭时,将 childWindow 设置为 nullchildWindow = null;});
};// 在主窗口创建完成后创建子窗口
app.on('ready', () => {createMainWindow();createChildWindow();
});

4.3 窗口间通信

通过 IPC 机制,主窗口和子窗口可以相互通信。这里使用 ipcMainipcRenderer 模块实现通信。

4.3.1 主窗口与子窗口之间的通信示例

主进程:

const { ipcMain } = require('electron');// 监听从渲染进程发送的消息
ipcMain.on('message-from-child', (event, arg) => {console.log('Received message from child:', arg);// 回复消息到渲染进程event.reply('reply-from-main', 'Message received by main process');
});

4.4 预加载脚本

预加载脚本在渲染进程加载前执行,允许在渲染器上下文中暴露自定义 API,并提供与主进程安全通信的桥梁。

4.4.1 创建预加载脚本

preload.js

const { contextBridge, ipcRenderer } = require('electron');// 使用 contextBridge 将安全的 API 暴露给渲染进程
contextBridge.exposeInMainWorld('electronAPI', {sendMessage: (message) => ipcRenderer.send('message-from-child', message),onReply: (callback) => ipcRenderer.on('reply-from-main', (event, args) => callback(args))
});

4.4.2 在渲染进程中使用预加载脚本

子窗口(渲染进程):

<!DOCTYPE html>
<html><head><title>Child Window</title></head><body><h1>Child Window</h1><button id="sendMessageBtn">Send Message to Main</button><script>// 使用预加载脚本暴露的 APIdocument.getElementById('sendMessageBtn').addEventListener('click', () => {window.electronAPI.sendMessage('Hello from child window');});window.electronAPI.onReply((message) => {console.log('Received reply from main:', message);});</script></body>
</html>

4.5 管理多个窗口

在复杂的应用中,可能需要同时管理多个窗口。可以通过存储窗口实例的数组或对象来实现这一点。

4.5.1 管理多个窗口的示例

const windows = {};// 创建子窗口的函数
const createChildWindow = (windowName) => {let childWindow = new BrowserWindow({parent: mainWindow,modal: true,width: 400,height: 300,webPreferences: {preload: path.join(__dirname, 'preload.js'),contextIsolation: true,nodeIntegration: false}});childWindow.loadFile('child.html');childWindow.on('closed', () => {// 当窗口被关闭时,从 windows 对象中删除对应的实例delete windows[windowName];});// 将窗口实例存储到 windows 对象中windows[windowName] = childWindow;
};// 创建多个子窗口
app.on('ready', () => {createMainWindow();createChildWindow('child1');createChildWindow('child2');
});

4.6 窗口的显示和隐藏

有时需要在应用中显示或隐藏窗口,而不是创建或销毁它们。

4.6.1 显示和隐藏窗口的示例

// 显示子窗口
const showChildWindow = (windowName) => {if (windows[windowName]) {windows[windowName].show();}
};// 隐藏子窗口
const hideChildWindow = (windowName) => {if (windows[windowName]) {windows[windowName].hide();}
};// 在主窗口创建完成后创建子窗口并演示显示和隐藏功能
app.on('ready', () => {createMainWindow();createChildWindow('child1');// 隐藏子窗口 child1hideChildWindow('child1');// 2 秒后显示子窗口 child1setTimeout(() => {showChildWindow('child1');}, 2000);
});

通过本章内容,你已经了解了如何在 Electron 中创建和管理主窗口及子窗口,包括如何进行窗口间通信、使用预加载脚本提高安全性、管理多个窗口以及显示和隐藏窗口的操作。在接下来的章节中,我们将进一步探讨如何实现更多高级功能和最佳实践,帮助你进一步掌握 Electron 开发。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/diannao/39435.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

【动态规划 前缀和】2478. 完美分割的方案数

本文涉及知识点 划分型dp 动态规划汇总 C算法&#xff1a;前缀和、前缀乘积、前缀异或的原理、源码及测试用例 包括课程视频 LeetCode 2478. 完美分割的方案数 给你一个字符串 s &#xff0c;每个字符是数字 ‘1’ 到 ‘9’ &#xff0c;再给你两个整数 k 和 minLength 。 如…

【C++ Primer Plus学习记录】指针和const

可以用两种不同的方式将const关键字用于指针。第一种方法是让指针指向一个常量对象&#xff0c;这样就可以防止使用该指针来修改所指向的值&#xff0c;第二种方法是将指针本身声明为常量&#xff0c;这样可以防止改变指针指向的位置。 首先&#xff0c;声明一个指向常量的指针…

前后端防重复提交(续)

前文介绍过前后端防重复提交的基本场景&#xff0c;简单的情况是只发起一个异步请求&#xff0c;如果有多个异步请求怎么操作呢&#xff1f;这个要分情况看下。 如果是后端服务器的接口支持一次传递多个申请&#xff0c;那么可以将任务放进数组中&#xff0c;发往后端。这是最好…

074、Python 关于实例方法、静态方法和类方法

在Python中&#xff0c;类可以定义三种类型的方法&#xff1a;实例方法、静态方法和类方法。每种方法都有其特定的用途和调用方式。 实例方法&#xff08;Instance Methods&#xff09; 定义&#xff1a;实例方法是绑定到类实例上的方法。它们必须有一个名为self的隐式第一个参…

golang 1.22特性之for loop

背景 go1.22版本 for loop每轮循环都生成新的变量. 原谅: https://tip.golang.org/doc/go1.22 Previously, the variables declared by a “for” loop were created once and updated by each iteration. In Go 1.22, each iteration of the loop creates new variables, to …

【C++11】自己封装RAII类,有哪些坑点?带你了解移动语义的真相

文章目录 一、持有资源的类定义移动构造函数的要点1.普通内置类型与std::move2.常见的容器与std::move3.结构体&#xff1a;4.智能指针与std::move 参考 一、持有资源的类定义移动构造函数的要点 1.普通内置类型与std::move 在C中&#xff0c;std::move 主要用于对象的移动语…

Wireshark - tshark支持iptables提供数据包

tshark现在的数据包获取方式有两种&#xff0c;分别是读文件、网口监听&#xff08;af-packet原始套接字&#xff09;。两种方式在包获取上&#xff0c;都是通过读文件的形式&#xff1b;存在文件io操作&#xff0c;在专门处理大流量的情境下&#xff0c; 我们复用wireshark去做…

Windows编程上

Windows编程[上] 一、Windows API1.控制台大小设置1.1 GetStdHandle1.2 SetConsoleWindowInfo1.3 SetConsoleScreenBufferSize1.4 SetConsoleTitle1.5 封装为Innks 2.控制台字体设置以及光标调整2.1 GetConsoleCursorInfo2.2 SetConsoleCursorPosition2.3 GetCurrentConsoleFon…

python如何输出list

直接输出list_a中的元素三种方法&#xff1a; list_a [1,2,3,313,1] 第一种 for i in range(len(list_a)):print(list_a[i]) 1 2 3 313 1 第二种 for i in list_a:print(i) 1 2 3 313 1 第三种&#xff0c;使用enumerate输出list_a方法&#xff1a; for i&#xff0c;j in enum…

Redis的使用(二)redis的命令总结

1.概述 这一小节&#xff0c;我们主要来研究一下redis的五大类型的基本使用&#xff0c;数据类型如下&#xff1a; redis我们接下来看一看这八种类型的基本使用。我们可以在redis的官网查询这些命令:Commands | Docs,同时我们也可以用help 数据类型查看命令的帮助文档。 2. 常…

数据结构 - C/C++ - 串

字符处理 C 特性 C语言中字符串存储在字符数组中&#xff0c;以空字符\0结束。 字符串常量&#xff0c;const char* str "Hello"&#xff0c;存储在只读的数据段中。 布局 字符串在内存中是字符连续存储的集合&#xff0c;最后一个字符为空字符(ASCII值为0)&…

opencascade AIS_InteractiveContext源码学习7 debug visualization

AIS_InteractiveContext 前言 交互上下文&#xff08;Interactive Context&#xff09;允许您在一个或多个视图器中管理交互对象的图形行为和选择。类方法使这一操作非常透明。需要记住的是&#xff0c;对于已经被交互上下文识别的交互对象&#xff0c;必须使用上下文方法进行…

【问题已解决】Vue管理后台,点击登录按钮,会发起两次网络请求(竟然是vscode Compile Hero编译插件导致的)

问题 VueElement UI 做的管理后台&#xff0c;点击登录按钮&#xff0c;发现 接口会连续掉两次&#xff0c;发起两次网络请求&#xff0c;但其他接口都是正常调用的&#xff0c;没有这个问题&#xff0c;并且登录按钮也加了loading&#xff0c;防止重复点击&#xff0c;于是开…

搜索引擎常用语法

引号 (" "): 用双引号将词组括起来&#xff0c;搜索引擎将返回包含完全相同短语的结果。 示例&#xff1a;"人工智能发展趋势" 减号 (-): 在关键词前加上减号可以排除包含特定词语的结果。 示例&#xff1a;人工智能 -机器学习&#xff08;排除包含 “机器…

朴素贝叶斯解密:sklearn中的分类器工作原理

&#x1f4da; 朴素贝叶斯解密&#xff1a;sklearn中的分类器工作原理 在机器学习领域&#xff0c;朴素贝叶斯分类器因其简单、高效而广受欢迎。特别是在处理大量特征数据时&#xff0c;朴素贝叶斯表现出了卓越的性能。scikit-learn&#xff08;简称sklearn&#xff09;是Pyth…

JavaMySQL 学习(基础)

目录 Java CMD Java发展 计算机存储规则 Java学习 switch新用法&#xff08;可以当做if来使用&#xff09; 数组定义 随机数 Java内存分配 MySQL MySQL概述 启动和停止 客户端连接 数据模型 关系型数据库 SQL SQL通用语法 SQL分类 DDL--数据定义语言 数据库…

浏览器开发者工具辅助爬虫开发

文章目录 浏览器开发者工具辅助爬虫开发打开开发者工具使用Network面板分析请求数据示例步骤&#xff1a; 使用Elements面板查看和修改DOM结构示例步骤&#xff1a; 使用Console面板调试JavaScript代码示例步骤&#xff1a;示例代码&#xff1a;1. 输出日志信息2. 输出对象信息…

Vue 与 React 区别

Vue.js和React是现代Web开发中两种非常流行的前端框架&#xff0c;两者在**核心概念、组件以及生态系统扩展性**等方面存在区别。具体分析如下&#xff1a; 1. **核心概念** - **Vue**&#xff1a;Vue是一个渐进式JavaScript框架&#xff0c;它致力于视图层&#xff0c;易于上手…

左值右值, 左值引用右值引用,完美转发

一. 左值和右值 左值: 可以取地址的对象 右值: 不可以取地址的对象 double x1.0, y 2.0; 1; // 字面量, 不可取地址, 是右值 x y; // 表达式返回值, 不可取地址, 是右值 max(x, y); // 传值返回函数的返回值 (非引用返回)总结就是: 根据是否可以取地址来区分是左值还…

线程池666666

1. 作用 线程池内部维护了多个工作线程&#xff0c;每个工作线程都会去任务队列中拿取任务并执行&#xff0c;当执行完一个任务后不是马上销毁&#xff0c;而是继续保留执行其它任务。显然&#xff0c;线程池提高了多线程的复用率&#xff0c;减少了创建和销毁线程的时间。 2…