探索 Electron:窗口菜单以及生命周期和对话框讲解

Electron是一个开源的桌面应用程序开发框架,它允许开发者使用Web技术(如 HTML、CSS 和 JavaScript)构建跨平台的桌面应用程序,它的出现极大地简化了桌面应用程序的开发流程,让更多的开发者能够利用已有的 Web 开发技能来构建功能强大且跨平台的应用程序,这对于提升开发效率和应用程序的快速交付具有重要意义。

目录

窗口操作

自定义菜单

主进程生命周期

dialog对话框


窗口操作

在Electron中,窗口操作是非常重要的,开发者可以通过一些核心API来管理和控制应用程序窗口的行为,以下是对窗口内容的一些常见操作:

设置大小与位置:通过如下代码设置窗口的初始大小与在桌面的初始位置:

const createWindow = () => {
    const win = new BrowserWindow({ // 窗口的配置
        width: 800, // 设置窗口初始大小
        height: 600, 
        x: 100, // 设置窗口初始位置
        y: 100,
        maxWidth: 1000, // 设置窗口最大最小宽高
        maxHeight: 800,
        minWidth: 500,
        minHeight: 400,
        resizable: false, // 设置窗口是否可以拖动改变大小,默认是true,设置false不允许进行窗口缩放了
    })
    win.loadFile('./src/index.html') // 加载页面
}

解决首页加载白屏: 在我们创建完窗口之后,窗口里面是没有加载内容的,内容是放在加载本地页面或者外部链接页面完成的,由于内容的加载和窗体的显示是异步执行不是同步的,所以可能看到类似于首屏加载会出现白屏的现状,这里我们可以采用下面的方式解决:

const createWindow = () => {
    const win = new BrowserWindow({ // 窗口的配置
        width: 800,
        height: 600,
        show: false, // 隐藏窗口,默认是true
        x: 100,
        y: 100
    })
    win.loadFile('./src/index.html') // 加载页面
    win.on('ready-to-show', () => { // 窗口准备就绪后,显示窗口
        win.show()
    })
}

窗口标题:如果想自定义窗口标题的话,可以将index.html中的title删除掉,采用如下的方式:

const createWindow = () => {
    const win = new BrowserWindow({ // 窗口的配置
        width: 800, 
        height: 600, 
        icon: 'logo.png', 
        title: "亦世凡华、"
    })
    win.loadFile('./src/index.html') // 加载页面
}

如果想去掉窗口标题和菜单的话可以采用如下方式frame去掉边框,去掉之后窗口不再能拖动了,当然也可以设置窗口透明,不过很少用:

当然如果想隐藏掉原本自带的导航栏可以采用如下的属性进行:

自定义菜单

如果想对electron进行自定义菜单的设置的话,可以采用如下的方式进行,通过自定义菜单选项,设置一级二级菜单,让给菜单设置回调事件来实现菜单的自定义:

// app应用;BrowserWindow 窗口
const { app, BrowserWindow, Menu } = require('electron')

const createWindow = () => {
    const win = new BrowserWindow({ // 窗口的配置
        width: 800, 
        height: 600, 
        icon: 'logo.png', 
        title: "亦世凡华、",
    })
    win.loadFile('./src/index.html') // 加载页面
}

// 自定义菜单选项
let menuTemp = [
    { label: '文件', submenu: [
        { label: '打开文件', click() {
            console.log("打开文件")
        } },
        { type: 'separator' }, // 添加一个分割线
        { label: '关闭文件夹' },
        { label: '关于', role: 'about' },
    ] },
    { label: '编辑' },
]
// 利用上述的模板生成一个菜单选项
const menu = Menu.buildFromTemplate(menuTemp)
// 将上述的自定义菜单添加到应用里面
Menu.setApplicationMenu(menu)

// 监听app的ready事件,当应用加载完成的时候,创建窗口
app.on('ready', () => {
    createWindow()
})

得到的效果如下所示:

当然菜单本身的role属性还分配了不同的角色,这里就不再一一赘述了,通过如下代码进行一个简单的演示:

// app应用;BrowserWindow 窗口
const { app, BrowserWindow, Menu } = require('electron')

const createWindow = () => {
    const win = new BrowserWindow({ // 窗口的配置
        width: 800, 
        height: 600, 
        icon: 'logo.png', 
        title: "亦世凡华、",
    })
    // 自定义菜单选项
    let menuTemp = [
        {
            label: '角色',
            submenu: [
                { label: '复制', role: 'copy' },
                { label: '剪切', role: 'cut' },
                { label: '粘贴', role: 'paste' },
                { label: '最小化', role: 'minimize' }
            ]
        },
        {
            label: '类型',
            submenu: [
                { label: '选项1', type: 'checkbox' },
                { label: '选项2', type: 'checkbox' },
                { label: '选项3', type: 'checkbox' },
                { type: 'separator' },
                { label: 'item1', type: 'radio' },
                { label: 'item2', type: 'radio' },
                { type: 'separator' },
                { label: 'windows', type: 'submenu', role: 'windowMenu' },
            ]
        },
        {
            label: '其它',
            submenu: [
                {
                    label: '退出',
                    width: 80,
                    height: 60,
                    // icon: 'logo.png',
                    accelerator: 'CmdOrCtrl+Q', // 快捷键
                    click() {
                        app.quit()
                    }
                }
            ]
        }
    ]
    // 利用上述的模板生成一个菜单选项
    const menu = Menu.buildFromTemplate(menuTemp)
    // 将上述的自定义菜单添加到应用里面
    Menu.setApplicationMenu(menu)
    win.loadFile('./src/index.html') // 加载页面
}

// 监听app的ready事件,当应用加载完成的时候,创建窗口
app.on('ready', () => {
    createWindow()
})

// 当所有的窗口都被关闭时,并且还不是苹果系统,则直接退出程序
app.on('window-all-closed', () => {
    console.log("第四步: window-all-closed-所有窗口都被关闭了")
    app.quit() // 退出程序
})

最终呈现的效果如下所示:

主进程生命周期

Electron应用程序的生命周期涉及到整个应用程序从启动到关闭的各个阶段和事件,这些阶段包括主进程和渲染进程的不同生命周期事件,以下是一个简要的概述:

应用程序启动:当应用程序启动时,主进程开始执行,并触发app模块的ready事件,在这一阶段,通常进行应用程序的初始化设置:

窗口创建与关闭:主进程通过创建窗口实例来展示用户界面,窗口的创建和关闭触发了一系列事件,如browser-window模块的ready-to-show、closed等事件:

应用程序激活和休眠:当应用程序从后台切换到前台时,会触发activate事件,应用程序进入休眠状态时,可以监听before-quit事件进行必要的清理工作:

退出应用程序:用户关闭所有窗口或者通过代码触发退出时,会触发window-all-closed和will-quit事件,允许应用程序执行最后的清理操作:

接下来我们通过代码对主进程生命周期进行一个简单的梳理:

// app应用;BrowserWindow 窗口
const { app, BrowserWindow } = require('electron')

const createWindow = () => {
    const win = new BrowserWindow({ // 窗口的配置
        width: 800,
        height: 600,
        autoHideMenuBar: true, // 自动隐藏菜单栏
    })
    win.loadFile('./src/index.html') // 加载页面

    win.webContents.on('did-finish-load', () => { // 页面加载完毕后,执行回调函数
        console.log("第三步: did-finish-load-页面加载完毕")
    })
    win.webContents.on('dom-ready', () => { // 页面dom加载完毕后,执行回调函数
        console.log("第二步: dom-ready-dom加载完毕")
    })

    win.on('closed', () => { // 窗口关闭时,销毁窗口对象
        console.log("第八步: closed-窗口被销毁了")
    })
}

// 当app准备完毕,创建窗口
app.on('ready', () => {
    console.log("第一步: ready-app准备完毕")
    createWindow()
})

// 当所有的窗口都被关闭时,并且还不是苹果系统,则直接退出程序
app.on('window-all-closed', () => {
    console.log("第四步: window-all-closed-所有窗口都被关闭了")
    app.quit() // 退出程序
})
app.on('before-quit', () => {
    console.log("第五步: before-quit-准备退出程序")
})
app.on('will-quit', () => {
    console.log("第六步: will-quit-即将退出程序")
})
app.on('quit', () => {
    console.log("第七步: quit-退出程序")
})

