Electronデスクトップアプリ開発入門(3)

Electronデスクトップアプリ開発入門(3)

Electron APIデモから学ぶ実装テクニック ― ネイティブUIと通信

2017年2月17日

Electron API Demosで紹介されている、Electronアプリの実装テクニックを紹介。今回はネイティブUIと通信の実装方法を基礎から説明する。

尾崎 義尚
  • このエントリーをはてなブックマークに追加

はじめに

 前回は、Electronのウィンドウ管理やメニューの表示の仕方を説明した。今回は、OSネイティブ機能の呼び出しやIPC(Inter-process Communication:プロセス間通信)によるプロセス間通信を解説する。

 なお、今回もElectron API Demosというデモアプリを使う。デモアプリを動かす方法は、前回の説明を参照してほしい。

APIデモアプリ

ネイティブUI(NATIVE USER INTERFACE)

 ここでは、OSが持つファイルマネージャーやダイアログなどのネイティブUIを呼び出す機能を解説している。

▲メニュー項目の一覧に戻る

外部リンクとシステムのファイルマネージャーを開く(Open external links or system file manager)

 リスト1は、OSのシェル機能にアクセスしてファイルマネージャーとWebブラウザーを開くサンプルコードである。

JavaScript
const shell = require('electron').shell
const os = require('os')

shell.showItemInFolder(os.homedir())
shell.openExternal('http://electron.atom.io')
リスト1 shellの機能を使ってファイルマネージャーとURLを開く

 showItemInFolderメソッドにフォルダー(ここではOSのホームディレクトリ)を指定するとOSのファイルマネージャー(WindowsではExplorer、macOSではFinder)が開く。また、openExternalメソッドでURLを指定すると、OSで設定されている標準のWebブラウザーが開いて、そのURLのページに遷移する。

▲メニュー項目の一覧に戻る

システムダイアログを呼び出す(Use system dialogs)

 [ファイルを開く]や[保存]のダイアログなど、システムが標準で持っているダイアログを呼び出す。

 ●[ファイル/フォルダーを開く]ダイアログ(Open a File or Directory)

 リスト2は、OS標準の[ファイル/フォルダーを開く]ダイアログを開くサンプルコードだ(メインプロセス側)。

JavaScript
const { app, BrowserWindow } = require('electron');
const ipc = require('electron').ipcMain
const dialog = require('electron').dialog

ipc.on('open-file-dialog', function(event) {
  dialog.showOpenDialog({
    properties: ['openFile', 'openDirectory']
  }, function(files) {
    if (files) event.sender.send('selected-directory', files)
  })
})

var mainWindows = null;
app.on('ready', function() {
  mainWindow = new BrowserWindow({ width: 400, height: 100 });
  mainWindow.loadURL(`file://${__dirname}/index.html`);
  mainWindow.on('closed', () => {
    mainWindow = null;
  });
});
リスト2 [ファイル/フォルダーを開く]ダイアログを表示する(メインプロセス側: index.js)

IPCの'open-file-dialog'チャネルが呼び出されると(=メッセージ受信)、dialogモジュールのshowOpenDialogメソッドを使って[ファイルかフォルダーを開く]ダイアログを表示して*1、選択されたフォルダー(もしくはファイル)をIPCの'selected-directory'チャネルで返している(=メッセージ送信)。

  • *1 WindowsとLinuxは、ファイルとディレクトリを同時に選択できないため、'openDirectory'オプションが指定されているリスト2の場合、[フォルダーの選択]ダイアログが表示されてフォルダーのみが選択可能なので注意してほしい。

 レンダラープロセス側は、ボタンがクリックされたらIPCでメインプロセス側を呼び出すようにしてある(リスト3)。

HTML
<html>
<body>
  <span id="selected-file"></span>
  <button id="select-directory">...</button>

  <script>
    const ipc = require('electron').ipcRenderer
    const selectDirBtn = document.getElementById('select-directory')

    selectDirBtn.addEventListener('click', function(event) {
      ipc.send('open-file-dialog')
    })

    ipc.on('selected-directory', function(event, path) {
      document.getElementById('selected-file').innerHTML = `You selected: ${path}`
    })
  </script>
</body>
</html>
リスト3 選択されたファイル/フォルダーのパスを表示する(レンダラープロセス側: index.html)

ボタンがクリックされたら、IPCの'open-file-dialog'チャネルでメインプロセスを呼び出して(=メッセージ送信)、IPCの'selected-directory'チャネルで、選択されたフォルダー(もしくはファイル)のパスを受け取っている(=メッセージ受信)。

 このコードを実行してみよう(図1)。

