我有一个主窗口,其中列出了所有可用的服务器以及带有服务器ID的状态按钮。按下相关状态按钮后,将打开一个信息窗口-将ID传递给信息窗口的副本,从而使状态按钮处于禁用状态。如果关闭了信息窗口,则信息窗口会将ID传递回主窗口,从而使状态按钮再次启用。为此,我使用main.js
作为代理,侦听渲染器进程并在主窗口和信息窗口之间交换信息。
我想做的是列出服务器。如果它们在线,则一次从不同渲染器进程(信息窗口的实例)上的多个服务器获取一些信息。
问题是,如果主窗口关闭,我希望所有信息窗口都关闭。
// App ready
app.on('ready', ()=>{
mainWindow = new BrowserWindow({x : 0, y : 0 , width : 500, height: 600});
mainWindow.loadURL(url.format({
pathname : path.join(__dirname, 'windows', 'mainWindow.html'),
protocol : 'file',
slashes : true
}));
// Close the app if main window closed
mainWindow.on('close', (e) => {
let openedOnes = BrowserWindow.getAllWindows();
openedOnes.forEach(wind => {
if(wind.hasOwnProperty('custom')){
wind.close();
};
});
app.quit();
});
});
在创建信息窗口时,我向BrowserWindow
对象添加了一个自定义字段:
BrowserWindow {
_events:
{ blur: [Function],
focus: [Function],
show: [Function: visibilityChanged],
hide: [Function: visibilityChanged],
minimize: [Function: visibilityChanged],
maximize: [Function: visibilityChanged],
restore: [Function: visibilityChanged],
close: [Function: callIntoRenderer] },
_eventsCount: 8,
devToolsWebContents: [Getter],
custom: { server_id: '3' } }
因此,借助自定义字段,我可以获得所有打开的服务器信息实例。
但是当我单击关闭时,以下部分在main.js
处失败;
ipcMain.on('window_closed', (e, item)=>{
mainWindow.webContents.send('button_enable', item);
});
它会引发以下错误。
main.js:53
是行ipcMain.on('window_closed'...
。顺便说一句,如果我忽略了这一行,一切都会很好地工作。
答案 0 :(得分:1)
似乎发生了什么事,您的mainWindow
close
处理函数被触发,告诉其他窗口关闭,然后触发了window_closed
事件(我想这是您自定义的事件添加?),并在调用mainWindow.webContents.send
时,mainWindow
的关闭处理程序完成,窗口关闭。
在发送消息之前,只需添加isDestroyed
检查,就像这样:
ipcMain.on('window_closed', (e, item)=>{
if (mainWindow && !mainWindow.isDestroyed())
mainWindow.webContents.send('button_enable', item);
});
您的其他选择(虽然可能不是最佳选择)是
window_closed
处理程序看到该标志,则将其退出(如果我们要关闭所有内容,肯定没有理由发送button_enable
消息)下):
let mainWindowIsClosing = false;
mainWindow.on('close', (e)=>{
mainWindowIsClosing = true;
...
wind.close();
...
});
ipcMain.on('window_closed', (e, item)=>{
if (mainWindowIsClosing) return;
mainWindow.webContents.send('button_enable', item);
});
destroy
方法而不是close
来避免为子窗口触发close
事件。 (尽管我相信window_closed
不是电子事件,所以这取决于您如何挂钩所有内容):
mainWindow.on('close', (e)=>{
...
wind.destroy();
});
答案 1 :(得分:0)
找到了以下解决方案;
mainWindow.on('close', (e)=>{
mainWindow = null;
try{
let openedOnes = BrowserWindow.getAllWindows();
openedOnes.forEach(wind=>{
if(wind.hasOwnProperty('custom')){
wind.close();
};
});
app.quit();
}catch(e){
console.log(e);
}
});
在关闭主窗口之前,我将主窗口设置为null。关闭信息窗口后,检查其是否未设置为null,向主窗口发送信息窗口已关闭且应启用其状态按钮的信息;
ipcMain.on('window_closed', (e, item)=>{
try {
if(mainWindow !== null){
mainWindow.webContents.send('button_enable', item);
}
} catch (error) {
console.log(error);
}
});
答案 2 :(得分:0)
您应该像下面这样使用子级/父级BrowserWindows:https://electronjs.org/docs/api/browser-window#parent-and-child-windows
使用以下所有子窗口,您将变得更加轻松
win.getChildWindows()
https://electronjs.org/docs/api/browser-window#wingetchildwindows