从上文代码可以看出,所谓的app的生命周期就是我们在桌面上点击一个图标,那么app就会启动,启动完成之后会进行一些初始化操作,所以这里就需要ready准备,准备完成之后app就需要给我们进行展示特定界面也就是窗口,窗口有了之后它里面的dom元素就会进行dom-ready加载,页面加载完成然后我们再点击其中导航栏中的某个选项,这个时候某个选项dom加载完成之后会触发did-finsh-load的执行,点击关闭app窗口之后会执行closed,关闭所有窗口window-all-closed函数会被执行。

以下是具体的函数代码流程:

1)ready:app初始化完成

2)dom-ready:一个窗口中的文本加载完成

3)did-finsh-load:导航完成时触发

4)window-all-closed:所有窗口都被关闭时触发

5)before-quit:在关闭窗口之前触发

6)will-quit:在窗口关闭并且应用退出时触发

7)quit:当所有窗口被关闭时触发

8)closed:当窗口关闭时触发,此时应删除窗口引用

dialog对话框

在electron中dialog对话框可以显示用于打开和保存文件、警报等的本机系统对话框。这里对常用的dialog对话框函数进行一个简单的代码讲解:

showOpenDialog:用于显示一个打开文件或目录的对话框,让用户进行文件选择操作。

dialog.showOpenDialog({
    buttonLabel: '选择', // 设定对话框中选择按钮的显示文本为“选择”
    defaultPath: app.getPath('desktop'), // 设定默认路径为桌面
    properties: ['multiSelections','createDirectory','openFile','openDirectory'] // 设定选择类型为多选、新建文件夹、打开文件、打开文件夹
}).then((result)=> {
    console.log(result.filePaths) // 将用户选择的文件路径数组打印到控制台,以便开发者查看或进一步处理这些路径。
})

showSaveDialog:用于显示一个保存文件的对话框,并进行相应的操作。

dialog.showSaveDialog({
    title: "保存文件",
    defaultPath: 'test.txt' // 默认路径
}).then(res => {
    console.log("第一步: dialog.showSaveDialog", res)
})

showMessageBox:用于显示一个消息框并接收用户的选择。

const answers = ['Yes','No','Maybe']
dialog.showMessageBox({
    title: 'Message Box',
    message: 'Please select an option',
    detail: 'Message details',
    buttons: answers,
}).then(({ response }) => {
    console.log(`User selected ${answers[response]}`)
})

showErrorBox:用于显示一个简单的错误提示框。

dialog.showErrorBox('自定义标题', '当前错误内容')

最近更新

  1. docker php8.1+nginx base 镜像 dockerfile 配置

    2024-07-12 05:10:01       70 阅读
  2. Could not load dynamic library ‘cudart64_100.dll‘

    2024-07-12 05:10:01       74 阅读
  3. 在Django里面运行非项目文件

    2024-07-12 05:10:01       62 阅读
  4. Python语言-面向对象

    2024-07-12 05:10:01       72 阅读

热门阅读

  1. ls命令学习记录1

    2024-07-12 05:10:01       29 阅读
  2. ARM Ubuntu 主机安装指定版本Python

    2024-07-12 05:10:01       27 阅读
  3. sqlite3 — DB-API 2.0 interface for SQLite databases

    2024-07-12 05:10:01       24 阅读
  4. arm 版的 deb、rpm、AppImage 都有什么区别

    2024-07-12 05:10:01       30 阅读
  5. 【无标题】

    2024-07-12 05:10:01       26 阅读
  6. IT专业高考假期入门指南

    2024-07-12 05:10:01       27 阅读
  7. 墨烯的C语言技术栈-C语言基础-012

    2024-07-12 05:10:01       28 阅读
  8. Kubernetes(k8s)架构的工作原理

    2024-07-12 05:10:01       29 阅读
  9. 【问题记录】xxl-job admin端锁超时问题

    2024-07-12 05:10:01       26 阅读