図1 [ファイル/フォルダーを開く]ダイアログの表示と、選択結果の取得

表示されたウィンドウの[...]ボタンをクリックすると[ファイル/フォルダーを開く]ダイアログが表示される。フォルダー(もしくはファイル)を選択すると、その名前がウィンドウ上に表示される。

 あとは、選択されたフォルダー(もしくはファイル)を読み込んで表示するコードを書けばよい。

 ●[保存]ダイアログ(Save Dialog)

 [(ファイルの)保存]ダイアログも[ファイル/フォルダーを開く]ダイアログと同じように記述できる(リスト4)。

JavaScript
const { app, BrowserWindow, dialog } = require('electron');
const ipc = require('electron').ipcMain

ipc.on('save-dialog', function(event) {
  const options = {
    title: 'Save an Image',
    filters: [
      { name: 'Images', extensions: ['jpg', 'png', 'gif'] }
    ]
  }
  dialog.showSaveDialog(options, function(filename) {
    event.sender.send('saved-file', filename)
  })
})

var mainWindows = null;
app.on('ready', function() {
  mainWindow = new BrowserWindow({ width: 400, height: 150 });
  mainWindow.loadURL(`file://${__dirname}/index.html`);
  mainWindow.on('closed', () => {
    mainWindow = null;
  });
});
リスト4 [(ファイルの)保存]ダイアログを表示する(メインプロセス側: index.js)

IPCの'save-dialog'チャネルが呼び出されると(=メッセージ受信)、showSaveDialogメソッドで[(ファイルの)保存]ダイアログを表示して、指定されたファイル名を'save-file'チャネルで呼び出し元に返す(=メッセージ送信)。

 レンダラープロセス側のコードを見てみよう。

HTML
<html>
<body>
  <button id="save-dialog">Save</button>
  <div id="file-saved"></div>
  <script>
    const ipc = require('electron').ipcRenderer

    const saveBtn = document.getElementById('save-dialog')
    saveBtn.addEventListener('click', function(event) {
      ipc.send('save-dialog')
    })

    ipc.on('saved-file', function(event, path) {
      if (!path) path = 'No path'
      document.getElementById('file-saved').innerHTML = `Path selected: ${path}`
    })
  </script>
</body>
</html>
リスト5 指定されたファイルのパスを表示する(レンダラープロセス側: index.html)

[Save]ボタンがクリックされると、IPCの'save-dialog'チャネルでメインプロセスを呼び出して(=メッセージ送信)、IPCの'saved-file'チャネルで、指定されたファイル名を受け取る(=メッセージ受信)。

 このコードを実行すると、表示されたウィンドウの[Save]ボタンをクリックすると、ファイルを保存するためのダイアログが表示される。

図2 [保存]ダイアログの表示と、指定結果の取得

 ファイル名が取得できたら、あとはファイルを保存するコードを記述すればよい。

 ●エラーダイアログ(Error Dialog)

 エラーダイアログの表示は、インタラクティブにする必要がないため、起動したらすぐにダイアログを表示することにする。

HTML
const app = require('electron').app
const dialog = require('electron').dialog

app.on('ready', () => {
  dialog.showErrorBox('An Error Message', 'Demonstrating an error message.')
})
リスト6 showErrorBoxメソッドを呼び出すとエラーダイアログが表示される

 リスト6のコードを実行すると、エラーダイアログが表示される(図3)。

図3 エラーダイアログの表示
図3 エラーダイアログの表示
 ●情報ダイアログ(Information Dialog)

 情報ダイアログの表示も、エラーダイアログの表示と同様、メインプロセスだけで完結させることにする。

JavaScript
const { app, dialog } = require('electron');

app.on('ready', () => {
  const options = {
    type: 'info',
    title: 'Information',
    message: "This is an information dialog. Isn't it nice?",
    buttons: ['Yes', 'No']
  }
  dialog.showMessageBox(options, function(index) {
    console.log(index);
  })
})
リスト7 情報ダイアログを表示するコード

optionsで、表示するメッセージと、表示するボタンを指定して、showMessageBoxメソッドでダイアログを表示する。

クリックされたボタンのインデックスがindexに返ってくるのでコンソールに表示している。

 リスト7のコードを実行すると、情報ダイアログが表示される(図4)。

図4 情報ダイアログの表示と、選択インデックスの取得
図4 情報ダイアログの表示と、選択インデックスの取得

