8. Menu

原文:https://github.com/electron/electron/blob/master/docs/api/menu.md
译者:Lin

创建原生应用菜单和右键菜单

进程:主进程

new Menu()

创建一个新的菜单。

静态方法

menu类有以下静态方法:

Menu.setApplicationMenu(menu)

  • menu Menu类型

MacOS中设置menu作为应用菜单。Windows和Linux中,menu将被设置为每个窗口的顶部菜单。

注意:这个接口必须在app模块的ready事件之后调用。

Menu.getApplicationMenu()

返回值为Menu类型 - 如果设置了应用的菜单则返回应用的菜单,如果没有设置则返回null

Menu.sendActionToFirstResponder(action) MacOS

  • action String类型

action发送给应用的第一响应器。这将被用来模仿默认的Cocoa菜单行为,通常你只使用MenuItemrole属性。

查看macOS Cocoa Event Handling Guide来获取更多关于MacOS的原生actions的信息。

Menu.buildFromTemplate(template)

  • template MenuItemConstructorOptions[]类型

返回值为Menu类型

一般情况下,template只是一个构成一个MenuItemoptions组成的数组。用法可以参考上面。

你也可以将其他字段添加到template的元素中,然后它们将成为构成菜单项的属性。

实例的方法

menu对象有以下实例方法:

menu.popup([browserWindow, options])

  • browserWindow BrowserWindow类型(可选参数)- 默认是聚焦的窗口。
  • options Object类型(可选参数)
    • x Number类型(可选参数)- 默认是当前鼠标光标的位置
    • y Number类型 (如果设置了x则必须设置这个选项) - 默认是当前鼠标光标的位置。
    • async Boolean类型(可选参数)- 设置为true则这个方法的返回值立刻被调用,设置为false则在菜单被选择或关闭后调用返回值。默认为false
    • positioningItem Number类型(可选参数)MacOS - 被放置在鼠标光标下指定坐标的菜单项的索引。默认为-1

browserWindow中作为右键菜单弹出这个菜单。

menu.closePopup([browserWindow])

  • browserWindow BrowserWindow类型(可选参数)- 默认是聚焦的窗口。

browserWindow中关闭右键菜单。

menu.append(menuItem)

  • menuItem MenuItem类型

添加菜单项到菜单中。

menu.insert(pos, menuItem)

  • pos Integer类型
  • menuItem MenuItem类型

插入menuItem到菜单的pos位置。

实例的属性

menu对象有以下属性:

menu.items

一个包含了菜单的项的MenuItem[]类型数组。

每个Menu包含了多个MenuItem,并且每个MenuItem可以又一个子菜单。

例子

Menu类只在主进程中有效,但是你也可以在渲染线程中通过remote模块来使用它。

const {app, Menu} = require('electron')

const template = [
{
    label: 'Edit',
    submenu: [
    {
        role: 'undo'
    },
    {
        role: 'redo'
    },
    {
        type: 'separator'
    },
    {
        role: 'cut'
    },
    {
        role: 'copy'
    },
    {
        role: 'paste'
    },
    {
        role: 'pasteandmatchstyle'
    },
    {
        role: 'delete'
    },
    {
        role: 'selectall'
    }
    ]
},
{
    label: 'View',
    submenu: [
    {
        role: 'reload'
    },
    {
        role: 'forcereload'
    },
    {
        role: 'toggledevtools'
    },
    {
        type: 'separator'
    },
    {
        role: 'resetzoom'
    },
    {
        role: 'zoomin'
    },
    {
        role: 'zoomout'
    },
    {
        type: 'separator'
    },
    {
        role: 'togglefullscreen'
    }
    ]
},
{
    role: 'window',
    submenu: [
    {
        role: 'minimize'
    },
    {
        role: 'close'
    }
    ]
},
{
    role: 'help',
    submenu: [
    {
        label: 'Learn More',
        click () { require('electron').shell.openExternal('https://electron.atom.io') }
    }
    ]
}
]

