【golang-GUI開發】qt之signal和slot(二)


上一篇文章里我們詳細介紹了signal的用法。

今天我們將介紹slot的使用。在qt中slot和signal十分相像,這次我們將實現一個能顯示16進制數字的SpinBox,它繼承自QSpinbox並重寫了validatevalurFromTexttextFromValue這三個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 將顯示或輸入的合法內容轉換成整數int
func (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.Validatebox.ValueFromTextbox.TextFromValue啦。

// 就像signal,調用他們時連接的函數也會被調用
// 一點區別在於slot擁有返回值,所以你也可以使用變量來接收slot返回的結果
box.ValueFromText("ff") // -> 255
box.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就是這樣一個簡單而又靈活的庫,后面我們還將進行跟深入的研究。如果有意見和建議歡迎在評論中指出,也歡迎大家積極提出問題。

祝玩得愉快!


免責聲明!

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



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