简体   繁体   English

为什么看起来像来自Electron中一个菜单项的IPC消息到达了我的窗口,但是却不是从另一个菜单iteam发送时却到达了我的窗口?

[英]Why does it look like IPC messages from one menu item in Electron reach my window, but not when sent from another menu iteam?

I have a simple application that needs to run a background process to get some data. 我有一个简单的应用程序,需要运行一个后台进程来获取一些数据。 I would like to show a loading indicator while the data is being retrieved and I am having trouble with getting that done. 我想在检索数据时显示一个加载指示器,但在完成任务时遇到了麻烦。

I am using ipcrenderer to receive the message in the main window. 我正在使用ipcrenderer在主窗口中接收消息。 My code is below: 我的代码如下:

//// main.js

const electron = require('electron');
const url = require('url');
const path = require('path');

const {
  app,
  BrowserWindow,
  Menu,
  ipcMain
} = electron

// SET ENV
//process.env.NODE_ENV = 'production';

let mainWindow;
let addWindow;
let workerWindow;

// Listen for app to be ready
app.on('ready', function () {
  // Create new window
  mainWindow = new BrowserWindow({});
  // Load the HTML file into the window
  mainWindow.loadURL(url.format({
    pathname: path.join(__dirname, 'mainWindow.html'),
    protocol: 'file',
    slashes: true
  }));

  // Quit app when closed
  mainWindow.on('closed', function () {
    app.quit();
  })

  // Build menu from menu template
  const mainMenu = Menu.buildFromTemplate(mainMenuTemplate);
  // Insert menu
  Menu.setApplicationMenu(mainMenu);
});

// Handle create worker window
function createWorkerWindow() {
  mainWindow.webContents.send('status:showLoading'); // This does NOT work
  // Create new window
  workerWindow = new BrowserWindow({
    width: 300,
    height: 200,
    title: 'workerWindow',
    show: process.env.NODE_ENV == 'production' ? false : true
  });
  // Load the HTML file into the window
  workerWindow.loadURL(url.format({
    pathname: path.join(__dirname, 'worker.html'),
    protocol: 'file',
    slashes: true
  }));
  // Garbage collection
  workerWindow.on('close', function () {
    workerWindow = null;
  })
  mainWindow.webContents.send('status:hideLoading'); // This does NOT work
}

// Catch item:add-worker
ipcMain.on('item:add-worker', function(e, item){
  console.log(item);
  mainWindow.webContents.send('item:add-worker', item);
  workerWindow.close();
});


// Create menu template
const mainMenuTemplate = [{
  label: 'File',
  submenu: [
    {
      label: 'Add Item from Worker',
      click() {
        mainWindow.webContents.send('status:showLoading'); // This does NOT work
        createWorkerWindow();      
      }
    },
    {
      label: 'Clear Items',
      click(){
        mainWindow.webContents.send('item:clear'); // This works
      }
    },
    {
      label: 'Show Loading',
      click(){
        mainWindow.webContents.send('status:showLoading'); // This works
      }
    },
    {
      label: 'Hide Loading',
      click(){
        mainWindow.webContents.send('status:hideLoading') // This works
      }
    },
    {
      label: 'Quit',
      accelerator: process.platform == 'darwin' ? 'Command+Q' : 'Ctrl+Q',
      click() {
        app.quit();
      }
    }
  ]
}];

When I use the Show Loading and Hide Loading menu items, the main window receives the message and does what it needs to do. 当我使用“ Show Loading和“ Hide Loading项”菜单项时,主窗口会收到消息并执行所需的操作。 However, when I click the Add Item from Worker menu item, the message appears to not reach the main window. 但是,当我单击“ Add Item from Worker菜单项时,该消息似乎未到达主窗口。

 <!-- mainWindow.html --> <!DOCTYPE html> <html lang="en"> <head> <meta http-equiv="Content-Security-Policy" content="default-src file: https:"> <title>Shopping List</title> <!-- Compiled and minified CSS --> <link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/materialize/1.0.0-beta/css/materialize.min.css"> <link rel="stylesheet" href="mainWindow.css"> </head> <body> <nav> <div class="nav-wrapper"> <a class="brand-logo center">Shopping List</a> <div id="loadingIndicator" class="progress"> <div class="indeterminate"></div> </div> </div> </nav> <ul></ul> <script src="mainWindow.js"></script> </body> </html> 

//// mainWindow.js

// Show Loading
ipcRenderer.on('status:showLoading', function(){
    document.getElementById('loadingIndicator').style.display = 'block';
}); 

// Hide Loading
ipcRenderer.on('status:hideLoading', function(){
    document.getElementById('loadingIndicator').style.display = 'none';
});

I tried to add the mainWindow.webContents.send('status:showLoading'); 我试图添加mainWindow.webContents.send('status:showLoading'); line in side the click() function for the menu item and inside the createWorkerWindow() function. 线一侧的click()菜单项和内部功能createWorkerWindow()函数。 Neither appear to work. 两者似乎都不起作用。

Any insight would be much appreciated. 任何见解将不胜感激。

Thank you. 谢谢。

The problem is that loading a url in a browser window isn't synchronous so when it runs createWorkerWindow it will send the status:showLoading message then it'll create the worker window and send the status:hideLoading all in a split second. 问题在于,在浏览器窗口中加载URL是不同步的,因此当它运行createWorkerWindow ,它将发送status:showLoading消息,然后将创建工作器窗口并发送status:hideLoading If you wanted to hide the loading window after the worker window has finished loading you can use: 如果要在工作程序窗口完成加载后隐藏加载窗口,可以使用:

workerWindow.webContents.on('did-finish-load', function () {
    mainWindow.webContents.send('status:hideLoading');
});

Although keep in mind this will run when any url is loaded not just the first one. 尽管请记住,这将在加载任何URL而不只是第一个URL时运行。

did-finish-load docs did-finish-load文档

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM