Electron 如何创建模态窗口?
目录
- 前言
- 一、模态窗口
- 1.Web页面模态框
- 2.Electron中的模态窗口
- 3.区分父子窗口与模态窗口
- 二、实际案例使用
- 总结
前言
模态框是一种常用的交互元素,无论是在 Web 网站、桌面应用还是移动 APP 中,都有其应用场景。模态框指的是一种弹出窗口,它显示在原有主界面的上方,通常使用于展示一些重要的信息或提供一些交互能力,增强用户体验。
那么在 Electron
中如何实现模态框呢?在 Electron
中是叫模态窗口,在 BrowserWindow
模块中。
一、模态窗口
1.Web页面模态框
模态框指的是一种弹出窗口,它显示在原有主界面的上方,通常使用于展示一些重要的信息或提供一些交互能力。
模态框的外部区域会被半透明遮罩覆盖,用户必须优先完成模态框的操作或关闭模态框,才可以返回到主界面进行其他操作。这种机制可以有效地防止用户在没有进行必要操作的情况下误操作或忽视重要信息,从而提升用户体验和效率。
模态框通常包含一个标题栏、一个内容区域以及一组操作按钮。标题栏用于显示模态框的名称或信息,内容区域用于展示相关信息或操作选项,操作按钮则用于响应用户的操作或关闭模态框等。
其实很多前端UI框架都提供了模块框,比如 Bootstrap
中的模态框:
是不是突然觉得很常见呀,原来就是它呀。
2.Electron中的模态窗口
我们先来看实际效果,以下是使用官方入门案例的主界面:
之后我们来看模态窗口效果,如下动图:
如何实现呢?其实官网说的很清楚。
首先在 Main Process
模块中,找到 BrowserWindow
,它在主进程中负责创建和控制浏览器窗口。
我们在官方文档可以找到父子窗口和模态窗口API,如下:
父子窗口
通过使用parent
选项,你可以创建子窗口。
官方示例代码如下:
const { BrowserWindow } = require('electron')const top = new BrowserWindow() // 创建一个普通窗口
const child = new BrowserWindow({ parent: top })// 创建一个子窗口,并将top窗口设置为child窗口的父窗口
child.show() // 显示子窗口
top.show() // 显示父窗口
相信代码中的注释已经很明了了,这里最重要的是在创建窗口时配置是parent
选项,用于指定父窗口。要注意,child 窗口将总是显示在 top 窗口的顶部。
模态窗口
模态窗口是禁用父窗口的子窗口,创建模态窗口必须设置parent
和modal
选项。
const { BrowserWindow } = require('electron')// 创建child窗口,并将top窗口设置为父窗口。通过modal选项将该子窗口设置为模态窗口,预先将窗口隐藏起来
const child = new BrowserWindow({ parent: top, modal: true, show: false })
// 子窗口加载github网页
child.loadURL('https://github.com')
// 当子窗口渲染完毕后再显示
child.once('ready-to-show', () => {child.show()
})
其实就是在创建父子窗口的基础上,设置 modal
选项。将父子窗口变为模态窗口,并通过 show:false
提前将其隐藏起来,再通过一些事件等触发显示。
该窗口也是一个普通浏览器窗口,new BrowserWindow()
时的一些属性、方法等皆可以设置、调用。
现在贴出上面模态窗口的完整示例代码:
const { app, BrowserWindow } = require('electron')const createWindow = () => {const win = new BrowserWindow({width: 800,height: 600})win.loadFile('index.html')// 这里将创建的win窗口进行返回return win;
}app.whenReady().then(() => {const win = createWindow()// 这里要拿到父窗口const child = new BrowserWindow({ width: 600, height: 400, parent: win, modal: true, show: false })child.loadURL('https://github.com')child.once('ready-to-show', () => {child.show()})
})
该示例代码直接放在官网入门示例中 main.js
中运行即可,运行后会直接在窗口中显示模态窗口。
3.区分父子窗口与模态窗口
在 Electron
中,父子窗口和模态窗口是两种不同的窗口类型,它们具有不同的特点和用途。
- 父子窗口:在一个父窗口中打开一个子窗口,子窗口具有和父窗口相同的特性,可以共享父窗口的一些信息和资源。父子窗口之间可以相互通信和交互,父窗口还可以控制子窗口的动态行为,比如打开、关闭等。
- 模态窗口:指打开一个额外的窗口来进行一些必要的交互,但你不能在模态窗口外面进行任何操作。模态窗口打开后,你必须要完成其中需要的操作才能关闭它,否则无法操作其他窗口。模态窗口通常用于进行重要的提示、询问或操作确认等场景,以确保用户了解并明确自己的操作,避免一些不必要的错误发生。
需要注意的是,虽然父子窗口和模态窗口都可以用于打开新的窗口,并在其中进行一些操作,但它们有着不同的交互模式和使用场景。在使用时需要根据实际需求选择合适的窗口类型。
二、实际案例使用
我们先来看效果:
这里直接使用了 @中二少年学编程 导师的 electron+vue3
项目结构和基础代码,应用主窗口创建封装在 windows.js
中,部分代码如下:
const windowStateKeeper = require('electron-window-state');const { BrowserWindow, app, Menu, Tray} = require('electron');
const path = require('path');
const {join} = require('path');process.env.DIST = join(__dirname, '../../')
const indexHtml = join(process.env.DIST, 'dist/index.html')/*** 创建窗口类*/
class Window {win = null;getWindowState() {// 配置 electron-window-state 插件,获取窗口 optionlet win;const mainWindowState = windowStateKeeper({defaultWidth: 1000,defaultHeight: 800});let{width,height}=mainWindowStateconst options = {width,height,devTools: true,show: false,icon: path.resolve(__dirname, '../log.ico'),webPreferences: {// nodeIntegration:true, //集成node api// contextIsolation:false //关闭上下文隔离,配合nodeIntegration,可以赋予在render进程中写node代码的能力preload: path.resolve(__dirname, '../preload/preload.js') //预加载的js文件}}win = new BrowserWindow(options)mainWindowState.manage(win);return win}// 创建窗口createWindow () {this.win = this.getWindowState()// 应用被打包了,返回trueif(app.isPackaged){this.win.loadFile(indexHtml)}else{this.win.loadURL('http://localhost:5173')}// 等待dom渲染后打开窗口this.win.on('ready-to-show', () => {this.win.show()})this.win.on('closed', () => {this.win = null;})// webContents是一个EventEmitter. 负责渲染和控制网页, 是 BrowserWindow 对象的一个属性。(主进程)let contents = this.win.webContents;contents.openDevTools()this.win.loadURL('http://localhost:5173/')// this.win.loadFile('../../dist/index.html')return this.win}
}module.exports = Window
我们可以看到在 Window
类中的 createWindow()
方法可以创建窗口,并返回该窗口实例。
我们在入口 main.js
中执行,完成窗口创建工作,部分代码如下:
const { app, BrowserWindow, ipcMain, dialog, globalShortcut } = require('electron')
const getWindow = require('./windows')// 当Electron初始化完成
app.whenReady().then(() => {let win = nullwin = new getWindow().createWindow() // 创建窗口
});app.on('activate', () => {if (BrowserWindow.getAllWindows().length === 0) win.createWindow()
});app.on('window-all-closed', () => {if (process.platform !== 'darwin') app.quit()
});
在这段代码中,主进程(main.js
)在应用启动时会创建一个浏览器窗口。但是对于需要显示模态窗口的场景,我们需要将该场景的实现放到业务代码中。在渲染器进程与主进程之间的通信过程中,渲染器进程负责渲染页面和执行预加载的js文件,而主进程负责实现模态窗口的功能。
我们可以直接在业务代码中调用创建模态窗口的函数,但是需要注意的是,创建窗口的代码可能会被封装在 windows.js
等独立的模块中,在这种情况下,如何获取到父窗口是一个需要考虑的问题。我们再次调用创建窗口代码吗?不!
win = new getWindow().createWindow() // 创建窗口
如何解决这个问题呢?BrowserWindow
类中提供了一个名为getFocusedWindow()
的方法,该方法可用于获取当前应用程序中获得焦点的窗口。如果当前存在焦点窗口,则该方法将返回一个 BrowserWindow
对象,否则将返回 null
。
使用getFocusedWindow()
方法,我们可以方便地获取父窗口对象,所以在业务js中的实现代码是这样的:
const { ipcMain, BrowserWindow, dialog } = require('electron')
const path = require('path');ipcMain.handle('go-add-url', (event, msg) => {// 获取焦点窗口const top = BrowserWindow.getFocusedWindow()// 创建模态窗口const child = new BrowserWindow({parent: top,modal: true,autoHideMenuBar: true,show: false,webPreferences: {preload: path.resolve(__dirname, '../../preload/preload.js') //预加载的js文件}})// 模态窗口加载页面child.loadURL('http://localhost:5173#addUrl')child.once('ready-to-show', () => {child.show()})})
总结
Electron
主进程中可以通过实例化 BrowserWindow
类来创建浏览器窗口。可以向构造函数中传入一些选项,如窗口大小、位置、URL等。如果传入 parent
选项,便可以将该窗口设置为子窗口,子窗口可以访问父窗口的一些属性和方法。在此基础上,还可以设置 modal
选项来创建模态窗口,模态窗口会锁定父窗口,防止用户在未完成当前窗口操作前操作其他窗口。
在某些情况下,我们需要使用主窗口对象作为参数传递给其他方法或模块中,可以使用 BrowserWindow.getFocusedWindow()
方法来获取当前焦点窗口的对象。这个方法非常有用,可以使我们很方便地获取到主窗口对象,进行各种操作。
相关文章:

Electron 如何创建模态窗口?
目录 前言一、模态窗口1.Web页面模态框2.Electron中的模态窗口3.区分父子窗口与模态窗口 二、实际案例使用总结 前言 模态框是一种常用的交互元素,无论是在 Web 网站、桌面应用还是移动 APP 中,都有其应用场景。模态框指的是一种弹出窗口,它…...

诺贝尔化学奖:酶分子“定向进化”
2018年,诺贝尔化学奖迎来了历史上第五位女性得主——加州理工学院的Frances H. Arnold教授,以表彰她在“酶的定向进化”这一领域的贡献。 1、“酶的定向进化”到底是什么? 这里有三个点,“酶”、“进化”还有“定向”:…...
Centos8下源码编译安装运行Primihub
参考文献 PrimiHub 本地编译启动How to install Bazel on CentOS 8 Linux or Redhat 8/7 编译启动步骤 由于历史原因,服务器是Centos8操作系统,所以源码编译异常的麻烦。特此记录如下。 采用源码编译方式可以在一步步的运行过程中对整个流程进行深刻…...
嘉兴桐乡考证培训-23年教资认定注意事项你知道吗?
又到了新的一年了,去年错过认定的同学们可以竖起耳朵啦~ 每年认定机会有两次,大部分省份一般上半年下半年各一次。 问:在校生可以认定么? 答:可以,但有年级限制:本科生大四最后一学期…...

oracle客户端的安装教程
文章目录 一、安装前的准备工作 1.1、百度网盘安装包的连接 1.2、百度网盘oracle11g软件包 二、oracle数据库客户端的安装与数据的准备 安装步骤 前言 本文主要讲解oracle客户端的安装与简单使用过程 一、安装前的准备工作 1.1、百度网盘安装包的连接 客户端的软件包 …...

python 文件操作 , 异常处理 , 模块和包
文件操作 1.写数据 # open(name, mode) # name:是要打开的目标文件名的字符串(可以包含文件所在的具体路径)。 # mode:设置打开文件的模式(访问模式):只读、写入、追加等。 #1.打开文件---通道建立--申请资源 # w 模式会清空之前的内…...
AIGC技术研究与应用 ---- 下一代人工智能:新范式!新生产力!(1-简介)
文章大纲 AI GC简介决策式/分析式AI(Discriminant/Analytical AI)和生成式AI (Generative AI)参考文献与学习路径模型进化券商研报陆奇演讲AI GC 《我,机器人》中所演绎的一样,主角曾与机器人展开了激烈的辩论,面对“机器人能写出交响乐吗?”“机器人能把画布变成美丽…...

Flask restful分页接口实现
1.先定义一个工作信息表: 指定一些相关的字段:工作名称、年限、级别等 class Work(db.Model):__tablename__ = workid = db.Column(db.Integer, primary_key=True)workName = db.Column(db.String(5),nullable=False)year = db.Column(db.String(20), nullable=False)level = …...

27事务管理AOP
一、MySQL事务回顾 二、Spring事务管理 Spring框架的第一大核心:IOC控制反转 在DeptServiceImpl下删除部门方法下新加一个删除员工信息的操作,注意:此时的id是部门id。 1、问题分析 2、Transactional-Spring事务管理 一般是在Service实现类的…...

煤矿电子封条实施方案 yolov7
煤矿电子封条实施方案采用YOLOv7网络模型算法技术,煤矿电子封条实施算法模型过将全国各省矿山实时监测数据,实现对全国各矿山及时有效的处理及分析。YOLOv7 的发展方向与当前主流的实时目标检测器不同,研究团队希望它能够同时支持移动 GPU 和…...
Linux-inode和block概述
操作系统的文件数据除了实际内容之外,通常含有非常多的属性,例如Linux操作系统的文件权限与文件属性。文件系统通常会将这两部分内容分别存放在inode和block中。 inode 和 block 概述 文件是存储在硬盘上的,硬盘的最小存储单位叫做扇区sect…...
安卓开发投屏反控实现方式
在安卓开发中,可以通过MediaProjection API来实现屏幕投屏的功能,同时也可以通过Socket通信实现反控功能。下面将详细介绍实现步骤和注意事项。 1. 创建MediaProjectionManager对象 首先,我们需要创建一个MediaProjectionManager对象&#…...

外网SSH远程连接linux服务器「cpolar内网穿透」
✨个人主页:bit me👇 目 录 视频教程🌴1. Linux CentOS安装cpolar☘️2. 创建TCP隧道🎍3. 随机地址公网远程连接🎋4. 固定TCP地址🎄5. 使用固定公网TCP地址SSH远程 转载自内网穿透工具的文章:无…...

Deferred Components-实现Flutter运行时动态下发Dart代码 | 京东云技术团队
导读 Deferred Components,官方实现的Flutter代码动态下发的方案。本文主要介绍官方方案的实现细节,探索在国内环境下使用Deferred Components,并且实现了最小验证demo。读罢本文,你就可以实现Dart文件级别代码的动态下发。 一、…...
08 集合框架1
什么是数据结构? 存储数据,组织数据的方法,就是对数据做增删改查的操作 常见的数据结构有哪些?各自的优缺点是什么? 数组:擅长修改 查找操作,不擅长增加 删除操作 链表:有单项链表和双向链表,擅长增加和删除操作,不擅长修改和查找的操作 队列:擅长操作头和尾,先进先出,…...

内卷把同事逼成了“扫地僧”,把Git上所有面试题整理成足足24W字测试八股文
互联网大厂更多的是看重学历还是技术? 毫无疑问,是技术,技术水平相近的情况下,肯定学历高/好的会优先一点,这点大家肯定都理解。 说实话,学弟学妹们找工作难,作为面试官招人也难呀!…...
10-jQuery-遍历children、parent、for、each、for...of等
1、for 循环:可以用来遍历数组或类数组对象,但不能用来遍历普通对象。 <ul><li>John</li><li>Doe</li><li>Jane</li><li>Doe</li> </ul><script>var lis $(li);for (var i 0; i &…...

联想集团财报:收入持续下滑,联想集团财务前景已恶化
来源:猛兽财经 作者:猛兽财经 联想集团2023财年第三季度财务业绩回顾 联想集团(00992)于2023年2月16日盘后公布了该公司2023财年第三季度的财报。 财报显示,联想集团的收入已经从2022财年第三季度的201.27亿美元下降到…...

GPT4限制被破解!ChatGPT实现超长文本处理的新方法
目录 前言 使用chat-gpt过程中有哪些痛点 1.无法理解人类情感和主观性 2.上下文丢失 3.约定被打断 那如何去解决这个痛点 Transformer(RMT)怎么去实现的 1.Transformer 模型 2.RMT模型 3.计算推理速率 4.渐进学习能力 总结 写到最后 大家好…...
奋斗,然后成功:我的架构狮之梦
与代码结缘 2018年,当时听说了一个很厉害的人——吴瀚清老师,也就是大家所熟知的“道哥”。关于他的事情有很多传说,于是我也很快成为了他的小迷弟,把吴瀚清老师当成了自己的偶像。 也是那一年,我买了人生中第一本关…...
设计模式和设计原则回顾
设计模式和设计原则回顾 23种设计模式是设计原则的完美体现,设计原则设计原则是设计模式的理论基石, 设计模式 在经典的设计模式分类中(如《设计模式:可复用面向对象软件的基础》一书中),总共有23种设计模式,分为三大类: 一、创建型模式(5种) 1. 单例模式(Sing…...
论文解读:交大港大上海AI Lab开源论文 | 宇树机器人多姿态起立控制强化学习框架(二)
HoST框架核心实现方法详解 - 论文深度解读(第二部分) 《Learning Humanoid Standing-up Control across Diverse Postures》 系列文章: 论文深度解读 + 算法与代码分析(二) 作者机构: 上海AI Lab, 上海交通大学, 香港大学, 浙江大学, 香港中文大学 论文主题: 人形机器人…...
k8s从入门到放弃之Ingress七层负载
k8s从入门到放弃之Ingress七层负载 在Kubernetes(简称K8s)中,Ingress是一个API对象,它允许你定义如何从集群外部访问集群内部的服务。Ingress可以提供负载均衡、SSL终结和基于名称的虚拟主机等功能。通过Ingress,你可…...

【JVM】- 内存结构
引言 JVM:Java Virtual Machine 定义:Java虚拟机,Java二进制字节码的运行环境好处: 一次编写,到处运行自动内存管理,垃圾回收的功能数组下标越界检查(会抛异常,不会覆盖到其他代码…...
基于数字孪生的水厂可视化平台建设:架构与实践
分享大纲: 1、数字孪生水厂可视化平台建设背景 2、数字孪生水厂可视化平台建设架构 3、数字孪生水厂可视化平台建设成效 近几年,数字孪生水厂的建设开展的如火如荼。作为提升水厂管理效率、优化资源的调度手段,基于数字孪生的水厂可视化平台的…...
大模型多显卡多服务器并行计算方法与实践指南
一、分布式训练概述 大规模语言模型的训练通常需要分布式计算技术,以解决单机资源不足的问题。分布式训练主要分为两种模式: 数据并行:将数据分片到不同设备,每个设备拥有完整的模型副本 模型并行:将模型分割到不同设备,每个设备处理部分模型计算 现代大模型训练通常结合…...

AirSim/Cosys-AirSim 游戏开发(四)外部固定位置监控相机
这个博客介绍了如何通过 settings.json 文件添加一个无人机外的 固定位置监控相机,因为在使用过程中发现 Airsim 对外部监控相机的描述模糊,而 Cosys-Airsim 在官方文档中没有提供外部监控相机设置,最后在源码示例中找到了,所以感…...
【JavaSE】多线程基础学习笔记
多线程基础 -线程相关概念 程序(Program) 是为完成特定任务、用某种语言编写的一组指令的集合简单的说:就是我们写的代码 进程 进程是指运行中的程序,比如我们使用QQ,就启动了一个进程,操作系统就会为该进程分配内存…...

【无标题】湖北理元理律师事务所:债务优化中的生活保障与法律平衡之道
文/法律实务观察组 在债务重组领域,专业机构的核心价值不仅在于减轻债务数字,更在于帮助债务人在履行义务的同时维持基本生活尊严。湖北理元理律师事务所的服务实践表明,合法债务优化需同步实现三重平衡: 法律刚性(债…...
Spring Boot + MyBatis 集成支付宝支付流程
Spring Boot MyBatis 集成支付宝支付流程 核心流程 商户系统生成订单调用支付宝创建预支付订单用户跳转支付宝完成支付支付宝异步通知支付结果商户处理支付结果更新订单状态支付宝同步跳转回商户页面 代码实现示例(电脑网站支付) 1. 添加依赖 <!…...