信號處理
簡介
現在我們已經把按鈕添加到窗口中了,但是有一個問題:點擊按鈕沒有反應。我們既然添加的是按鈕,肯定希望當我們點擊一個按鈕時,能夠做一些事情,這就用到了信號處理。
學習圖形界面編程,我們會經常接觸到“信號”這個名詞。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