Electron解决白屏问题及进程之间的通信,相信你也用的到

2,317 阅读3分钟

解决白屏问题

在electron中使用 loadURL来加载窗口,会出现短暂的白屏,从给出的图片可以看出,我在mainjs中通过loadUrl加载了两个窗口

mainWindow.loadURL(resolveHtmlPath('index.html'));
image.png

在主程序在app.whenReady()准备完毕的时候,我创建了一个窗口,监听到渲染进程的动作会

app
  .whenReady()
  .then(() => {
    createWindow()
    app.on('activate', () => {
      if (mainWindow === null) createWindow();
    });
  })
  .catch(console.log);
const createWindow = async () => {
mainWindow = new BrowserWindow({
    // show: false,
    width: 1024,
    height: 728,
    transparent: true, 
    icon: getAssetPath('icon.png'),
    webPreferences: {
      preload: app.isPackaged
        ? path.join(__dirname, 'preload.js')
        : path.join(__dirname, '../../.erb/dll/preload.js'),
    },
});
mainWindow.loadURL(resolveHtmlPath('index.html'));
//监听渲染进程事件
ipcMain.on('ipc-example', async (event, arg) => {
  const msgTemplate = (pingPong: string) => `IPC test: ${pingPong}`;
  console.log(msgTemplate(arg),'收到渲染进程信息');
  showNotification()
  // event.reply('ipc-example', msgTemplate('pong'));
});

const showNotification = ()=>{
    dialogWindow = new BrowserWindow({
    width:digalogWidth,
    height:dialogHeight, 
    x:width-digalogWidth,
    y:height-dialogHeight, 
    skipTaskbar:true,
  }); 
  dialogWindow.loadURL(resolveHtmlPath('dialog.html'));
}
}
 

两个窗口都会被触发,并且载入html,所以这段时间会进入短暂的白屏,我们可以通过以下操作来解决

使用 ready-to-show 事件解决

在加载页面时,渲染进程第一次完成绘制时,如果窗口还没有被显示,渲染进程会发出 ready-to-show 事件 。 在此事件后显示窗口将没有白屏

const dialogWindow = new BrowserWindow({ show: false })
dialogWindow.once('ready-to-show', () => {
  dialogWindow.show()
})

对于官方给的以上的解释其实有点模糊,直白的理解就是show:false设置的是不自动显示,我们通过dialogwindow.show()和hide()来手动控制窗口的显示和隐藏,

窗口加载时候自带了一个ready-to-show 事件,这个事件是窗口已经载入html可以展示的状态,在这条件下再去通过show来控制窗口的显示,就能解决加载时候的白屏问题.

222.gif

image.png

解决ipcRenderer报错提示

当我使用ipcRenderer来声明一个新的监听事件的时候 发现sendMessage 是'ipc-example'的时候是正常的,但是 不给我新增新的事件,并且会出现提示 window.electron.ipcRenderer.sendMessage('ipc-example'); 即使我定义了监听事件,错误仍然存在 ipcMain.on('close-msg', async (event, arg) => { console.log('收到渲染进程信息'); dialogWindow!.hide(); }); 后续发现在preload.ts中,定义了一个名为 Channels 的类型别名,它的值是 'ipc-example'

image.png

给Channels增加多几个类型就可以解决ts的提示问题

export type Channels = 'ipc-example' | 'close-msg' | 'open-msg';

解决主进程和渲染进程通信

我想实现的主要思路:

1.渲染进程设置事件

2.发送时间给主进程

3.主进程根据渲染进程设置的时间打开窗口

监听TimePicker改变 发送ipc事件

const onChange = (time: Dayjs, timeString: string) => {
    console.log(time.format('HH:mm'));
    window.electron.ipcRenderer.sendMessage('change-time', time.format('HH:mm'));
  };
  return (
    <div>
      <div className="Hello">
        <img width="200" alt="icon" src={icon} onClick={showLoading} />
      </div>
      <h1>Choose the time:</h1>
      <Space wrap>
        <TimePicker onChange={onChange} defaultValue={dayjs('18:00', 'HH:mm')} size="large" />
      </Space>
    </div>
  );

主进程接收事件并且设置定时器

这里我希望根据我设置的时间来打开窗口,所以要用interval轮询,对窗口进行show操作

ipcMain.on('change-time', async (event, arg) => {
  timeString = arg
  if (myTimer !== null) {
    clearInterval(myTimer);
    myTimer = null;
  }
  myTimer = setInterval(() => {
    const now = dayjs().format('HH:mm');
    console.log('now', now);
    console.log('timeString', timeString);
    if(now==timeString){
      clearInterval(myTimer!);
      dialogWindow!.show();
      setTimeout(() => {
        dialogWindow!.hide();
      }, 22000);
    }
  }, 5000);
});

🙏 感谢您花时间阅读这篇文章!如果觉得有趣或有收获,请关注我的更新,给个喜欢和分享。您的支持是我写作的最大动力!✍️🌟

往期好文推荐