![[Tutorial][Electron] Electronで文章を話すアプリを作ってみよう #2 基本機能実装編](https://casualdevelopers.com/wp-content/uploads/2017/10/electronlogo-700x300.png)
アメリカの友人と初めて職業について話していた時のことです。自分がエンジニアであることを言うと「Oh, you are patient.」と言われました。え?「患者」じゃなくて「我慢強い」という意味であることは知っていましたが、なぜ?という感じです。話を聞くと、彼は学生時代にプログラミングの授業を1回だけ取ったことがあるそうで、簡単なタイプミスですぐエラーになるのにうんざりして辞めたということでした。あーなるほど、だからpatientかー。ある意味本質をついている気がします。エンジニアは普通の人より我慢強くなければ仕事ができないということです。感情的に他人を批判しているエンジニアは三流でしょう。普通の人未満なわけですから。ま、この記事を見ている皆さんは一流に決まっていますね、こんな長話を読んでいるわけですから(笑)
余談はさておき、前回に引き続き、「文章を話すデスクトップアプリ」を作っていきましょう。
見出し
前回のおさらい
- ElectronアプリはWeb標準技術で実装できる
- Electronアプリはappオブジェクトから始まる
- appからBrowserWindowオブジェクトを生成して画面を表示している
- Chromeと同じデベロッパーツールが使える(なぜならElectronはChromiumでできているから)
1. Electron内のデータ通信の仕組み
今回からHello以上の機能を作っていくわけですが、その前にElectronアプリ内でのデータ通信の仕組みを簡単に説明します。
1-1. IPCシステム
IPCシステムとはinter-process communication systemの略称で、1つのメインプロセス(app)と複数のレンダラープロセス(BrowserWindow)との間のデータ通信の方法のことです。
[app] ipcMain.on <-------------------- ipcRenderer.send [fooWindow]
[app] barWindow.webContents.send -------> ipcRenderer.on [barWindow]
[app] ipcMain.on <-------------------- ipcRenderer.send [barWindow]
[app] fooWindow.webContents.send -------> ipcRenderer.on [fooWindow]
この図では、矢印はデータが行き来している方向を示しており、BrowserWindowオブジェクトであるfooWindowとbarWindowが通信している様子を示しています。ウィンドウ同士が直接やり取りするのではなく、必ずappを経由している点がポイントです。
1-2. 軽くドキュメントに目を通しておきましょう。
2. 基本機能を作ろう!
「文章を話すデスクトップアプリ」ってイメージできていますか?何かを作る時は設計が重要です。設計書を書く?データベース設計から始める?そんな時代は終わっています。今設計といえばUIデザインがメインになります。今はコンポーネント設計全盛期です。従来の設計書やデータベース設計が不要とは言っていませんよ。現実世界はコンピュータのように0と1だけでは無いのです。・・・なんてね(笑)というか、今回はそこまで複雑なものは作らないので。
2-1. このアプリの機能の定義
「文章を話すデスクトップアプリ」の機能は以下の3つとします。
- 文章を追加する(基本機能) ※別ウィンドウにする
- 文章を削除する(基本機能)
- 文章を話す(次回)
メインウィンドウに3つのボタン(追加、削除、話す)を用意し、それらのボタンをクリックすることで動作させます。UIは以下のようなイメージです。
今回の記事では基本機能までを作っていきます。
2-2. 基本機能の実装
フォルダ構成の確認
前回のフォルダを開き、新しくinput.htmlを作成します。フォルダ構成が問題ないことを念のため確認してください。
$ cd speak-sentences
$ ls
index.html index.js node_modules/ package-lock.json package.json
$ touch input.html
$ ls
index.html index.js input.html node_modules/ package-lock.json package.json
index.jsのコーディング
それでは、メインのJavascriptをコーディングしましょう。IPCシステムを意識すると理解が深まります。また、当たり前ですがコピペはせずにタイプしてください。コピペだとこの記事で学んだことは明日には忘れていますよ。
const electron = require("electron");
const { app, BrowserWindow, ipcMain } = electron;
let mainWindow;
let inputWindow;
app.on("ready", () => {
mainWindow = new BrowserWindow({
width: 500,
height: 500
});
mainWindow.loadURL(`file://${__dirname}/index.html`);
mainWindow.on("closed", () => app.quit());
});
function createInputWindow() {
inputWindow = new BrowserWindow({
width: 300,
height: 300
});
inputWindow.loadURL(`file://${__dirname}/input.html`);
inputWindow.on("closed", () => (inputWindow = null));
}
// Create a input window.
ipcMain.on("inputWindow:create", event => {
createInputWindow();
});
// Send a sentence to a main window.
ipcMain.on("sentence:insert", (event, sentence) => {
mainWindow.webContents.send("sentence:insert", sentence);
inputWindow.close();
});
index.htmlのコーディング
次に、メインウィンドウをコーディングしましょう。
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>Speak Sentences</title>
</head>
<body>
<h1>Speak Sentences</h1>
<button id="input-sentence">Input</button>
<button id="clear-sentences">Clear</button>
<div id="sentences"></div>
<script>
const electron = require('electron');
const { ipcRenderer } = electron;
const sentences = document.getElementById('sentences');
const insert = document.getElementById('input-sentence');
const clear = document.getElementById('clear-sentences');
// Request a input window.
insert.addEventListener('click', (event) => {
ipcRenderer.send('inputWindow:create');
});
// Clear sentences.
clear.addEventListener('click', (event) => {
sentences.innerHTML = '';
});
// Insert sentence.
ipcRenderer.on('sentence:insert', (event, sentence) => {
if (sentence.trim() === '') {
return;
}
const text = document.createTextNode(sentence);
const p = document.createElement('p');
p.appendChild(text);
sentences.appendChild(p);
});
</script>
</body>
</html>
input.htmlのコーディング
最後に、入力用のウィンドウをコーディングしましょう。
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>Input Text</title>
</head>
<body>
<form>
<div>
<label>Text: </label>
<input autofocus />
</div>
<button type="submit">Enter</button>
</form>
<script>
const electron = require('electron');
const { ipcRenderer } = electron;
// Insert text.
document.querySelector('form').addEventListener('submit', (event) => {
event.preventDefault();
const { value } = document.querySelector('input');
ipcRenderer.send('sentence:insert', value);
});
</script>
</body>
</html>
Electron実行!
$ npm run electron
以下の画面が表示され、InputボタンとClearボタンが動作すれば完成です。
新しく追加したウィンドウとメインウィンドウは問題なく連携されていますか?動かなかったらデバッグしましょう。
最後に
今回はElectronのIPCシステムを利用してアプリの基本機能を実装しました。次回はこのアプリの肝である「話す」部分を作っていきます。正直言うと、今回の記事に書いてあることを完全に理解しているのであれば余裕です。では、お楽しみに。
環境
- OS: macOS Sierra 10.12.6
- NodeJS: v8.4.0
- NPM: 5.4.0
- Electron: 1.7.6


コメントを残す