macOSの場合は、[Yes]が右に表示されるが、indexは0で返されるので注意してほしい。

▲メニュー項目の一覧に戻る

トレイにアプリを表示する(Put your app in the tray)

 通知領域(システムトレイ)にアイコンとコンテキストメニュー(前回説明)を追加する(リスト8)。

JavaScript
const path = require('path')
const electron = require('electron')
const BrowserWindow = electron.BrowserWindow
const ipc = electron.ipcMain
const app = electron.app
const Menu = electron.Menu
const Tray = electron.Tray

let appIcon = null

ipc.on('put-in-tray', function(event) {
  const iconName = process.platform === 'win32' ? 'windows-icon.png' : 'iconTemplate.png'
  const iconPath = path.join(__dirname, iconName)
  appIcon = new Tray(iconPath)
  const contextMenu = Menu.buildFromTemplate([{
    label: 'Remove',
    click: function() {
      event.sender.send('tray-removed')
    }
  }])
  appIcon.setContextMenu(contextMenu)
})

ipc.on('remove-tray', function() {
  appIcon.destroy()
})

app.on('window-all-closed', function() {
  if (appIcon) appIcon.destroy()
})

var mainWindows = null;
app.on('ready', function() {
  mainWindow = new BrowserWindow({ width: 400, height: 200 });
  mainWindow.loadURL(`file://${__dirname}/index.html`);
  mainWindow.on('closed', () => {
    mainWindow = null;
  });
});
リスト8 トレイにアプリを表示するコード(メインプロセス側: index.js)

IPCの'put-in-tray'チャネルのメッセージを受信したときに、Trayクラスをインスタンス化して、システムトレイにアイコンを表示している。

また、'remove-tray'チャネルのメッセージを受信したときに、appIcon.destroyメソッドでアイコンを削除している。

 リスト8のコードをブロックごとに解説していこう。

JavaScript
const iconName = process.platform === 'win32' ? 'windows-icon.png' : 'iconTemplate.png'
const iconPath = path.join(__dirname, iconName)
リスト9 アイコンのファイル名決定とパス作成

 IPCの'put-in-tray'チャネルのメッセージを受信したときに、Trayクラスをインスタンス化して、システムトレイにアイコンを表示している。まずリスト9に示すように、process.platformでアプリがWindows('win32')上で動作しているかどうかで分岐して、Windows用のアイコン(32px×32px、windows-icon.png)か、それ以外のアイコン(16px×16px、windows-icon.png)かを切り替えている。

 なお、これらのアイコン画像はGitHub上のElectron API Demosのソースに含まれており、具体的には以下の3種類が使われている。@2xは2倍サイズを意味し、つまり例えばWindows用のアイコンは64px×64pxが使われているということになる。

 さらに、決定したアイコン名からファイルパスを作成している。なお、__dirnameという記述から分かるように、アイコンはアプリのルートと同じディレクトリに置いている。

JavaScript
appIcon = new Tray(iconPath)
リスト10 アイコンパスを指定してTrayクラスをインスタンス化

 リスト10では、アイコンのパスを指定して、Trayクラスをインスタンス化している。これによりシステムトレイにアイコンが表示される。

JavaScript
const contextMenu = Menu.buildFromTemplate([{
  label: 'Remove',
  click: function() {
    event.sender.send('tray-removed')
  }
}])
appIcon.setContextMenu(contextMenu)
リスト11 トレイアイコンに対するメニューの定義と設定

 トレイアイコンをクリックしたときに表示されるメニューは、「コンテキストメニュー」と同じように定義をして、setContextMenuメソッドでセットすればよい。リスト11では[Remove]というメニューを表示して、クリックされたらIPCで'tray-removed'チャネルのメッセージを送信している。

JavaScript
appIcon.destroy()
リスト12 トレイアイコンのメニューを破棄

 IPCで'remove-tray'チャネルのメッセージを受信した場合、またはウィンドウが全てクローズされた場合には、destroyメソッドを呼び出して、トレイアイコンを削除している。

 レンダラープロセス側のコードも見ていこう(リスト13)。

HTML
<html>
<body>
  <button id="put-in-tray">Put in tray</button>
  <div id="tray-countdown"></div>
</body>
<script>
  const ipc = require('electron').ipcRenderer

  const trayBtn = document.getElementById('put-in-tray')
  let trayOn = false

  trayBtn.addEventListener('click', function(event) {
      if (trayOn) {
        trayOn = false
        document.getElementById('tray-countdown').innerHTML = ''
        ipc.send('remove-tray')
      } else {
        trayOn = true
        const message = 'Click demo again to remove.'
        document.getElementById('tray-countdown').innerHTML = message
        ipc.send('put-in-tray')
      }
    })
    // Tray removed from context menu on icon
  ipc.on('tray-removed', function() {
    ipc.send('remove-tray')
    trayOn = false
    document.getElementById('tray-countdown').innerHTML = ''
  })
</script>
</html>
リスト13 ボタンクリック時にトレイアイコンの表示/非表示を切り替えるコード(レンダラープロセス側: index.html)

ボタンがクリックされたときに、トレイアイコンが表示されていたらIPCの'remove-tray'チャネルのメッセージを送信して非表示にし(=トレイアイコンを削除)、表示されていなければIPCで'put-in-tray'チャネルのメッセージを送信して表示している。

 トレイアイコンをすでに表示している場合(=trayOnフラグがtrue)、IPCで'remove-tray'チャネルのメッセージを送信して、前述のメインプロセス側でトレイアイコンを削除している。表示されていない場合は、ICPで'put-in-tray'チャネルのメッセージを送信してアイコンを表示している。

 Linuxの場合は、ディストリビューションによって表示できるかが変わるが、筆者のUbuntu 16.04環境ではlibappindicator1をインストールすることで表示できた。インストールコマンドはリスト14のとおり。

Bash
sudo apt-get install libappindicator1
リスト14 libappindicator1のインストール

 その他のTray機能はAPIリファレンスを参照してほしい。

通信(COMMUNICATION)

 すでに前回から何度も登場しているが、ここではIPC(Inter-Process Communication:プロセス間通信)用のipcMainipcRendererモジュールを使った、メインプロセスとレンダラープロセス間の通信(同期・非同期)について解説する。

▲メニュー項目の一覧に戻る

非同期メッセージ(Asynchronous messages)

 非同期メッセージでは、レンダラープロセス側から送られてきたメッセージを、リスト15のようにメインプロセス側のチャネルで受け、そのメッセージに対する処理をし終わったら、呼び出し元にメッセージとしてsendして、非同期にその処理結果を返す。

JavaScript
const path = require('path')
const electron = require('electron')
const BrowserWindow = electron.BrowserWindow
const app = electron.app
const ipc = require('electron').ipcMain

ipc.on('asynchronous-message', function(event, arg) {
  event.sender.send('asynchronous-reply', 'pong')
})

var mainWindows = null;
app.on('ready', function() {
  mainWindow = new BrowserWindow({ width: 400, height: 200 });
  mainWindow.loadURL(`file://${__dirname}/index.html`);
  mainWindow.on('closed', () => {
    mainWindow = null;
  });
});
リスト15 非同期メッセージの受信と、処理結果の送信(メインプロセス側: index.js)

IPCの'asynchronous-message'チャネルでメッセージを受信すると、非同期で処理を実行し、event.sender.sendメソッドを使って送信元に処理結果を送信している。

 レンダラープロセス側でメッセージを送信し、メインプロセス側の処理結果を受信するコードの例も見てみよう(リスト16)。

HTML
<html>
<body>
  <button id="async-msg">Ping</button>
  <div id="async-reply"></div>
  <script>
    const ipc = require('electron').ipcRenderer

    const asyncMsgBtn = document.getElementById('async-msg')

    asyncMsgBtn.addEventListener('click', function() {
      ipc.send('asynchronous-message', 'ping')
    })

    ipc.on('asynchronous-reply', function(event, arg) {
      const message = `Asynchronous message reply: ${arg}`
      document.getElementById('async-reply').innerHTML = message
    })
  </script>
</body>
</html>
リスト16 非同期メッセージの送信と、処理結果の受信(レンダラープロセス側: index.html)

ボタンがクリックされたらIPCの'asynchronous-message'チャネルに'ping'というメッセージを送信している。

非同期処理が完了すると'asynchronous-reply'チャネルに処理結果が返される。

 このように非同期メッセージでは、メインプロセスとレンダラープロセスの間で呼び出し送信チャネル名と応答チャネル名を決めておき、送信チャネルのメッセージに対する処理が完了したら、応答チャネルに結果を受け取るようにする。

▲メニュー項目の一覧に戻る

同期メッセージ(Synchronous messages)

 通常は非同期で通信すればよいが、場合によっては同期で通信したいケースもあるだろう。同期メッセージでは、処理が完了してから同期的に応答を返す。

 レンダラープロセス側では、先ほどのように非同期メッセージとしてsendせずに、同期的にevent.returnValueプロパティに値をセットする(リスト17)。

JavaScript
const path = require('path')
const electron = require('electron')
const BrowserWindow = electron.BrowserWindow
const app = electron.app
const ipc = require('electron').ipcMain

ipc.on('synchronous-message', function(event, arg) {
  event.returnValue = 'pong'
})

var mainWindows = null;
app.on('ready', function() {
  mainWindow = new BrowserWindow({ width: 400, height: 200 });
  mainWindow.loadURL(`file://${__dirname}/index.html`);
  mainWindow.on('closed', () => {
    mainWindow = null;
  });
});
リスト17 同期メッセージの受信(メインプロセス)

IPCの'synchronous-message'チャネルのメッセージを受信すると、event.returnValueに処理結果を返している。

 同期メッセージを送信するメインプロセス側では、同期メッセージを送信するためのsendSyncメソッドを使い、その戻り値として処理結果を受け取る(リスト18)。

HTML
<html>
<body>
  <button id="sync-msg">Ping</button>
  <div id="sync-reply"></div>
  <script>
    const ipc = require('electron').ipcRenderer

    const syncMsgBtn = document.getElementById('sync-msg')

    syncMsgBtn.addEventListener('click', function() {
      const reply = ipc.sendSync('synchronous-message', 'ping')
      const message = `Synchronous message reply: ${reply}`
      document.getElementById('sync-reply').innerHTML = message
    })
  </script>
</body>
</html>
リスト18 同期メッセージの送信と結果の受け取り(レンダラープロセス)

ボタンがクリックされると、IPCの'synchronous-message'チャネルで同期メッセージを送信(sendSync)して、(応答チャネルではなく)戻り値として処理結果を受信する。

▲メニュー項目の一覧に戻る

非表示ウィンドウとの対話(Communicate with an invisible window)

 メインプロセスに負荷をかけないように、非表示のウィンドウ(レンダラープロセス)を起動して、それに処理をさせるテクニックを紹介しよう。

 まずは通常通り、メインプロセス側でユーザー操作用のウィンドウを表示する(リスト19)。

JavaScript
const path = require('path')
const electron = require('electron')
const BrowserWindow = electron.BrowserWindow
const app = electron.app

var mainWindows = null;
app.on('ready', function() {
  mainWindow = new BrowserWindow({ width: 400, height: 200 });
  mainWindow.loadURL(`file://${__dirname}/index.html`);
  mainWindow.on('closed', () => {
    mainWindow = null;
  });
});
リスト19 ユーザー操作用ウィンドウの表示(メインプロセス側: index.js)

 次に、ユーザー操作用ウィンドウ(レンダラープロセス:index.html、リスト20)側で、ボタンクリック時に別の非表示ウィンドウ(レンダラープロセス:invisible.html、後述のリスト24)を起動する。

HTML
<html>
<body>
  <button id="invis-msg">Invisible message</button>
  <div id="invis-reply"></div>
  <script>
    const BrowserWindow = require('electron').remote.BrowserWindow
    const ipcRenderer = require('electron').ipcRenderer
    const path = require('path')

    const invisMsgBtn = document.getElementById('invis-msg')
    const invisReply = document.getElementById('invis-reply')

    invisMsgBtn.addEventListener('click', function(clickEvent) {
      const windowID = BrowserWindow.getFocusedWindow().id
      const invisPath = 'file://' + path.join(__dirname, '/invisible.html')
      let win = new BrowserWindow({
        width: 400,
        height: 400,
        show: false
      })
      win.loadURL(invisPath)

      win.webContents.on('did-finish-load', function() {
        const input = 100
        win.webContents.send('compute-factorial', input, windowID)
      })
    })

    ipcRenderer.on('factorial-computed', function(event, input, output) {
      const message = `The factorial of ${input} is ${output}`
      invisReply.textContent = message
    })
  </script>
</body>
</html>
リスト20 ユーザー操作用のウィンドウ(レンダラープロセス側: index.html)

ボタンがクリックされたら、非表示ウィンドウを起動して、IPCで非同期メッセージをsendしている。また、処理が終わったら結果をIPCで受信している。

 リスト20のコードをブロックごとに解説していく。

JavaScript
invisMsgBtn.addEventListener('click', function(clickEvent) {
  ……省略……
  const invisPath = 'file://' + path.join(__dirname, '/invisible.html')
  let win = new BrowserWindow({
    width: 400,
    height: 400,
    show: false
  })
  win.loadURL(invisPath)
  ……省略……
})
リスト21 ボタンクリック時に非表示ウィンドウを起動

 リスト21では、ボタンがクリックされたら、show: falseで非表示にした新規ウィンドウを作成し、ロード(=起動)している。

