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


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM