【问题标题】:Electron, Creating Duplicate of Main Window On Button Click电子,在按钮单击时创建主窗口的副本
【发布时间】:2020-06-15 06:06:44
【问题描述】:

我正在制作一个 electron 应用程序,用户可以根据需要打开任意数量的主窗口(默认打开的)实例。

我希望他们能够通过单击index.html 中的按钮来执行此操作。

如何在以下默认应用代码中实现这一点?

main.js

const { app, BrowserWindow } = require('electron')

function createWindow () {
  // Create the browser window.
  const win = new BrowserWindow({
    width: 800,
    height: 600,
    webPreferences: {
      nodeIntegration: true
    }
  })

  // and load the index.html of the app.
  win.loadFile('index.html')

  // Open the DevTools.
  win.webContents.openDevTools()
}

// This method will be called when Electron has finished
// initialization and is ready to create browser windows.
// Some APIs can only be used after this event occurs.
app.whenReady().then(createWindow)

// Quit when all windows are closed.
app.on('window-all-closed', () => {
  // On macOS it is common for applications and their menu bar
  // to stay active until the user quits explicitly with Cmd + Q
  if (process.platform !== 'darwin') {
    app.quit()
  }
})

app.on('activate', () => {
  // On macOS it's common to re-create a window in the app when the
  // dock icon is clicked and there are no other windows open.
  if (BrowserWindow.getAllWindows().length === 0) {
    createWindow()
  }
})

// In this file you can include the rest of your app's specific main process
// code. You can also put them in separate files and require them here.

index.html

<!DOCTYPE html>
<html>
  <head>
    <meta charset="UTF-8">
    <title>Hello World!</title>
    <!-- https://electronjs.org/docs/tutorial/security#csp-meta-tag -->
    <meta http-equiv="Content-Security-Policy" content="script-src 'self' 'unsafe-inline';" />
  </head>
  <body>
    <button onclick="openWindow()">click to open new window</button>
  </body>
</html>

【问题讨论】:

    标签: javascript jquery html electron


    【解决方案1】:

    您需要做的就是在您单击按钮时向主进程发送一条消息,然后在我们收到该消息时在main.js 中创建一个新窗口。

    所以首先从您的openWindow() 函数向main.js 发送一条消息,如下所示:

    var ipcRenderer = require('electron').ipcRenderer;
    function openWindow () {
        ipcRenderer.send('asynchronous-message', 'createNewWindow');
    }
    

    然后我们像这样监听main.js中的消息:

    var ipcMain = require('electron').ipcMain;
    ipcMain.on('asynchronous-message', function (evt, message) {
        if (message == 'createNewWindow') {
            // Message received.
            // Create new window here.
        }
    });
    

    那么您需要做的就是在收到'createNewWindow' 消息时创建一个新窗口。

    See docs for sending a message to the main process

    See docs for receiving messages in the main process

    【讨论】:

    • 感谢您到目前为止的帮助,我们究竟如何创建一个新窗口
    • @AlexHawking 您可以像创建主窗口一样创建窗口,基本上只需再次调用createWindow()。
    【解决方案2】:

    您可以通过两种方式实现目标。

    您应该将您的 index.html 更改为喜欢此作为先决条件 在你的index.html

    <!DOCTYPE html>
    <html>
      <head>
        <meta charset="UTF-8">
        <title>Hello World!</title>
      </head>
      <body>
        <h1>Hello World!</h1>
        <body>
        <button onclick="require('./renderer.js').openWindow()">click to open new window</button>
      </body>
        <!-- All of the Node.js APIs are available in this renderer process. -->
        We are using Node.js <script>document.write(process.versions.node)</script>,
        Chromium <script>document.write(process.versions.chrome)</script>,
        and Electron <script>document.write(process.versions.electron)</script>.
    
        <script>
          // You can also require other files to run in this process
          require('./renderer.js')
        </script>
      </body>
    </html>
    
    1. 使用 ipc 通信。

    在您的main.js

    const {app, BrowserWindow, ipcMain} = require('electron')
    let browserWindows = [];
    
    function createWindow () {
      // Create the browser window.
      let newWindow = new BrowserWindow({
        width: 800,
        height: 600,
        webPreferences: {
          nodeIntegration: true
        }
      })
    
      newWindow.loadFile('index.html')
    
    
      newWindow.on('closed', function () {
        newWindow = null
      })
    
      browserWindows.push(newWindow)
    }
    
    app.on('ready', createWindow)
    
    // Quit when all windows are closed.
    app.on('window-all-closed', function () {
      if (process.platform !== 'darwin') {
        app.quit()
      }
    })
    
    ipcMain.on('createNewWindow', (evnet, args) => {
      createWindow();
    })
    

    在您的renderer.js

    const { ipcRenderer } = require('electron')
    module.exports.openWindow = event => {
      ipcRenderer.send('createNewWindow', {});
    }
    
    1. 不使用ipc。 可以直接创建。无需 ipc 直接在渲染器上创建 browserWindow 交流。因此,您在渲染器中启用节点 api。这样

    在您的renderer.js

    const {BrowserWindow} = require('electron').remote
    module.exports.openWindow = event => {
      const newWindow = new BrowserWindow({
          width: 800,
          height: 600,
          webPreferences: {
            nodeIntegration: true
          }
        })
    
      // and load the index.html of the app.
      newWindow.loadFile('index.html')
    }
    

    这样你就不用改你的main.js

    【讨论】:

    • 解决方案 #2 的重要说明:虽然它实际上并没有使用 ipcMain 模块,但 remote 模块仍然在后台使用进程间通信,并且可能导致竞争条件。由于这个原因和其他原因,它可能会让应用程序头疼,并将在下一个主要版本的 Electron 中弃用(请参阅this GitHub issue 和相关的博客文章)。
    • 好,评论。 @埃里克。但是对于只是创建重复窗口,我认为这不会出现大的性能问题。 ;)
    • 另外我想说,为了获得最佳性能,所有后端操作(文件操作、进程处理、数据库管理等)都应该在main 进程中处理。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2023-04-06
    • 1970-01-01
    • 2020-11-14
    相关资源
    最近更新 更多