JavaScript
const windowID = BrowserWindow.getFocusedWindow().id
……省略……
win.webContents.on('did-finish-load', function() {
  const input = 100
  win.webContents.send('compute-factorial', input, windowID)
リスト22 非表示ウィンドウのロード完了時に、非表示ウィンドウのwebContentsオブジェクトに対しIPCでメッセージを送信し、処理を実行させる

 リスト22では、非表示ウィンドウのロードが終了(=WebContentsオブジェクトのイベントであるdid-finish-loadイベントをハンドル)したら、パラメーターを指定してIPCの'compute-factorial'チャネルにメッセージを送信している。またその際、処理結果の戻し先として使えるよう、フォーカスされているウィンドウ(この例ではユーザー操作用のウィンドウ)のIDを渡している。

JavaScript
ipcRenderer.on('factorial-computed', function(event, input, output) {
  const message = `The factorial of ${input} is ${output}`
  invisReply.textContent = message
})
リスト23 非表示ウィンドウでの処理結果を応答チャネルで受信

 リスト23では、非表示ウィンドウでの計算結果をIPCの'factorial-computed'チャネルで受信して、テキストコンテンツとして表示している。

 それでは、処理を実行する非表示ウィンドウのコードを見ていこう(リスト24)。

HTML
<html>
<script type="text/javascript">
  const ipc = require('electron').ipcRenderer
  const BrowserWindow = require('electron').remote.BrowserWindow

  ipc.on('compute-factorial', function(event, number, fromWindowId) {
    const result = factorial(number)
    const fromWindow = BrowserWindow.fromId(fromWindowId)
    fromWindow.webContents.send('factorial-computed', number, result)
    window.close()
  })

  function factorial(num) {
    if (num === 0) return 1
    return num * factorial(num - 1)
  }
</script>
</html>
リスト24 非表示ウィンドウでの処理(レンダラープロセス側: invisible.html)

 IPCで'compute-factorial'チャネルのメッセージを受信すると、計算(factorial)して、パラメーターとして渡されたIDのウィンドウに処理結果を返すため、BrowserWindow.fromIdメソッドでそのウィンドウ(この例では呼び出し元であるユーザー操作用のウィンドウ)を取得して、IPCの'factorial-computed'チャネルに処理結果を返している。最後にwindow.closeメソッドでウィンドウを閉じている。

 このように非表示ウィンドウに処理を任せることで、別プロセスに複雑な処理をさせて、UIウィンドウの負荷を軽減させることもできる。

▲メニュー項目の一覧に戻る

まとめ

 今回は、ダイアログやシステムトレイなどOSのネイティブ機能呼び出しとElectronの特徴的な機能であるIPC通信によるプロセス間通信の手順について解説した。次回は、システム情報として実行環境の情報取得やクリップボードへのアクセス、PDFへの出力方法、デバッグ方法などを解説していく。

1. Electronとは? アーキテクチャ/API/インストール方法/初期設定

Windows/macOS/Linuxで実行できるデスクトップアプリをWeb技術で作ろう! Electronの概要から開発を始めて動かすところまでを解説する。

2. Electron APIデモから学ぶ実装テクニック ― ウィンドウ管理とメニュー

Electron API Demosで紹介されている、Electronアプリの実装テクニックを紹介。今回はウィンドウ管理とメニューの実装方法を基礎から説明する。

3. 【現在、表示中】≫ Electron APIデモから学ぶ実装テクニック ― ネイティブUIと通信

Electron API Demosで紹介されている、Electronアプリの実装テクニックを紹介。今回はネイティブUIと通信の実装方法を基礎から説明する。

4. Electron APIデモから学ぶ実装テクニック ― システムとメディア

Electron API Demosで紹介されている、Electronアプリの実装テクニックを紹介。今回はシステムとメディアの実装方法を基礎から説明する。

5. Electronアプリのデバッグと、パッケージ化

本格的にElectronアプリ開発を進める方に向けて、そのデバッグ方法と、製品リリースのためのパッケージ作成の方法について説明する。

サイトからのお知らせ

Twitterでつぶやこう!


Build Insider賛同企業・団体

Build Insiderは、以下の企業・団体の支援を受けて活動しています(募集概要)。

ゴールドレベル

  • 日本マイクロソフト株式会社
  • グレープシティ株式会社