Ошибка генератора электронных событий во время app.quit с закрытием всех открытых процессов визуализации - PullRequest
0 голосов
/ 18 ноября 2018

У меня есть одно главное окно со списком всех доступных серверов с кнопкой состояния, которая имеет идентификатор сервера.Информационное окно открывается после нажатия соответствующей кнопки состояния - передача идентификатора копии информационного окна, делая кнопку статуса отключенной.Если информационное окно закрыто, информационное окно передает идентификатор в главное окно, поэтому кнопка статуса снова активируется.Для этого я использую 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);
});

Возникает следующая ошибка.

enter image description here

main.js:53 - это строка ipcMain.on('window_closed'....Кстати, если я пропущу эту строку, все будет отлично работать.

Ответы [ 3 ]

0 голосов
/ 19 ноября 2018

Вы должны использовать дочерний / родительский браузер Windows, как здесь: https://electronjs.org/docs/api/browser-window#parent-and-child-windows

Все дочерние окна станут проще:

win.getChildWindows()

https://electronjs.org/docs/api/browser-window#wingetchildwindows

0 голосов
/ 19 ноября 2018

Похоже, что происходит ваш обработчик 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);
});

Другие ваши варианты (хотя, возможно, менее оптимальные):

  1. Установите флаг, когда главное окно закрывается, и обработчик 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);
});
  1. Вы можете вызвать метод destroy вместо close, чтобы избежать запуска события close для дочерних окон. (хотя я считаю, что window_closed не является событием Electron, поэтому все зависит от того, как вы все подключили):

mainWindow.on('close', (e)=>{
    ...
    wind.destroy();
});
0 голосов
/ 19 ноября 2018

Нашел решение следующим образом;

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. Когда информационное окно закрыто, проверьте, не установлено ли оно в нуль, отправьте главному окну информационное окно, и его статусная кнопка должна быть включена;

ipcMain.on('window_closed', (e, item)=>{
    try {
        if(mainWindow !== null){
            mainWindow.webContents.send('button_enable', item);
        }
    } catch (error) {
        console.log(error);
    }
});
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...