logo
  • Home
  • ソフトウェア
    • アタッシェケースアイコン
      アタッシェケース

      ファイル暗号化ツール(Windows)

    • MarkDown#Editorアイコン
      MarkDown#Editor

      Markdownデュアルエディタ(Windows)

    • OutlineTextアイコン
      OutLineText

      Markdownによるアウトライナー(macOS)

    • OutlineTextアイコン
      BossComing

      一瞬で偽デスクトップに差し替え(Windows)

  • 開発ツール
    • Png2WinIco

      PNGからWindowsICOファイル生成(Windows)

    • SHCode-JP-Zen-Haku

      プログラミング用等幅フォント(Windows, macOS)

    • 秀丸エディタ・日付挿入マクロ

      柔軟な日付挿入可能な「秀丸エディタ」専用マクロ

    • 秀丸エディタ・Markdown強調表示定義ファイル

      「秀丸エディタ」専用の強調表示定義ファイル

  • このサイトについて
  • ブログ
  1. Home
  2. Blog
2019年07月02日 17:33 更新

Electronでメニューへ動的にチェックを入れる

hibara

2017年6月3日 16:03 Electron JavaScript Mac OSX プログラミング
Electron-icon

ElectronでMacOSアプリ作っています。

当サイトで「Open source & Free software」などと、標榜しておきながら、MacOSの方で有料アプリとして作って公開しています。(→気になる方はコチラからどうぞ)。

言い訳がましいですが、Appleのディベロッパーアカウントは1万円/年ほどかかっており、フリーで公開中のWindowsアプリのコードサイニング証明書更新など6万円/年と、すでに出銭の方が多いのではないかという状況でして。どうか忖度、願います。

そんなことはさておき、表題の件。

意外とサンプルが見つからなかったんですよね。

アプリ起動時のメニュー生成は、サンプルもいくつかみつかり、比較的簡単です。

let template = [
    {
      label: i18n.__('View'),
      submenu: [
        {
          label: i18n.__('Encoding'),
          id: 'Encoding',
          submenu: [
            {
              label: 'UTF-8',
              type: 'checkbox',
              checked: true
            },
            {
              label: 'EUC-JP',
              type: 'checkbox',
              checked: false
            },
            {
              label: 'Shift_JIS',
              type: 'checkbox',
              checked: false
            }
          ]
        }
      }
    }

  const menu = Menu.buildFromTemplate(template);
  Menu.setApplicationMenu(menu);

JSON形式でテンプレートを作っておいて、それをアプリケーションメニューとしてセットするだけです。

ただ、これですと、セットした後にメニュー内容を変更するにはどうすれば良いのしょうか? たとえば、以下のような場合です。

sample-menu

チェックボックスの変更です。たとえば、上記の例でいえば、エンコーディングの種類の変更を行いたい(その選択したメニューにチェックを入れ直したい)場合です。

これはもう構築したメニュー全体から、変更したい該当のメニューを探し出すしかありません。そこで、前述のソースコードの7行目に注目してほしいのですが、メニューアイテムの属性値に「id」を追加しています。これを頼りに検索する関数をつくります。

function getSubMenuItem(subMenuItems, id) {
  if (subMenuItems) {
    for (let i = 0; i < subMenuItems.length; i++) {
      if (subMenuItems[i].id === id) {
        return subMenuItems[i];
      }
      else if (subMenuItems[i].submenu) {
        let found = getSubMenuItem(subMenuItems[i].submenu.items, id);
        if (found) return found;
      }
    }
  }
}

const menu = Menu.getApplicationMenu();
let encodingMenu = getSubMenuItem(menu.items, 'Encoding');

これにより、変数encodingMenuには、「エンコーディング」以下のサブメニューオブジェクトが入ります。

これも関数にまとめてしまいましょう。

function clickEncodingMenu(item){
  const menu = Menu.getApplicationMenu();
  let encodingMenu = getSubMenuItem(menu.items, 'Encoding');

  // 一度、全チェックを外す
  for(let i = 0; i < encodingMenu.submenu.items.length; i++){
    encodingMenu.submenu.items[i].checked = false;
  }
  // 選択したエンコーディングをチェック
  item.checked = true;
}

ここで注意したいのが、6行目のループで使われているsubmenu.itemsです。ここ、submenuだけにしがちなので、ご注意ください。

まとめるとこうなります。

function getSubMenuItem(subMenuItems, id) {
  if (subMenuItems) {
    for (let i = 0; i < subMenuItems.length; i++) {
      if (subMenuItems[i].id === id) {
        return subMenuItems[i];
      }
      else if (subMenuItems[i].submenu) {
        let found = getSubMenuItem(subMenuItems[i].submenu.items, id);
        if (found) return found;
      }
    }
  }
}

let template = [
{
  label: i18n.__('View'),
  submenu: [
	{
	  label: i18n.__('Encoding'),
	  id: 'Encoding',
	  submenu: [
		{
		  label: 'UTF-8',
		  type: 'checkbox',
		  checked: true,
		  click: function (item) {
			clickEncodingMenu(item);
		  }
		},
		{
		  label: 'EUC-JP',
		  type: 'checkbox',
		  checked: false,
		  click: function (item) {
			clickEncodingMenu(item);
		  }
		},
		{
		  label: 'Shift_JIS',
		  type: 'checkbox',
		  checked: false,
		  click: function (item) {
			clickEncodingMenu(item);
		  }
		}
	  ]
	}
  }
}
const menu = Menu.getApplicationMenu();
let encodingMenu = getSubMenuItem(menu.items, 'Encoding');

本来ならよくあるように、’id’だけでズバッと該当のメニューを指定して変更できるのがベターなのですが、現状ではその方法がないので、メニュー内を探索して特定するしかなさそうですね。


コメントする     返信コメントをキャンセル(閉じる)

メールアドレスが公開されることはありません。

これらの HTML タグと属性を使用できます: <a href="" title=""> <abbr title=""> <acronym title=""> <b> <blockquote cite=""> <cite> <code> <del datetime=""> <em> <i> <q cite=""> <s> <strike> <strong>

*
*

このサイトはスパムを低減するために Akismet を使っています。コメントデータの処理方法の詳細はこちらをご覧ください。

HiBARA blog

日々の開発作業で気づいたこと共有を。同じところで躓いている人が、 検索で辿り着けたら良いな、というスタンスで記事を書くので不定期更新になります。

Post Categories

  • BizSpark (1)
  • C# (10)
  • C++ (2)
  • C++Builder (2)
  • C++Builder XE4 (1)
  • CoffeeScript (3)
  • DynamoDB (2)
  • Electron (1)
  • Inno Setup (3)
  • iPhone (1)
  • JavaScript (11)
  • jQuery (3)
  • Mac OSX (2)
  • Markdown (2)
  • MarkDown#Editor (5)
  • PHP (7)
  • Qt (5)
  • SHA-3 (2)
  • Smarty (2)
  • アタッシェケース (23)
  • など (2)
  • フォント (1)
  • プログラミング (33)
  • 未分類 (1)

Tags

  • DLL
  • exe
  • Inno Setup
  • NuGet
  • signtool
  • コードサイニング証明
  • サテライトアセンブリ
  • マージ
  • 光コラボレーション
  • 株式会社CL

© 2011-2023 M.Hibara

Facebook icon
Twitter icon
GitHub icon
Qiita icon