Go-Qt5開發之信號模擬
前言
- 在這系列案例中,對自定義信號的介紹是非常少的,在Qt中沒有自定義信號總感覺少了點什麼。
- 之後的幾個信號案例,都是對信號章節的補充。
- 於是去翻qt綁定(therecipe/qt )的案例,案例使用的是tags標籤機制,但發現案例不適用,當然可能也是我不會用。
- 再接着到處找資料,網上對此介紹真的是非常的少。
- 再之後,不斷的去翻看源碼來找答案,在最近終於做出了,初始方案。
本方案,只是自己的理解,不一定對,僅供參考。
案例介紹
- 本案例是根基源碼,進行的信號機制模擬;
- 使用的是映射機制;
demo1.go
package main
import (
"fmt"
"reflect"
)
/*
映射以及函數調用
*/
func prints(f func()) {
// 函數執行
f()
}
func main() {
/*
// 解析
// 得到反射對象
fv := reflect.ValueOf(prints)
// 創建一個長度爲1的控列表
params := make([]reflect.Value, 1)
// 要傳遞的參數;此處傳遞一個匿名函數
f := func() {
fmt.Println("********")
}
// 參數設置
params[0] = reflect.ValueOf(f)
// 要調用函數
fv.Call(params)
*/
// 合併調用
reflect.ValueOf(prints).Call([]reflect.Value{reflect.ValueOf(func() {
fmt.Println("********")
})})
}
demo2.go
package main
import (
"fmt"
"reflect"
"runtime"
"strings"
)
/*
模擬qt信號 信號鏈接
*/
// 以Connect開頭
func ConnectGoSignal(f func(clicked bool)) {
// 函數執行
func(checked bool) {
//fmt.Println(checked)
f(checked)
}(true)
}
// 信號解析
func parse(f, a interface{}) {
// 解析
// 映射函數f,獲得對象
ValueObj := reflect.ValueOf(f)
// 獲取函數指針
ValuePointer := ValueObj.Pointer()
// 獲取函數名
FuncForPC := runtime.FuncForPC(ValuePointer).Name()
// 函數名切割
Split := strings.Split(FuncForPC, ".Connect")
// 獲取信號名
Split1 := Split[1]
// qt 信號:FuncForPC github.com/therecipe/qt/widgets.(*QAbstractButton).ConnectClicked-fm
// 此處處理後綴
fn := strings.TrimSuffix(Split1, "-fm")
// 首字母小寫處理
// 最終結果: test
ToLower := strings.ToLower(fn[:1]) + fn[1:]
fmt.Println("ValueObj", ValueObj)
fmt.Println("ValuePointer", ValuePointer)
fmt.Println("FuncForPC", FuncForPC)
fmt.Println("Split", Split)
fmt.Println("Split1", Split1)
fmt.Println("fn", fn)
fmt.Println("ToLower", ToLower)
// 進行信號註冊
// 此處模擬就不註冊了
// t Qt__ConnectionType
// qt.RegisterConnectionType(ValuePointer, ToLower, int64(t))
// 映射函數a,獲取a對象
ValueObjA := reflect.ValueOf(a)
// 創建一個列表,存儲a
ValueA := []reflect.Value{ValueObjA}
fmt.Println("ValueOfA", ValueObjA)
fmt.Println(reflect.TypeOf(ValueA), ValueA)
// 調用函數,傳遞參數
ValueObj.Call(ValueA)
}
func main() {
// 傳遞的匿名函數
a := func(checked bool) {
fmt.Println("recv****************************")
}
// 參數模擬
// 重新賦值
f := ConnectGoSignal
// 信號解析
parse(f, a)
// ConnectSignal 函數原型
fn := strings.TrimSuffix(strings.Split(runtime.FuncForPC(reflect.ValueOf(f).Pointer()).Name(), ".Connect")[1], "-fm")
// 進行信號註冊
// 此處模擬就不註冊了
// t Qt__ConnectionType
// qt.RegisterConnectionType(f.Pointer(), strings.ToLower(fn[:1])+fn[1:], int64(t))
fmt.Println(fn)
reflect.ValueOf(f).Call([]reflect.Value{reflect.ValueOf(a)})
}