上一篇文章裡我們詳細介紹了signal的用法。
今天我們將介紹slot的使用。在qt中slot和signal十分相像,這次我們將實現一個能顯示16進位數位SpinBox,它繼承自QSpinbox並重寫了validate
,valurFromText
和textFromValue
這三個slot,以便能將原先的10進位整數值顯示為16進位。我們將在其中展示slot的具體用法。
slot的聲明
我們先看一下樣本:
type HexSpinbox struct { widgets.QSpinBox _ func() `constructor:"init"` _ func(int) string `slot:"textFromValue,auto"` _ func(string) int `slot:"valueFromText,auto"` _ func(string, int) gui.QValidator__State `slot:"validate,auto"` validator *gui.QRegExpValidator}
我們看到和signal一樣,需要用struct tags來指定slot和它的名字,名字一樣會被strings.Title
處理。在Qt中slot實質上是普通的函數,所以是允許擁有傳回值的。
我們同樣看到slot也可以指定auto
,沒錯對於slot,qt也會像signal一樣產生Connect[slot name]
,Disconnect[slot name]
和[slot name]
這三個函數。
這裡有一點需要特別注意,在qt中產生slot函數其實和訊號一樣,是一個空殼函數,需要用Connect[slot name]
使其和具體的函數串連,這樣才可以通過[slot name]
函數使用這個slot。而auto
則和signal會自動進行connect。
到目前為止,我們的slot其實和普通的成員函數沒什麼區別,而且在qt中signal可以和任意函數串連,那麼為什麼還要特意聲明成slot呢?
那是因為我們要對slot進行重寫,對Qt熟悉的讀者可能已經發現我們的例子裡的三個slot正是QSpinBox的slot,我們對它們進行了重寫。因為使用了moc系統,直接使用struct裡的同名函數進行重寫是無效的,所以我們需要用到slot tags。而我們例子裡類的衍生類別也可以通過slot tags來重寫基類的slots。如此一來自訂群組件將會更為方便和靈活。
slot的使用
前面提到過,想要使用slot,得先connect它,這是和Qt的重要區別之一:
// init 初始化對象,由NewHexSpinBox自動調用func (h *HexSpinbox) init() { h.SetRange(0, 255) // 我們通過正則來驗證輸入,保證只能輸入16進位數字 regexp := core.NewQRegExp2("[0-9A-Fa-f]{1,8}", core.Qt__CaseSensitive, core.QRegExp__RegExp) h.validator = gui.NewQRegExpValidator2(regexp, h)}// slots 的實現,這些slot都由spinbox自動調用// validate 對輸入進行驗證,無法通過的內容不會被顯示func (h *HexSpinbox) validate(input string, pos int) gui.QValidator__State { return h.validator.Validate(input, pos)}// textFromValue 將輸入或增加/減少後的內容轉換成string並顯示出來func (h *HexSpinbox) textFromValue(value int) string { return strconv.FormatInt(int64(value), 16)}// valueFromText 將顯示或輸入的合法內容轉換成整數intfunc (h *HexSpinbox) valueFromText(text string) int { value, _ := strconv.Atoi(text) return int(value)}// NewHexSpinbox是moc產生的建構函式,我們以後會講解box := NewHexSpinbox(nil)// 串連slot,使其可用,如果指定了auto就無需手動connect,這裡作為樣本進行示範box.ConnectValidate(box.validate)box.ConnectTextFromValue(box.textFromValue)box.ConnectValueFromText(box.valueFromText)
串連好之後我們就能調用box.Validate
,box.ValueFromText
和box.TextFromValue
啦。
// 就像signal,調用他們時串連的函數也會被調用// 一點區別在於slot擁有傳回值,所以你也可以使用變數來接收slot返回的結果box.ValueFromText("ff") // -> 255box.TextFromValue("26") // -> "1a"
當然,我們重寫這些slot不是為了在代碼裡調用的,而是為了改變SpinBox顯示行為的。
下面是main函數,對於slot的處理完成之後,像使用普通的widget一樣使用我們的HexSpinBox即可:
func main() { widgets.NewQApplication(len(os.Args), os.Args) hexSpin := NewHexSpinbox(nil) hexSpin.Show() widgets.QApplication_Exec()}
顯示效果:
怎麼樣,是不是很簡單? qt就是這樣一個簡單而又靈活的庫,後面我們還將進行跟深入的研究。如果有意見和建議歡迎在評論中指出,也歡迎大家積極提出問題。
祝玩得愉快!