【electron】ウィンドウを読み込んだらそのウィンドウにデータを送る

こんにちは〜

最近electronをコツコツ触っているので、そういう感じの投稿が多いです。

相変わらずタイトルの通りですが、例えばメインウィンドウで操作して、サブウィンドウを表示させるけど、そのサブウィンドウにデータを送りたい!って時にどうするの?というのを簡単にメモしていきます。

1.まずウィンドウを表示する

これは他のサイトとかでもよく書いてますし、特に細かく書かなくてもいいかなと。

ちなみに今回は、「メインウィンドウ→メインプロセス→サブウィンドウ生成→メインプロセスからデータを送る」という手順を取っています。

//mainwindow.js
const {ipcRenderer} = require('electron');
ipcRenderer.send("open_subwindow"); // サブウィンドウを表示して!!!

//mainprocess.js
const { BrowserWindow } = require('electron');
let mainWindow = new BrowserWindow(/*省略*/); //メインウィンドウを生成
let subWindow = null;

ipcMain.on("open_subwindow", (event) =>{  
	subWindow = new BrowserWindow({ 
		parent: mainWindow
	}); //サブウィンドウを生成
	subWindow();
});

//subwindow.js

はい。超省略版。

簡単に説明をすると、メインウィンドウではipcRenderer.sendを使って、メインプロセスに指令を送信。

メインプロセスではipcMain.onで指令を受信し、サブウィンドウを表示しています。

「parent: mainWindow」を指定する事で、メインウィンドウの子ウィンドウという扱いになるので、常に前面に出てくるタイプの子ウィンドウが完成します。

2.データを送信する

では次にデータを送信します。今回は、変数aを用意して、"noteで投稿"という文字列を入れておきます。

まずはメインプロセスに値を渡しましょう。

//mainwindow.js
const {ipcRenderer} = require('electron');
let a = "noteで投稿"; //追記
ipcRenderer.send("open_subwindow", a); // 引数を追加

//mainprocess.js
const { BrowserWindow } = require('electron');
let mainWindow = new BrowserWindow(/*省略*/); //
let subWindow = null;

ipcMain.on("open_subwindow", (event, arg) =>{   //受け取り引数を追加
	subWindow = new BrowserWindow({ 
		parent: mainWindow
	}); //サブウィンドウを生成
	subWindow();
});

//subwindow.js

3行ほど書き換え、追加をしました。これは普通にelectronを使っていたらするのではないでしょうか?特に説明する事はなさそう・・・。

3.サブウィンドウでデータを受け取る方法を考える。

ではタイトルでの本題。どうやってメインプロセスからサブウィンドウに投げましょうか。

普通に非同期通信する場合は、event.sender.sendを使えば返せます。

ただしこれは、元のウィンドウに投げるものなので、サブウィンドウには届きません。

調べてみると、プロセスからウィンドウに投げる方法はあるみたいです。

win.webContents.send関数を使います。

ではこれを使って実装してみましょう。

//mainwindow.jsは同じなので省略

//mainprocess.js
const { BrowserWindow } = require('electron');
let mainWindow = new BrowserWindow(/*省略*/); //
let subWindow = null;

ipcMain.on("open_subwindow", (event, arg) =>{   //受け取り引数を追加
	subWindow = new BrowserWindow({ 
		parent: mainWindow
	}); //サブウィンドウを生成
	subWindow();

    subWindow.webContents.send("subwindow_send",arg); //データを送信!!
 });

//subwindow.js
ipcRenderer.on("subwindow_send", (event, a) => { // ここで受け取って、logを出す!
    console.log(a + " received!");
});

どうでしょうか。多分これは上手くいきません。

何故か。まだ読み込まれてないからです。(electron-logを使って実行順序を確かめると、データを送信した後に、受信のイベントを設定していた)

4.サブウィンドウの読み込みが完了したらイベントを送信

では、読み込みが終わったら投げればいいのでは?

という事で、読み込みが終わるのを待ってから投げるコードを追記します。

調べてみると、ready-to-showというイベントがあるみたいなので、これを使います。

//mainwindow.jsは同じなので省略

//mainprocess.js
const { BrowserWindow } = require('electron');
let mainWindow = new BrowserWindow(/*省略*/); //
let subWindow = null;

ipcMain.on("open_subwindow", (event, arg) =>{  
	subWindow = new BrowserWindow({ 
		parent: mainWindow
	}); 
	subWindow();
    subWindow.on("ready-to-show",() => { // イベントを追加
        subWindow.webContents.send("subwindow_send",arg); 
    });
 });

//subwindow.js
ipcRenderer.on("subwindow_send", (event, a) => { 
    console.log(a + " received!");
});

これでどうでしょうか。自分は少なくともこれで動きませんでした。

なぜか。ready-to-showが呼ばれないから。

newの直後に移動させても、何秒待ったとしても、自分の環境では呼ばれませんでした。(もし呼ばれた人いたらこれで大丈夫・・・なのかな?)

5.結局どうやるの

(そろそろこのくだり長いと思ってる人いそう)

で、どうするか。did-finish-loadイベントを使います。

ただこのイベントは、BrowserWindow自体が持っているイベントではなく、継承先(?)のwebContentsが持っているため、electronのマニュアルにはありませんでした。

//mainwindow.js 改めて記述
const {ipcRenderer} = require('electron');
let a = "noteで投稿"; 
ipcRenderer.send("open_subwindow", a); 

//mainprocess.js
const { BrowserWindow } = require('electron');
let mainWindow = new BrowserWindow(/*省略*/); //
let subWindow = null;

ipcMain.on("open_subwindow", (event, arg) =>{   
	subWindow = new BrowserWindow({ 
		parent: mainWindow
	}); 
	subWindow();
    subWindow.webContents.on('did-finish-load',() => { // イベントを変更
        subWindow.webContents.send("subwindow_send",arg);     
    });
 });

//subwindow.js
ipcRenderer.on("subwindow_send", (event, a) => { 
    console.log(a + " received!");
});

これで、無事データを送信することが出来ました。めでたしめでたし。

6.結論

send関数と、did-finish-loadを使って、データを送信する。

というかready-to-showが呼ばれない理由がわからなさすぎて、他の方法色々と試してたら3,4時間くらい使った。なんで呼ばれないんだろう?(ちなみにメインウィンドウの生成時も試してみたけど呼ばれてない)

まぁもしつまづいた人がいれば、参考にでもしてください。

ではまた〜

もしよろしければ、サポートをしていただけると今後の励みになります!!