原地址:http://i.scwy.net/code/2020/070810-gui/
Golang之GUI: gotk3
Golang之GUI: gotk3 续一
Golang之GUI: gotk3 续二
最近花了点时间研究gotk3,网上资料很少,很费时。
考虑可能需要开发资源管理器/图片管理器,继续寻找golang的gui解决方案。
Github
这里有例程,我们都喜欢文档详细,例程多的东西。
依赖: sudo apt install libgtk-3-dev libcairo2-dev libglib2.0-dev
这里也讲了win环境下的安装。
网友的学习文章读一读
第一次运行例程simple,好几分钟才出来,第二次运行就快多了。也不知道它内部在干啥。
package main
import (
"log"
"github.com/gotk3/gotk3/gtk"
)
func main() {
gtk.Init(nil) // 初始化GTK而不解析任何命令行参数。
//创建顶层窗口,当销毁时关联退出事件
win, err := gtk.WindowNew(gtk.WINDOW_TOPLEVEL) 。
if err != nil {
log.Fatal("Unable to create window:", err)
}
win.SetTitle("Simple Example")
win.Connect("destroy", func() {
gtk.MainQuit()
})
// 添加标签控件
l, err := gtk.LabelNew("Hello, gotk3!")
if err != nil {
log.Fatal("Unable to create label:", err)
}
// 控件加到窗口中
win.Add(l)
// 窗口大小
win.SetDefaultSize(800, 600)
// 递归显示此窗口中包含的所有小部件。
win.ShowAll()
// 开始主循环
gtk.Main()
}
中文显示正常
看起来这个例子与库README中介绍的有点不同,看看:
import (
"log"
"os"
"github.com/gotk3/gotk3/glib"
"github.com/gotk3/gotk3/gtk"
)
func main() {
const appID = "org.gtk.example"
application, err := gtk.ApplicationNew(appID, glib.APPLICATION_FLAGS_NONE)
if err != nil {
log.Fatal("Could not create application.", err)
}
//关联激活事件
application.Connect("activate", func() { onActivate(application) })
os.Exit(application.Run(os.Args))
}
func onActivate(application *gtk.Application) {
appWindow, err := gtk.ApplicationWindowNew(application)
if err != nil {
log.Fatal("Could not create application window.", err)
}
//设置窗口相关属性
appWindow.SetTitle("简单应用窗口")
appWindow.SetDefaultSize(400, 400)
appWindow.Show()
}
代码还是容易理解。appID这个感觉有点象安卓App,给每个程序一个标识,一般使用公司域名。
或者以下代码也是一样。
package main
import (
"log"
"os"
"github.com/gotk3/gotk3/glib"
"github.com/gotk3/gotk3/gtk"
)
func main() {
const appID = "org.gtk.example"
application, err := gtk.ApplicationNew(appID, glib.APPLICATION_FLAGS_NONE)
if err != nil {
log.Fatal("Could not create application.", err)
}
application.Connect("activate", func() {
appWindow, err := gtk.ApplicationWindowNew(application)
if err != nil {
log.Fatal("Could not create application window.", err)
}
appWindow.SetTitle("Basic Application.")
appWindow.SetDefaultSize(400, 400)
appWindow.Show()
})
application.Run(os.Args)
}
添加按钮
package main
import (
"fmt"
"github.com/gotk3/gotk3/glib"
"github.com/gotk3/gotk3/gtk"
"log"
"os"
)
//这部分是相同的
func main() {
const appId = "com.nayoso.example"
app, err := gtk.ApplicationNew(appId, glib.APPLICATION_FLAGS_NONE)
if err != nil {
log.Fatal("Could not create application.", err)
}
app.Connect("activate", func() {
onActivate(app)
} )
app.Run(os.Args)
}
//
func onActivate(application *gtk.Application) {
appWindow, err := gtk.ApplicationWindowNew(application)
if err != nil {
log.Fatal("Could not create application window.", err)
}
appWindow.SetTitle("Basic Application.")
appWindow.SetDefaultSize(400, 400)
buttonBox, err := gtk.BoxNew(gtk.ORIENTATION_HORIZONTAL, 2) //以水平布局创建一个容器, 第二个参数是其中控件的像素间隔
if err != nil {
log.Fatal(err)
}
appWindow.Add(buttonBox) //将布局添加到window中
button, err := gtk.ButtonNewWithLabel("Hello World") //创建一个按钮
if err != nil {
log.Fatal(err)
}
buttonBox.Add(button) //将按钮添加到box容器中
button.Connect("clicked", func() { //让我们为按钮点击添加一个函数,每次点击都会在命令行输出Hello World
fmt.Println("Hello World")
appWindow.Destroy() //摧毁窗口
})
appWindow.ShowAll() //与Show()不同在于,它会输出Window中的子控件。你可以修改,查看不同的效果
}
看看布局的例子:
package main
import (
"os"
"github.com/gotk3/gotk3/glib"
"github.com/gotk3/gotk3/gtk"
)
func main() {
const appId = "com.nayoso.example"
app, _ := gtk.ApplicationNew(appId, glib.APPLICATION_FLAGS_NONE)
app.Connect("activate", func() {
onActivate(app)
})
app.Run(os.Args)
}
func onActivate(application *gtk.Application) {
appWindow, _ := gtk.ApplicationWindowNew(application)
appWindow.SetTitle("Grid example")
//-- 以上,通常的代码输入完了,接下就是这个例子的重点
grid, _ := gtk.GridNew() //创建容器
appWindow.Add(grid) //将容器添加到window中
//现在再让我们创建一些按钮来展示grid的效果
button1, _ := gtk.ButtonNewWithLabel("Button 1")
button2, _ := gtk.ButtonNewWithLabel("Button 2")
button3, _ := gtk.ButtonNewWithLabel("Button 3")
button4, _ := gtk.ButtonNewWithLabel("Button 4")
//将buttons添加到grid中
grid.Attach(button1, 0, 0, 1, 1) //参数:左,上,宽,高
grid.Attach(button2, 1, 0, 1, 1)
grid.Attach(button3, 0, 1, 2, 1)
grid.Attach(button4, 0, 2, 1, 1)
//-- 注意一下,按钮的位置就像在一个坐标轴中,原点在左上,x轴向右,y轴向下
appWindow.ShowAll()
}
据说,可以通过GtkBuilder使用XML构建UI。
我的Ubuntu上是啥时候装上的?(sudo apt-get install glade) 运行 glade 就弹出了。
package main
import (
"log"
"os"
"github.com/gotk3/gotk3/glib"
"github.com/gotk3/gotk3/gtk"
)
func main() {
const appId = "com.nayoso.example"
app, _ := gtk.ApplicationNew(appId, glib.APPLICATION_FLAGS_NONE)
app.Connect("activate", func() {
onActivate(app)
})
app.Run(os.Args)
}
//-- 在开始我们还是使用我们熟悉的代码
func onActivate(application *gtk.Application) {
if builder, err := gtk.BuilderNewFromFile("builder.ui"); err != nil { //从文件中创建Builder
log.Fatal(err)
} else if winObj, err := builder.GetObject("window"); err != nil { //从文件中读取window对象,其实际上是Gobject
log.Fatal(err)
} else {
window := winObj.(*gtk.Window) //由于winObj是Gobject,所以我们使用类型断言得到Gtk.Window对象
application.AddWindow(window) //记得将window加入我们的application中
window.ShowAll()
}
}
主菜ui
运行后就可以看到上图中设计的样子了。
看起来ui设计器有点“博大精深”,稍后再研究。先把示例代码研究一翻。特别是去发现是否依然存在不能输入中文的问题。
看起来并没有异常。仿佛就是它。
github上搜索gogtk3,会有一些示例
GTK3 Glade示例
示例
网络通信实例