Go-GTK 信号处理

信号处理

简介

现在我们已经把按钮添加到窗口中了,但是有一个问题:点击按钮没有反应。我们既然添加的是按钮,肯定希望当我们点击一个按钮时,能够做一些事情,这就用到了信号处理。

学习图形界面编程,我们会经常接触到“信号”这个名词。GTK中的“信号”实际上是一种软件中断。“中断”在我们生活中经常遇到,譬如,我正在房间里打游戏,突然送快递的来了,把正在玩游戏的我给“中断”了,我去签收快递( 处理中断 ),处理完成后,再继续玩我的游戏。GTK中的“信号”就是属于这么一种“中断”,当用户按下按钮的时候,就产生一个“中断”,相当于产生一个信号,接着就会处理这么一个“中断任务”(程序里体验为调用一个函数)。

按钮中常用的信号:

信号标识 触发条件
"clicked" 按下按钮且松开鼠标时触发(鼠标必须在按钮范围中)
"pressed" 按下按钮时(还没有松开鼠标)触发
"released" 释放按钮时(无论在哪松开鼠标)触发

信号注册

对于程序而言,我们按下按钮,其实就是调用一个函数来对信号进行处理。假如有函数A, B, C,我们如何确定按下按钮后只调用函数A,而不是函数 B 或 C。这时候,我们需要一种规则规定,按下按钮后就调用函数A。

我们通过控件的Connect()方法来处理对应的信号。

Connect() 方法说明:

func (v *Widget) Connect(s string, f interface{}, datas ...interface{}) int
功能:信号注册
参数:
  - v:信号发出者。可以认为我们操作的控件,如按下按钮,这个就是按钮指针
  - s:信号标志,如:"clicked"
  - f:回调函数的名称
  - datas:给回调函数传的参数。尽管是可变参数,但是只能传递一个参数,可变参数的目的是为了让用户多个选择(可以传参,或者不传)
返回值:注册函数的标志

示例程序

下面通过代码实现一个按钮的 clicked 信号,其它两个请自行测试效果。

package main

import (
	"fmt"
	"github.com/mattn/go-gtk/glib"
	"github.com/mattn/go-gtk/gtk"
	"os"
)

func main(){
	//GTK初始化操作
	gtk.Init(&os.Args)

	// 通过GTK创建窗口
	win := gtk.NewWindow(gtk.WINDOW_TOPLEVEL)

	// 设置窗体的大小
	win.SetSizeRequest(640, 480)

	// 设置窗体标题
	win.SetTitle("GTK窗口")

	// 创建按钮
	b := gtk.NewButton()
	// 设置按钮大小
	b.SetSizeRequest(80, 32)
	// 设置按钮内容
	b.SetLabel("点击")

	// 设置按钮点击事件
	b.Connect("clicked", BtnClick, "点我干嘛~")

	// 创建布局
	layout := gtk.NewFixed()
	// 将按钮 b 添加到布局中
	layout.Add(b)

	// 放在布局的指定位置
	layout.Put(b, 0, 0)
	// 移动按钮的位置,必须先Put(),再用Move()
	layout.Move(b, 280, 224)

	// 将布局放在界面中显示
	win.Add(layout)

	// 将界面显示
	win.ShowAll()

	// 调用GTK下的main运行程序
	gtk.Main()
}

// 按钮 b 信号处理的回调函数
func BtnClick(ctx *glib.CallbackContext){
	// 获取用户传递的参数,空接口类型
	arg := ctx.Data()
	// 对数据进行类型断言
	data, ok := arg.(string)
	// 如果 ok == true,说明类型断言正确
	if ok{
		fmt.Println(data)
	}
}

或者可以通过匿名函数来实现:

package main

import (
	"fmt"
	"github.com/mattn/go-gtk/glib"
	"github.com/mattn/go-gtk/gtk"
	"os"
)

func main(){
	//GTK初始化操作
	gtk.Init(&os.Args)

	// 通过GTK创建窗口
	win := gtk.NewWindow(gtk.WINDOW_TOPLEVEL)

	// 设置窗体的大小
	win.SetSizeRequest(640, 480)

	// 设置窗体标题
	win.SetTitle("GTK窗口")

	// 创建按钮
	b := gtk.NewButton()
	// 设置按钮大小
	b.SetSizeRequest(80, 32)
	// 设置按钮内容
	b.SetLabel("点击")

	// 设置按钮点击事件
	// b.Connect("clicked", BtnClick, "点我干嘛~")

	// 使用匿名函数实现按钮点击事件处理
	b.Connect("clicked", func(ctx *glib.CallbackContext){
		// 获取用户传递的参数,空接口类型
		arg := ctx.Data()
		// 对数据进行类型断言
		data, ok := arg.(string)
		// 如果 ok == true,说明类型断言正确
		if ok{
			fmt.Println(data)
		}
	}, "点我干嘛~")

	// 创建布局
	layout := gtk.NewFixed()
	// 将按钮 b 添加到布局中
	layout.Add(b)

	// 放在布局的指定位置
	layout.Put(b, 0, 0)
	// 移动按钮的位置,必须先Put(),再用Move()
	layout.Move(b, 280, 224)

	// 将布局放在界面中显示
	win.Add(layout)

	// 将界面显示
	win.ShowAll()

	// 调用GTK下的main运行程序
	gtk.Main()
}

运行结果:

运行结果

李培冠博客

欢迎访问我的个人网站:

李培冠博客:lpgit.com

posted @ 2020-08-02 22:28  李培冠  阅读(1226)  评论(0编辑  收藏  举报