代码之家  ›  专栏  ›  技术社区  ›  AIon

electron中两个浏览器窗口之间的通信

  •  17
  • AIon  · 技术社区  · 8 年前

    我需要构建一个跨越多个监视器屏幕的应用程序,如下所示: multiple windows on different monitors Electron支持多个窗口,但如何在它们之间进行通信?

    5 回复  |  直到 2 年前
        1
  •  37
  •   Community CDub    4 年前

    要记住的主要一点是,在Electron中,进程间通信由ipcMain(在主进程中)和IPCRender(在所有创建的窗口中)完成。如下所示: enter image description here 我在GitHub评论中看到,渲染器实例之间的直接通信是不允许的。一切都必须通过主流程。

    代码: mainProcess.js:

    function createWindow1 () {
      window1 = new BrowserWindow({width: 800,height: 600})
      window1.loadURL(`file://${__dirname}/window1.html`)
      window1.webContents.openDevTools()
      window1.on('closed', function () {
         window1 = null
      })
      return window1
    }
    function createWindow2 () {
      window2 = new BrowserWindow({width: 1000, height: 600})
      window2.loadURL(`file://${__dirname}/window2.html`)
      window2.webContents.openDevTools()
      window2.on('closed', function () {
        window2 = null
      })
      return window2
    }
    
    app.on('ready', () => {
      window1 = createWindow1();
      window2 = createWindow2();
    
      ipcMain.on('nameMsg', (event, arg) => {
      console.log("name inside main process is: ", arg); // this comes form within window 1 -> and into the mainProcess
      event.sender.send('nameReply', { not_right: false }) // sends back/replies to window 1 - "event" is a reference to this chanel.
      window2.webContents.send( 'forWin2', arg ); // sends the stuff from Window1 to Window2.
    });
    

    window1.html:

    <body>
        <input type="text" id="name" value="" placeholder="Enter your name">
        <button type="button" id="sendName" >Send the name! </button>
    </body>
    <script>
       // You can also require other files to run in this process
       require('./window1.js')
    </script>
    

    window1.js:

    const ipcRenderer = require('electron').ipcRenderer
    
    let name = document.getElementById('name');
    
    ButtonSendName = document.getElementById('sendName');
    ButtonSendName.addEventListener('click', (event) => {
      ipcRenderer.send('nameMsg', name.value);
    })
    
    ipcRenderer.on('nameReply', (event, arg) => {
      console.log(arg) // why/what is not right..
    });
    

    window2.html:

    <body>
      <p id = "showName"></p>
    </body>
    
    <script>
      require('./window2.js')
    </script>
    

    window2.js:

    const { ipcRenderer } = require('electron')
    
    showName = document.getElementById('showName')
    ipcRenderer.on('forWin2', function (event, arg){
      console.log(arg);
      showName.innerHTML = arg;
    });
    console.log("I'm Window2");
    

    演示会更好,但我不知道如何构建电子CodeBin应用程序。这张图片给了你一个想法: enter image description here

    享受电子的力量!

        2
  •  3
  •   Felix Turner    3 年前

    如果您从 渲染器 主窗口的进程,通过使用 window.open() 这避免了通过IPC呼叫进行通信的需要。 See Docs .

    例如:

    //renderer process
    let popupWindow = window.open(
      './popup.html', 
      'popup'       
      'width=800,height=600'
    );
    
    popupWindow.onload = () => {       
      //now we have access to popup window dom   
      popupWindow.document.body.appendChild(myDomElement);
    };
    

    请注意,要使其工作,您需要设置 nativeWindowOpen 初始创建主窗口时的webPreferences选项。

    // main process
    const mainWindow = new BrowserWindow({
      width: 800,
      height: 600,
      webPreferences: {
        nativeWindowOpen: true
      }
    })
    
        3
  •  2
  •   Pieter-Jan Van Robays    3 年前

    electron-multi-monitor : enter image description here

    我们的项目也有类似的问题。然而,两个浏览器窗口都必须传递JS对象&功能来回。

    通过IPC调用提出的解决方案是我们尝试的第一件事,但还不够。当您只需要传递一些小对象时,它工作得很好,但很快就会达到它的极限,因为Electron将序列化通过IPC调用传递的所有数据。

    我们前进的方式是使用 window.opener 功能。我们用电子产生一个 main 浏览器窗口,然后打开所需的 side 通过window.open()浏览窗口。电子可以在这些窗口生成时定位它们。 下一个 一边 窗口将其HTML DOM注册为其JS窗口实例 主要的 窗那样 主要的 窗口具有对 一边 windows的DOM和JS窗口实例。 从这里开始,你 主要的 窗口可以完全控制所有可用的窗口,并且可以在所有窗口上呈现新的HTML、传递JS对象、调用JS函数等等。就个人而言,我们使用 React Portals 以处理不同窗口上的渲染。

    目前我无法分享完整的示例,但如果有时间,我将创建一个github repo。

    一些已经可以帮助您前进的事情:

    • 浏览器窗口应具有相同的 affinity (见 BrowserWindow docs )
    • 使可能 nativeWindowOpen 您的webPreferences

    仅供参考:您也可以直接在浏览器中使用此技术,但它们仍然不允许您在窗口中移动

        4
  •  0
  •   Lynn Neir    6 年前

    根据您的要求,可以创建SharedWorker,作为在windows之间传输消息端口的代理。注意:SharedWorker要求所有窗口从同一源运行(可能不满足您的要求)。例如,在主窗口中创建一个MessageChannel(它提供了两个端口),然后通过SharedWorker将端口1传输到一个窗口,将端口2传输到另一个窗口。现在,两个窗口可以使用postMessage通过端口直接通信。作为一种奖励,postMessage还支持可转让。我一直在玩弄这个想法,但还没有完全开发这个库,但你可以从这里的一些正在进行的工作中得到这个想法: https://github.com/lneir/electron-direct-comm

        5
  •  0
  •   Daniel    6 年前

    每当我们讨论电子应用程序中从一个窗口到另一个窗口的通信时,您总是想考虑IPC系统,进程间通信。

    提交表单后,您可以从输入中提取文本,并向电子应用程序发送事件。

    然后,电子应用程序将触发自己的事件,并将事件发送到 mainWindow 其将接收文本并将其附加到其列表。

    您可以在二级窗口中仅使用普通JavaScript启动。html文件如下:

      document.querySelector('form').addEventListener('submit', event => {
        event.preventDefault();
      });
    

    因此,上面假设您正在使用您试图提交的表单。