if (process.platform === 'darwin') {
template.unshift({
    label: app.getName(),
    submenu: [
    {
        role: 'about'
    },
    {
        type: 'separator'
    },
    {
        role: 'services',
        submenu: []
    },
    {
        type: 'separator'
    },
    {
        role: 'hide'
    },
    {
        role: 'hideothers'
    },
    {
        role: 'unhide'
    },
    {
        type: 'separator'
    },
    {
        role: 'quit'
    }
    ]
})
// Edit menu.
template[1].submenu.push(
    {
    type: 'separator'
    },
    {
    label: 'Speech',
    submenu: [
        {
        role: 'startspeaking'
        },
        {
        role: 'stopspeaking'
        }
    ]
    }
)
// Window menu.
template[3].submenu = [
    {
    label: 'Close',
    accelerator: 'CmdOrCtrl+W',
    role: 'close'
    },
    {
    label: 'Minimize',
    accelerator: 'CmdOrCtrl+M',
    role: 'minimize'
    },
    {
    label: 'Zoom',
    role: 'zoom'
    },
    {
    type: 'separator'
    },
    {
    label: 'Bring All to Front',
    role: 'front'
    }
]
}

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

渲染进程

下面的例子是在网页(渲染进程)中使用remote模块来动态的创建一个菜单,并且当用户右键点击页面时展示它:

<!-- index.html -->
<script>
const {remote} = require('electron')
const {Menu, MenuItem} = remote

const menu = new Menu()
menu.append(new MenuItem({label: 'MenuItem1', click() { console.log('item 1 clicked') }}))
menu.append(new MenuItem({type: 'separator'}))
menu.append(new MenuItem({label: 'MenuItem2', type: 'checkbox', checked: true}))

window.addEventListener('contextmenu', (e) => {
e.preventDefault()
menu.popup(remote.getCurrentWindow())
}, false)
</script>

MacOS应用菜单的注意事项

MacOS有一个和Windows以及Linux完全不同的风格。这里有一些可以使你的应用的菜单更像原生菜单的注意事项。

标准菜单

MacOS中有许多系统定义的标准菜单,比如说Services(服务)Windows(窗口)菜单。要使你的菜单变成一个标准菜单,你需要设置你的菜单的role为下面的值中的一个,然后Electron将识别它们并且将它们设置为标准菜单:

  • window
  • help
  • services

标准菜单的动作

MacOS有给一些菜单项提供标准动作,例如About xxxHide xxxHide Others。要给一个菜单项的动作设置为标准动作,你需要设置菜单项的role参数。

主菜单的名字

MacOS中,无论你将应用菜单的第一项的标签设置成什么,它总是你应用的名字。想要改变它,需要改变你应用包中的Info.plist文件。查看About Information Property List Files来获取更多信息。

给指定的浏览器窗口设置菜单 (Linux Windows)

浏览器窗口的setMenu方法可以设置为某一浏览器的菜单。

菜单项的位置

当使用Menu.buildFromTemplate创建一个菜单时,你可以利用positionid来控制菜单项如何放置。

MenuItemposition参数有[placement]=[id]形式,placementbeforeafterendof其中之一,id是菜单中存在项的唯一ID:

  • before - 在id对应的项的前面插入这个项。如果id对应的项不存在那么就插入到菜单的最后。
  • after - 在id对应的项的后面插入这个项。如果id对应的项不存在那么就插入到菜单的最后。
  • endof - 在包含id对应的项的逻辑组(使用分隔器创建组)的末尾插入这个项。如果id对应的项不存在,那么使用给定的id创建一个新的分隔,然后这个项将被插入到分隔器的后面。

当一个项被放置,在放置一个新的项之前,所有未放置的项被插入到这个已经放置的项的后面。所以如果你想要在同一个位置放置一组菜单项,你只需要指定这一组的第一个项的位置。

例子

模板:

[
    {label: '4', id: '4'},
    {label: '5', id: '5'},
    {label: '1', id: '1', position: 'before=4'},
    {label: '2', id: '2'},
    {label: '3', id: '3'}
]

菜单:

- 1
- 2
- 3
- 4
- 5

模板:

[
    {label: 'a', position: 'endof=letters'},
    {label: '1', position: 'endof=numbers'},
    {label: 'b', position: 'endof=letters'},
    {label: '2', position: 'endof=numbers'},
    {label: 'c', position: 'endof=letters'},
    {label: '3', position: 'endof=numbers'}
]

菜单:

- ---
- a
- b
- c
- ---
- 1
- 2
- 3
最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 212,294评论 6 493
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 90,493评论 3 385
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 157,790评论 0 348
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 56,595评论 1 284
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 65,718评论 6 386
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 49,906评论 1 290
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 39,053评论 3 410
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 37,797评论 0 268
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 44,250评论 1 303
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 36,570评论 2 327
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 38,711评论 1 341
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 34,388评论 4 332
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 40,018评论 3 316
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 30,796评论 0 21
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 32,023评论 1 266
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 46,461评论 2 360
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 43,595评论 2 350

推荐阅读更多精彩内容