Electron桌面开发入门

1.初始化工作
midir electron-demo
cd electron-demo
npm init

//到package.json 文件下将入口文件修改为main.js
  "main": "main.js",
//并且创建main.js文件

//electron 安装依赖
npm i electron -S
//安装nodemon 
npm install nodemon -D

修改package.json

{
  "name": "electron-demo",
  "version": "1.0.0",
  "description": "",
  "main": "main.js",
  "scripts": {
    "test": "echo \"Error: no test specified\" && exit 1",
    "start": "nodemon --exec electron . --watch ./ --ext .html,.js,.css"    //监听html,js,css文件的变化
  },
  "author": "",
  "license": "ISC",
  "dependencies": {
    "electron": "^19.0.6",
    "electron-win-state": "^1.1.22"
  },
  "devDependencies": {
    "nodemon": "^2.0.16"
  }
}


修改main.js

//app应用模块
//BrowserWindow 浏览器串口模块
const { app, BrowserWindow } = require('electron')

//创建窗口
const createwindow = ()=>{
  const win = new BrowserWindow({
    width:800,
    height:600
  })

  // 给窗口装载页面
  // win.loadFile('./renderer/index.html')
  win.loadURL('https://cn.bing.com/?mkt=zh-CN')

  //自动打开发开工具
  win.webContents.openDevTools()


  //可以创建多个窗口
//   const win2 = new BrowserWindow({
//     width:800,
//     height:600
//   })

//   win2.loadURL('https://www.baidu.com')
}

//应用就绪,可以装载窗口了
app.whenReady().then(createwindow)

启动程序

npm start

看到效果
在这里插入图片描述
后续操作省略,可以对应文件夹实现
目录如下
在这里插入图片描述
main.js 主程序文件 node环境,能读写文件
renderer 渲染文件 有关页面渲染的都在这里,可以结合vue等框架
app.js //vue模板
index.html //窗口页面
style.css //窗口样式文件
preload-js 桥接文件
因为渲染程序和主程序直接传递消息有严重的安全隐患,所以要通过这里的’桥’文件,当工具人这里面重要的核心就是通过contextBridge 暴露一个对象给渲染程序通过ipcRenderer中的方法监听和抛发事件
controller 主程序事件控制器
主要处理主程序监听事件和抛发事件的逻辑处理
具体操作如下

main.js

// 引入事件处理器,对render的操作作出回应
require('./controller/ipcMessage')

//引入插件    作用:记录窗口的位置大小
const  WinState = require('electron-win-state').default

//app应用模块
//BrowserWindow 浏览器串口模块
const { app, BrowserWindow } = require('electron')
const {resolve} =require('path') 
//创建窗口
const createwindow = ()=>{

  // 设置默认窗口大小
  const  winState = new WinState({ 
    defaultWidth: 1400,
    defaultHeight: 600,
    dev:true
  })

  const win = new BrowserWindow({
    ...winState.winOptions,
    // width:800,
    // height:600,
    show:false,
    minHeight:300,
    minWidth:400,
   
    backgroundColor: 'aliceblue',
    resizable:true, //默认可以 切换窗口大小
    movable:true,  //窗口是否可以移动
    // frame:true,  //是否关闭边框
    // titleBarStyle: "hidden",  // 控制titleBar的状态
    backgroundColor:"skyblue",
    webPreferences:{
      //nodeIntegration 开启node  contextIsolation 开启或关闭主程序和渲染程序的隔离 
      //这两个的开启会有安全隐患 
      // nodeIntegration:true,
      // contextIsolation:false    

      //预加载,桥文件
      preload: resolve(__dirname,'./preload-js')
    }
  })

  //将窗口位置大小存起来
  winState.manage(win)

  // 给窗口装载页面
  win.loadFile('./renderer/index.html')
  // win.loadURL('https://cn.bing.com/?mkt=zh-CN')

  //自动打开发开工具
  // win.webContents.openDevTools()

  //同win 的show一起配置 当win装载完成显示
  win.once('ready-to-show',()=>{
    win.show()
  })
  // 可以创建多个窗口
  // const win2 = new BrowserWindow({
  //   width:800,
  //   height:600,
  //   parent:win,  //配置父窗口,这里是子窗口
  //   modal:false   //锁定子窗口
  // })

  // win2.loadURL('https://www.baidu.com')
  //win2 关闭时 win 全屏
  // win2.on('close',()=>{
  //   win.maximize()
  // })
}

//app主进程完成加载
// app.on('will-finish-launching',()=>{
//   console.log('will-finish-launching')
// })
// //app准备就绪
// app.on('ready',()=>{
//   console.log('ready')
// })

// // app将要退出
// app.on('will-quit',()=>{
//   console.log('will-quit')
// })

// app.on('before-quit',()=>{
//   console.log('before-quit')
// })

// //app退出
// app.on('quit',()=>{
//   console.log('quit')
// })
// //所有窗口都关闭
// app.on('window-all-closed',()=>{
//   console.log('window-all-closed')
//   //对于macos系统,关闭窗口时,不会直接退出应用,还会保留图标
//   // if(process.platform!=='darwin'){
//   //   app.quit()
//   // }
// })


//应用就绪,可以装载窗口了
app.whenReady().then(()=>{
  createwindow()
  //在macos下,当全部窗口都关了,点击图标,窗口再次打开
  app.on('activate',()=>{
    if(BrowserWindow.getAllWindows().length===0){
      createwindow()
    }
  })

  //isReady  app是否装载完成
  console.log(app.isReady())
  //获取路径
  console.log(app.getPath('desktop'))
  console.log(app.getPath('music'))
  console.log(app.getPath('temp'))
  console.log(app.getPath('userData'))

  console.log(BrowserWindow.getAllWindows().length)
})

// 程序失焦
app.on('browser-window-blur',()=>{
  console.log("app blur")
})

// 程序获取焦点
app.on('browser-window-focus',()=>{
  console.log('app focus')
})

// 在html中允许使用第三方资源  设为false 会有警告
process.env['ELECTRON_DISABLE_SECURITY_WARNINGS'] = 'true'

renderer/index.html

<!DOCTYPE html>
<html lang="en">
<head>
  <meta charset="UTF-8">
  <meta http-equiv="X-UA-Compatible" content="IE=edge">
  <meta name="viewport" content="width=device-width, initial-scale=1.0">
  <!-- unsafe-eval 配置第三方引用安全策略 -->
  <!-- <meta http-equiv="Content-Security-Policy" content="script-src 'self' unsafe-eval"> -->
  <title>Document</title>
  <script src="./vue.global.js"></script>
  <link rel="stylesheet" href="./style.css">
</head>
<body>
  <h1>hello electron!</h1>
  <input type="range" />
  <div id="root"></div>
  <script src="./app.js"></script>
</body>
</html>

renderer/app.js

const versions = window.myAPI.versions

const app = Vue.createApp({
  template:`
    <p>Chrome version: {{chromeVersion}}</p>
    <p>Node version: {{NodeVersion}}</p>
    <p>Electron version: {{electronVersion}}</p>
    <button @click="sendSyncMsg"> 发送同步消息 </button>
    <button @click="sendAsyncMsg"> 发送异步消息 </button>
  `,

  data(){
    return {
      chromeVersion: versions.chrome,
      NodeVersion: versions.node,
      electronVersion: versions.electron
    }
  },

  methods:{
    // 发送同步消息给桥文件,桥文件转发给主程序
    sendSyncMsg(){
      myAPI.sendSyncMsg("this message from render ")
    },
    // 主进程和渲染进程传递消息 建议IPC通信 全部通过异步
    async  sendAsyncMsg(){
      let result = await myAPI.sendAsyncMsg()
      console.log(result)
    }

  },
  mounted() {
    // 接受main 返回的消息
    // myAPI.recieveSyncMsgUseCb((msg)=>{
    //   console.log(msg)
    //   console.log(this)
    // })
    //promise调用
    // const result = await myAPI.recieveSyncMsgUsePromise()
    // console.log(result,1111)
    myAPI.recieveSyncMsgUsePromise().then((res)=>{
      console.log(res,22222);
    })
  }
})

app.mount("#root")

renderer/style.css

body {
  background-color: pink;
  /* 设置拖拽 */
  user-select: none;
  -webkit-app-region:drag;
}

/* 设置input可拖拽 */
input {
  -webkit-app-region: no-drag;
}

preload-js/index.js

//preload-js下面的文件我把他叫做'桥'文件,桥文件能直接访问到主程序的信息   因为渲染程序不能直接和主程序做通信 有安全隐患
// 通过桥文件让渲染程序能够获取到主程序的信息

const {contextBridge, ipcRenderer} = require('electron')

// 向main发送一个同步消息
const sendSyncMsg = (msg)=>{
  console.log(msg,"发送了一次");
  ipcRenderer.send('sync-send-event',msg)
}

// main收到同步消息抛发事件到这里,通过promise给Vue层
const recieveSyncMsgUsePromise = ()=>{
  return new Promise((resolve,reject) => {
    ipcRenderer.on('recive-sync-event',(event,msg)=>{
      console.log("返回的数据 1")
      resolve(msg)
    })
  })
}

// main收到同步消息抛发事件到这里,通过callback给Vue层(推荐使用这种方法)
const recieveSyncMsgUseCb = (cb) => {
  ipcRenderer.on('recive-sync-event',(event,msg)=>{
    cb(msg)
  })
}

// 发送异步消息
const sendAsyncMsg = async ()=>{
  const result = await ipcRenderer.invoke('my-invokable-ipc')
  return result
}


//通过这里向渲染程序暴露一个对象,这个对象是myAPI
//通过直接暴露ipcRenderer给vue层有些方法会丢失(坑)
contextBridge.exposeInMainWorld('myAPI',{
  versions: process.versions,
  sendSyncMsg,
  recieveSyncMsgUsePromise,
  sendAsyncMsg,
  recieveSyncMsgUseCb
})

controller/ipcMessage.js

// 事件处理器  对于桥文件抛发的事件做回应
const { ipcMain } = require("electron")

ipcMain.on('sync-send-event',(event,msg)=>{
  console.log(msg,'shoudao 1');
  event.reply('recive-sync-event', '我已经收到:' + msg)
  // event.sender.send('a', '我已经收到:' + msg)
})

function somePromise(){
  return new Promise((resolve,reject)=>{
    setTimeout(()=>{
      resolve('async message from main')
    },2000)
  })
}
// 异步事件监听
ipcMain.handle("my-invokable-ipc", async (ecent,...args)=>{
  const result = await somePromise()
  return result
})
  • 1
    点赞
  • 6
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
Electron 是一个基于 Node.js 和 Chromium 的桌面应用程序开发框架,可以使用 HTML、CSS 和 JavaScript 来构建跨平台的桌面应用程序。在本文中,我们将介绍如何使用 Python 和 Flask 结合 Electron 编写一个简单的桌面应用程序。 1. 安装 Electron 首先,我们需要安装 Electron。可以通过 npm 来安装它: ``` npm install electron --save-dev ``` 2. 创建 Electron 应用程序 接下来,我们需要创建一个基本的 Electron 应用程序。在项目根目录下创建一个名为 main.js 的文件,并添加以下代码: ``` const { app, BrowserWindow } = require('electron') const path = require('path') function createWindow() { const win = new BrowserWindow({ width: 800, height: 600, webPreferences: { nodeIntegration: true } }) win.loadFile('index.html') win.webContents.openDevTools() } app.whenReady().then(() => { createWindow() app.on('activate', () => { if (BrowserWindow.getAllWindows().length === 0) { createWindow() } }) }) app.on('window-all-closed', () => { if (process.platform !== 'darwin') { app.quit() } }) ``` 这段代码创建了一个基本的窗口,加载了一个名为 index.html 的文件,并打开了开发者工具。 3. 创建 Flask 应用程序 然后,我们需要创建一个 Flask 应用程序。在项目根目录下创建一个名为 server.py 的文件,并添加以下代码: ``` from flask import Flask, jsonify app = Flask(__name__) @app.route('/api') def api(): return jsonify({'message': 'Hello, World!'}) if __name__ == '__main__': app.run(debug=True) ``` 这段代码创建了一个简单的 Flask 应用程序,具有一个名为 /api 的路由,返回了一个 JSON 响应。 4. 集成 Flask 应用程序 现在,我们需要将 Flask 应用程序集成到 Electron 应用程序中。在 main.js 文件中添加以下代码: ``` const { app, BrowserWindow } = require('electron') const path = require('path') const { spawn } = require('child_process') let flaskProcess = null const flaskPath = path.join(__dirname, 'server.py') function createWindow() { const win = new BrowserWindow({ width: 800, height: 600, webPreferences: { nodeIntegration: true } }) win.loadFile('index.html') win.webContents.openDevTools() } app.whenReady().then(() => { flaskProcess = spawn('python', [flaskPath]) createWindow() app.on('activate', () => { if (BrowserWindow.getAllWindows().length === 0) { createWindow() } }) }) app.on('window-all-closed', () => { if (process.platform !== 'darwin') { app.quit() } }) app.on('before-quit', () => { flaskProcess.kill() }) ``` 这段代码启动了一个 Python 进程来运行 Flask 应用程序,并在应用程序关闭之前杀死该进程。 5. 发起请求 最后,我们需要在渲染进程中发起请求。在项目根目录下创建一个名为 index.html 的文件,并添加以下代码: ``` <!DOCTYPE html> <html> <head> <meta charset="UTF-8"> <title>Hello, World!</title> </head> <body> <h1 id="message"></h1> <script> const { ipcRenderer } = require('electron') ipcRenderer.on('message', (event, message) => { document.getElementById('message').textContent = message }) fetch('http://localhost:5000/api') .then(response => response.json()) .then(data => { ipcRenderer.send('message', data.message) }) .catch(error => console.error(error)) </script> </body> </html> ``` 这段代码使用 IPC 通信来从 Python 进程接收消息,并使用 fetch API 发起一个请求来获取 Flask 应用程序的响应。 6. 运行应用程序 现在,我们可以通过运行以下命令来启动应用程序: ``` npm start ``` 这将同时启动 Electron 应用程序和 Flask 应用程序,并打开一个窗口,显示来自 Flask 应用程序的消息。 至此,我们已经成功地构建了一个使用 Python、Flask 和 Electron 框架的桌面应用程序。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值