astilectron
是一个Electron应用程序,通过TCP套接字提供API,允许执行Electron的方法以及捕获Electron的事件。
架构
+-----------------------+ TCP +-------------+ IPC +---------------------+
+ Client App (any Lang) |<--------->+ Astilectron +<-------->+ win1: (HTML/JS/CSS) +
+-----------------------+ +-------------+ | +---------------------++
| | +---->+ win2: (HTML/JS/CSS) +
| +----------+ | | +---------------------++
+---------+ Electron +--------+ +-->+ win3: (HTML/JS/CSS) +
+----------+ +---------------------+
语言绑定
语言绑定起着重要作用,astilectron
因为它们允许与TCP套接字进行通信,因此与任何语言的API进行交互。
我想为一种新的语言开发语言绑定
大!:)
以下是您需要了解的几件事情:
astilectron
通常包括下载和解压缩的语言绑定的责任astilectron
是electron
- TCP addr
astilectron
通过命令行参数发送,因此您的命令行调用时astilectron
应该看起来像<path to electron executable> <path to astilectron directory>/main.js <tcp addr>
GO的语言绑定
查看go-astilectron的astilectron
GO语言绑定
go-astilectron
使用GO和HTML / JS / CSS构建跨平台GUI应用程序。这是官方GO绑定astilectron,由供电电子。
现实生活中的例子
以下是一系列令人敬畏的项目go-astilectron
(如果您正在使用go-astilectron
并希望将您的项目列在此处,请提交PR):
- go-astivid用GO编写的视频工具
- GroupMatcher计划将人员分配给团体,同时尽可能地履行所有愿望
快速开始
警告:以下代码无法处理可读性的错误。但你应该!
进口 go-astilectron
要导入go-astilectron
运行:
$ go get -u github.com/asticode/go-astilectron
开始 go-astilectron
//初始化astilectron
var a, _ = astilectron。新的(astilectron。选项 {
AppName: “ <您的应用程序名称> ”,
AppIconDefaultPath: “ <您的.png图标> ”,
AppIconDarwinPath: “ <your .icns图标> ”,
BaseDirectoryPath: “ <您希望供应商安装依赖关系> “,
})
推迟一个 关闭()
//开始astilectron
a。开始()
为了使一切正常工作,我们需要获取2个依赖关系:astilectron和Electron。.Start()
通过下载源并正确设置来处理它。
如果要嵌入二进制来源,以保持唯一的二进制就可以使用NewDisembedderProvisioner功能得到适当的置备并将其连接到go-astilectron
用.SetProvisioner(p Provisioner)
。看看这个例子,看看如何使用go-bindata。
当您尝试添加自己的应用程序图标时,请注意,您需要2个图标:一个与MacOSX(.icns)兼容的图标,另一个与其他图标兼容(例如.png)。
如果没有提供BaseDirectoryPath,它将默认为可执行文件的目录路径。
大多数方法是同步器,这意味着执行它们时go-astilectron
将阻塞,直到它接收到特定的电子事件或者直到整个上下文被取消为止。这种情况.Start()
将阻止,直到它收到app.event.ready
astilectron
事件或直到整个上下文被取消为止。
创建一个窗口
//创建一个新窗口
var w, _ = a。NewWindow( “ http://127.0.0.1:4000 ”,与astilectron。 WindowOptions {
中心:astilectron PtrBool(真),
身高:astilectron PtrInt( 600),
宽度:astilectron PtrInt( 600)
})
W上。创建()
创建窗口时,您需要指定一个URL以及位置,大小等选项。
这是非常简单的,除了astilectron.Ptr*
方法,所以让我解释一下:GO不会在json编码时执行可选字段,除非你使用指针,而Electron确实处理可选字段。因此,我添加了帮助方法将int,bool和string转换为指针,并将结果中使用的指针转换为Electron。
添加听众
//在Astilectron上添加一个监听器
a。在(astilectron。 EventNameAppCrash, FUNC(E astilectron。事件)(deleteListener布尔){
astilog。错误(“ App已崩溃”)
返回
})
//在窗口
w上添加一个监听器。在(astilectron。 EventNameWindowEventResize, FUNC(E astilectron。事件)(deleteListener布尔){
astilog。Info(“ Window resized ”)
return
})
除了你可以添加听众到Astilectron以外,没有什么可说的。
玩窗户
//玩窗户
w。调整大小( 200, 200)
时间。睡觉(时间第二)
W上。最大化()
查看窗口文档以获取所有已导出方法的列表
在GO和您的网络服务器之间发送消息
在您的网络服务器中,将以下JavaScript添加到您要与之进行交互的任何页面:
< script >
//这将等待astilectron命名空间准备好
文档。的addEventListener( “ astilectron就绪”,函数(){ //这将听取GO发送的消息astilectron。听(函数(消息){ //这将消息发送回走astilectron。发送( “我很好bro “) }); })
< / script >
在您的GO应用中添加以下内容:
//听Web服务器
w发送的消息。上(astilectron。 EventNameWindowEventMessage, FUNC(E astilectron。事件)(deleteListener布尔){
VAR 米 串
即消息。解组(M)
astilog。Infof(“ Received message %s ”,m)
return
})
//发送消息到webserver
w。发送( “什么事了”)
就是这样!
注意:不用说,消息可以是字符串以外的东西。一个自定义结构体例如!
处理几个屏幕/显示
//如果有几个显示,将窗口移动到第二个显示器
var displays = a。显示()
如果 len(显示)> 1 {
时间。睡觉(时间第二)
W上。MoveInDisplay(显示[ 1 ],50,50)
}
菜单
//初始化一个新的应用程序菜单
//您可以使用窗口
var m = a执行相同的操作。NewMenu([] * astilectron。 MenuItemOptions {
{
标签:astilectron。PtrStr(“ Separator ”),
子菜单:[] * astilectron。MenuItemOptions {
{标签:astilectron。PtrStr(“ Normal 1 ”)},
{
标签:astilectron。PtrStr(“ Normal 2 ”),
的OnClick:FUNC(即astilectron 事件)(deleteListener 布尔){
astilog。信息(“正常2项已被点击”)
返回
},
},
{类型:astilectron。MenuItemTypeSeparator },
{标签:astilectron。PtrStr(“ Normal 3 ”)},
},
},
{
标签:astilectron。PtrStr(“复选框”),
子菜单:[] * astilectron。MenuItemOptions {
{检查:astilectron。PtrBool(true),标签:astilectron。PtrStr(“复选框1 ”),类型:astilectron。MenuItemTypeCheckbox },
{标签:astilectron。PtrStr(“复选框2 ”),类型:astilectron。MenuItemTypeCheckbox },
{标签:astilectron。PtrStr(“复选框3 ”),类型:astilectron。MenuItemTypeCheckbox },
},
},
{
标签:astilectron。PtrStr(“ Radio ”),
子菜单:[] * astilectron。MenuItemOptions {
{检查:astilectron。PtrBool(true),标签:astilectron。PtrStr(“ Radio 1 ”),类型:astilectron。MenuItemTypeRadio },
{标签:astilectron。PtrStr(“ Radio 2 ”),类型:astilectron。MenuItemTypeRadio },
{标签:astilectron。PtrStr(“ Radio 3 ”),类型:astilectron。MenuItemTypeRadio },
},
},
{
标签:astilectron。PtrStr(“角色”),
子菜单:[] * astilectron。MenuItemOptions {
{标签:astilectron。PtrStr(“最小化”),角色:astilectron。MenuItemRoleMinimize },
{标签:astilectron。PtrStr(“关闭”),角色:astilectron。MenuItemRoleClose },
},
},
})
//检索菜单项
//这将检索“复选框1”项目
mi, _ := m。项( 1, 0)
//手动添加监听器
//一个OnClick监听器已经直接添加到另一个菜单项
mi的选项中。在(astilectron。 EventNameMenuItemEventClicked, FUNC(E astilectron。事件) BOOL {
astilog。Infof(“菜单项已被点击。‘经过’现在状态%T ”,* E。MenuItemOptions。经过)
返回 假
})
//创建菜单
m。创建()
//操纵菜单项
mi。SetChecked( true)
//初始化一个新菜单项
var ni = m。的newitem(astilectron。 MenuItemOptions {
标签:astilectron PtrStr( “插入的”),
子菜单:[] * astilectron MenuItemOptions {
{标签:astilectron。PtrStr(“插入1 ”)},
{标签:astilectron。PtrStr(“插入2 ”)},
},
})
//将菜单项插入位置“1”
m。插入( 1,ni)
//获取子菜单
s, _ := m。子菜单( 0)
//初始化一个新的菜单项
ni = s。的newitem(astilectron。 MenuItemOptions {
标签:astilectron PtrStr( “追加”),
子菜单:[] * astilectron MenuItemOptions {
{标签:astilectron。PtrStr(“附加1 ”)},
{标签:astilectron。PtrStr(“附加2 ”)},
},
})
//动态附加菜单项
。追加(ni)
//弹出子菜单作为上下文菜单
。弹出(&astilectron。 MenuPopupOptions {PositionOptions:astilectron。 PositionOptions {X:astilectron PtrInt( 50)中,Y:astilectron PtrInt( 50)}})
//关闭弹出
秒。ClosePopup()
//破坏菜单
m。毁灭()
要知道的几件事情
- 当将角色分配给菜单项时,
go-astilectron
将无法捕获其点击事件 - 在MacOS上没有窗口菜单,只有应用程序菜单,所以我的建议是坚持一个全球的应用程序菜单,而不是创建单独的窗口菜单
对话框
在您的网络服务器中,添加以下JavaScript之一来实现任何类型的对话。
错误框
< script >
//这将等待astilectron命名空间准备好
文档。的addEventListener( ' astilectron就绪',函数(){ //这将打开对话框astilectron。 showErrorBox( “我的标题”, “我的内容”) })
< / script >
留言框
< script >
//这将等待astilectron命名空间准备好
文档。的addEventListener( ' astilectron就绪',函数(){ //这将打开对话框astilectron。 showMessageBox({消息:“我的信息”,标题:“我的标题” }) })
< / script >
打开对话框
< script >
//这将等待astilectron命名空间准备好
文档。的addEventListener( ' astilectron就绪',函数(){ //这将打开对话框astilectron。 showOpenDialog({属性: [ '中openFile ', ' multiSelections ' ],标题:“我的标题” },功能(路径){控制台。日志( “选择路径是”,
< / script >
保存对话框
< script >
//这将等待astilectron命名空间准备好
文档。的addEventListener( ' astilectron就绪',函数(){ //这将打开对话框astilectron。 showSaveDialog({标题:“我的标题” },函数(文件名){控制台。日志( “选择文件名”,文件名) } ) })
< / script >
最终代码
//设置记录器
var l <您的记录器类型 >
astilog。SetLogger(l)
//启动http服务器
http。HandleFunc( “ / ”, FUNC(瓦特HTTP。 ResponseWriter,R * HTTP。请求){
W上。写([] 字节(` <!DOCTYPE HTML>
<HTML LANG = “EN”>
<HEAD>
<META字符集= “UTF-8”>
<标题>世界,你好</ title>
</ HEAD>
<BODY>
< span id =“message”> Hello world </ span>
<script>
//这将等待astilectron命名空间准备好
document.addEventListener('astilectron-ready',function(){
//这将
收到发送的消息通过GO astilectron.listen(function(message){
document.getElementById('message'))。
innerHTML = message //这将发送一条消息给GO
astilectron.send(“我是好兄弟”)
});
})
</ script>
</ body>
</ html> `))
})
去 http ListenAndServe(“ 127.0.0.1:4000 ”,nil)
//初始化astilectron
var a, _ = astilectron。新的(astilectron。选项 {
AppName: “ <您的应用程序名称> ”,
AppIconDefaultPath: “ <您的.png图标> ”,
AppIconDarwinPath: “ <your .icns图标> ”,
BaseDirectoryPath: “ <您希望供应商安装依赖关系> “,
})
推迟一个 关闭()
//处理退出
a。HandleSignals()
一个。在(astilectron。EventNameAppCrash,FUNC(E astilectron。事件)(deleteListener 布尔){
astilog。错误(“ App已崩溃”)
返回
})
//启动astilectron:这将下载并设置依赖关系,并启动Electron应用程序
。开始()
//初始化一个新的应用程序菜单
//您可以使用窗口
var m = a执行相同的操作。NewMenu([] * astilectron。 MenuItemOptions {
{
标签:astilectron。PtrStr(“ Separator ”),
子菜单:[] * astilectron。MenuItemOptions {
{标签:astilectron。PtrStr(“ Normal 1 ”)},
{
标签:astilectron。PtrStr(“ Normal 2 ”),
的OnClick:FUNC(即astilectron 事件)(deleteListener 布尔){
astilog。信息(“正常2项已被点击”)
返回
},
},
{类型:astilectron。MenuItemTypeSeparator },
{标签:astilectron。PtrStr(“ Normal 3 ”)},
},
},
{
标签:astilectron。PtrStr(“复选框”),
子菜单:[] * astilectron。MenuItemOptions {
{检查:astilectron。PtrBool(true),标签:astilectron。PtrStr(“复选框1 ”),类型:astilectron。MenuItemTypeCheckbox },
{标签:astilectron。PtrStr(“复选框2 ”),类型:astilectron。MenuItemTypeCheckbox },
{标签:astilectron。PtrStr(“复选框3 ”),类型:astilectron。MenuItemTypeCheckbox },
},
},
{
标签:astilectron。PtrStr(“ Radio ”),
子菜单:[] * astilectron。MenuItemOptions {
{检查:astilectron。PtrBool(true),标签:astilectron。PtrStr(“ Radio 1 ”),类型:astilectron。MenuItemTypeRadio },
{标签:astilectron。PtrStr(“ Radio 2 ”),类型:astilectron。MenuItemTypeRadio },
{标签:astilectron。PtrStr(“ Radio 3 ”),类型:astilectron。MenuItemTypeRadio },
},
},
{
标签:astilectron。PtrStr(“角色”),
子菜单:[] * astilectron。MenuItemOptions {
{标签:astilectron。PtrStr(“最小化”),角色:astilectron。MenuItemRoleMinimize },
{标签:astilectron。PtrStr(“关闭”),角色:astilectron。MenuItemRoleClose },
},
},
})
//检索菜单项
//这将检索“复选框1”项目
mi, _ := m。项( 1, 0)
//手动添加监听器
//一个OnClick监听器已经直接添加到另一个菜单项
mi的选项中。在(astilectron。 EventNameMenuItemEventClicked, FUNC(E astilectron。事件) BOOL {
astilog。Infof(“菜单项已被点击。‘经过’现在状态%T ”,* E。MenuItemOptions。经过)
返回 假
})
//创建菜单
m。创建()
//在resize
var w, _ = a上创建一个带有监听器的新窗口。NewWindow( “ http://127.0.0.1:4000 ”,与astilectron。 WindowOptions {
中心:astilectron PtrBool(真),
身高:astilectron PtrInt( 600),
图标:astilectron PtrStr(<你的图标路径>),
宽度:astilectron PtrInt( 600),
})
W上。在(astilectron。EventNameWindowEventResize,FUNC(E astilectron。事件)(deleteListener 布尔){
astilog。信息(“窗口大小调整”)
返回
})
W上。上(astilectron。EventNameWindowEventMessage,FUNC(E astilectron。事件)(deleteListener 布尔){
VAR 米 串
即消息。解组(M)
astilog。Infof(“ Received message %s ”,m)
return
})
W上。创建()
//玩窗户
w。调整大小( 200, 200)
时间。睡觉(时间第二)
W上。最大化()
//如果有几个显示,将窗口移动到第二个显示器
var displays = a。显示()
如果 len(显示)> 1 {
时间。睡觉(时间第二)
W上。MoveInDisplay(显示[ 1 ],50,50)
}
//发送消息到服务器的
时间。睡觉(时间第二)
W上。发送(“什么事了”)
//操纵菜单项
时间。睡觉(时间第二)
MI。SetChecked(true)
//初始化一个新菜单项
var ni = m。的newitem(astilectron。 MenuItemOptions {
标签:astilectron PtrStr( “插入的”),
子菜单:[] * astilectron MenuItemOptions {
{标签:astilectron。PtrStr(“插入1 ”)},
{标签:astilectron。PtrStr(“插入2 ”)},
},
})
//将菜单项插入位置“1”
。睡觉(时间第二)
米 插入(1,ni)
//获取子菜单
s, _ := m。子菜单( 0)
//初始化一个新的菜单项
ni = s。的newitem(astilectron。 MenuItemOptions {
标签:astilectron PtrStr( “追加”),
子菜单:[] * astilectron MenuItemOptions {
{标签:astilectron。PtrStr(“附加1 ”)},
{标签:astilectron。PtrStr(“附加2 ”)},
},
})
//动态追加菜单项
时间。睡觉(时间第二)
秒。追加(ni)
//弹出子菜单作为上下文菜单
时间。睡觉(时间第二)
秒。弹出(&astilectron。MenuPopupOptions {PositionOptions:astilectron。PositionOptions {X:astilectron PtrInt(50)中,Y:astilectron PtrInt(50)}})
//关闭弹出
时间。睡觉(时间第二)
秒。ClosePopup()
//销毁菜单
时间 睡觉(时间第二)
米 毁灭()
//阻止模式
a。等()
引导
为了方便起见,我添加了一个引导程序来帮助第一个定时器,并避免代码重复。
注意:您不必使用引导,完全取决于您是否使用它。
引导允许您快速创建单窗口应用程序。
使用静态文件和远程信息(最好的方式)
为了使用引导与静态文件和远程消息传递,您必须:
-
遵循以下项目组织:
|--+ resources | |--+ app (contains your static files such as .html, .css, .js, .png, etc.) |--+ main.go
-
使用
MessageHandler
引导选项来处理远程消息传递 -
使用
remote messaging
您的静态文件
使用Web服务器
为了使用带有Web服务器的引导程序,您必须:
-
遵循以下项目组织:
|--+ resources | |--+ static (contains your static files such as .css, .js, .png, etc.) | |--+ templates (contains your templates .html files) |--+ main.go
-
使用
AdaptRouter
和TemplateData
引导选项来处理服务器路由
共同
-
如果您使用
RestoreAssets
引导选项,请在您的main()
方法之上添加以下注释://go:generate go-bindata -pkg $GOPACKAGE -o resources.go resources/...
并在构建二进制文件之前运行以下命令:
$ go generate main.go
-
使用
bootstrap.Run()
方法
检查出的例子进行了详细的工作实施例(见实施例下面的特定命令来运行部分)。
我想在行动中看到它!
为了使事情更加清晰,我试图在不同的例子中分割特征。
要运行任何示例,请运行以下命令:
$ go run examples/<name of the example>/main.go -v
以下是示例的列表:
- 1.basic_window创建一个显示静态.html文件的基本窗口
- 2.basic_window_events播放基本的窗口方法,并显示如何设置自己的监听器
- 3.webserver_app设置一个基本的网络服务器应用程序
- 4.remote_messaging向Web服务器发送消息并侦听任何响应
- 5.single_binary_distribution显示如何
go-astilectron
在唯一的二进制文件中使用。对于此示例,您必须运行以前的示例之一(以便存在.zip文件)并运行以下命令:
$ go generate examples/5.single_binary_distribution/main.go
$ go run examples/5.single_binary_distribution/main.go examples/5.single_binary_distribution/vendor.go -v
- 6.screens_and_displays用屏幕和显示屏播放
- 菜单创建和操作菜单
- 8.bootstrap显示如何使用引导程序。对于此示例,您必须运行以下命令:
$ go generate examples/8.bootstrap/main.go
$ go run examples/8.bootstrap/main.go examples/8.bootstrap/resources.go -v