Go语言图形界面开发GTK:信号处理

  • A+
所属分类:Golang

1 概述

前面我们学习的GTK界面都是静态的,我们按下按钮它是没有响应的,如何让它有响应呢?接下来我们一起学习GTK的信号处理。

GTK采用了信号与回调函数来处理窗口外部传来的事件、消息或信号。当信号发生时,程序自动调用为信号连接(注册)的回调函数。

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

“信号”在GTK中可以认为一种中断的标志,如按下按钮的标志为”pressed”,释放按钮的标志为”released”,这些标志就相当于 go 语言的关键字一样,我们使用的时候必须完全按照它的名字来写。需要注意的是,每个控件的信号标志不一定都一样,如按钮(GtkButton)里有”pressed”信号,窗口(GtkWindow)里就没这个信号,每个控件具体有哪个信号,应该查看帮助文档来确定。

按钮的常用信号:

| 信号标识 | 触发条件 |
| --- | --- |
| “clicked” | 按下按钮时触发 |
| “pressed” | 按下按钮时触发 |
| “released” | 释放按钮时触发 |

2 信号注册

对于程序而言,我们按下按钮,是让其调用一个函数。假如有函数A, B, C,我们如何确定按下按钮后只调用函数A,而不是函数 B 或 C。这时候,我们需要一种规则规定,按下按钮后就调用函数A,就像交通规则一样,红灯走绿灯行,信号注册函数就是做这样的事情。

信号注册函数说明:

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

3 示例程序

```
package main

import (
"fmt"
"os"

"github.com/mattn/go-gtk/glib"
"github.com/mattn/go-gtk/gtk"

)

//按钮b1信号处理的回调函数
func HandleButton(ctx glib.CallbackContext) {
arg := ctx.Data() //获取用户传递的参数,是空接口类型
p, ok := arg.(
int) //类型断言
if ok { //如果ok为true,说明类型断言正确
fmt.Println("p = ", p) //用户传递传递的参数为&tmp,是一个变量的地址
*p = 250 //操作指针所指向的内存
}

fmt.Println("按钮b1被按下")

//gtk.MainQuit() //关闭gtk程序

}

func main() {
gtk.Init(&os.Args) //环境初始化

//--------------------------------------------------------
// 主窗口
//--------------------------------------------------------
window := gtk.NewWindow(gtk.WINDOW_TOPLEVEL) //创建窗口
window.SetPosition(gtk.WIN_POS_CENTER)       //设置窗口居中显示
window.SetTitle("GTK Go!")                   //设置标题
window.SetSizeRequest(300, 200)              //设置窗口的宽度和高度

//--------------------------------------------------------
// GtkFixed
//--------------------------------------------------------
layout := gtk.NewFixed() //创建固定布局

//--------------------------------------------------------
// GtkButton
//--------------------------------------------------------
b1 := gtk.NewButton() //新建按钮
b1.SetLabel("^[email protected]")    //设置内容
//b1.SetSizeRequest(100, 50) //设置按钮大小

b2 := gtk.NewButtonWithLabel("@_~") //新建按钮,同时设置内容
b2.SetSizeRequest(100, 50)          //设置按钮大小

//--------------------------------------------------------
// 添加布局、添加容器
//--------------------------------------------------------
window.Add(layout) //把布局添加到主窗口中

layout.Put(b1, 0, 0)    //设置按钮在容器的位置
layout.Move(b1, 50, 50) //移动按钮的位置,必须先put,再用move

layout.Put(b2, 50, 100)

//--------------------------------------------------------
// 信号处理
//--------------------------------------------------------
//按钮按下自动触发"pressed",自动调用HandleButton, 同时将 &tmp 传递给HandleButton
tmp := 10
b1.Connect("pressed", HandleButton, &tmp)

//回调函数为匿名函数,推荐写法
//按钮按下自动触发"pressed",自动调用匿名函数,
b2.Connect("pressed", func() {

    fmt.Println("b2被按下")
    fmt.Println("tmp = ", tmp)

}) //注意:}和)在同一行

window.ShowAll() //显示所有的控件

gtk.Main() //主事件循环,等待用户操作

}

```

程序运行效果:
这里写图片描述

  • 我的微信
  • 这是我的微信扫一扫
  • weinxin
  • 我的微信公众号
  • 我的微信公众号扫一扫
  • weinxin