天天看點

【golang-GUI開發】struct tags系統(二)qt的自定義元件和構造函數

今天我們來講講自定義元件和它的構造函數。

在前面的文章裡我們已經接觸了好幾個自定元件,這次的示例是一個自定義對話框,他有一個about按鈕,點選按鈕可以顯示出Qt的資訊或者使用者輸入的資訊。這是效果圖:

【golang-GUI開發】struct tags系統(二)qt的自定義元件和構造函數
【golang-GUI開發】struct tags系統(二)qt的自定義元件和構造函數
【golang-GUI開發】struct tags系統(二)qt的自定義元件和構造函數
下面我們就來重點講解自定義元件和它的構造函數吧。

構造函數的聲明

先上代碼:

type MyDialog struct {
	widgets.QDialog
	
	_ func() `constructor:"init"`
	
	_ func(string) `signal:"showAbout"`
	_ func() `signal:"showAboutQt"`
	
	_ func(bool)   `slot:"aboutClicked,auto"`
	_ func(string) `slot:"enableAboutButton,auto"`
	
	label         *widgets.QLabel
	edit          *widgets.QLineEdit
	testCheck     *widgets.QCheckBox
	isDialogCheck *widgets.QCheckBox
	aboutButton   *widgets.QPushButton
	closeButton   *widgets.QPushButton
}
           

構造函數用 “ _ func() `constructor:"init"` ”

來聲明,目前隻支援無參數的構造函數,以後會逐漸擴充。之後我們需要實作一個名字是

init

的類方法,這是構造函數的實體。

qt的moc系統遇到派生自QObject及其派生類的類時,會自動生成一個

New[type name]

的函數(type name也會被Title處理),它會傳回一個已經初始化的指向自定義類型執行個體的指針,這個函數的參數類型會根據最先繼承的QObject或是其派生類的

New[type name]

而定,舉個例子:

假設我們的類繼承自

QLineEdit

,在qt裡有

NewQLineEdit(parent QWidget_ITF)

,那麼我們這個類自動生成的

New[type name]

就會是

New[type name](parent QWidget_ITF)

;

再舉個例子,我們的元件繼承自QWidget,它有

NewQWidget(parent QWidget_ITF, fo core.Qt__WindowType)

,那麼我們的類會自動生成

New[type name](parent QWidget_ITF, fo core.Qt__WindowType)

我們實作的init會被

New[type name]

自動調用。不過這裡有個問題,如果我想實作自己的

New[type name]

函數呢,比如需要加上自己的配置參數,其實也很簡單,我們再定義一個

New[type name]WithXXX

然後在其中調用

New[type name]

即可,向下面這樣:

func NewYourTypeWithConfig(conf Config) *YourType {
    // 假設繼承自QWidget
	obj := NewYourType(nil, 0)
	// 一些額外的初始化處理
	// 一般在init裡進行界面的初始化,如果你的界面初始化依賴外部資料,那麼可以不指定constructor,
	// 這樣New[type name]就不會自動調用init,你可以在自定義函數裡調用它。
	obj.conf = conf
  
	// obj.init()
}
           

這就是構造函數的全貌了,接着我們來看看界面的初始化,也就是我們要實作的init函數:

func (d *MyDialog) init() {
	d.label = widgets.NewQLabel2("About &Text:", d, 0)
	d.edit = widgets.NewQLineEdit(nil)
    // 将label和edit綁定
	d.label.SetBuddy(d.edit)
	
	d.testCheck = widgets.NewQCheckBox2("Test case", nil)
    // 選擇顯示自定義元件的About還是Qt的About
	d.isDialogCheck = widgets.NewQCheckBox2("Show &Dialog's about", nil)

    // 當使用者輸入要顯示的内容時才可以點選
    d.aboutButton = widgets.NewQPushButton2("&About", nil)
	d.aboutButton.SetDefault(true)
	d.aboutButton.SetEnabled(false)
	
	d.closeButton = widgets.NewQPushButton2("&Close", nil)
	d.closeButton.ConnectClicked( func(_ bool) {
		d.Done(0)
	})
	
	d.edit.ConnectTextChanged(d.EnableAboutButton)
	d.aboutButton.ConnectClicked(d.aboutClicked)
	
	topLeftLayout := widgets.NewQHBoxLayout()
	topLeftLayout.AddWidget(d.label, 0, 0)
	topLeftLayout.AddWidget(d.edit, 0, 0)
	
	leftLayout := widgets.NewQVBoxLayout()
	leftLayout.AddLayout(topLeftLayout, 0)
	leftLayout.AddWidget(d.testCheck, 0, 0)
	leftLayout.AddWidget(d.isDialogCheck, 0, 0)
	
	rightLayout := widgets.NewQVBoxLayout()
	rightLayout.AddWidget(d.aboutButton, 0, 0)
	rightLayout.AddWidget(d.closeButton, 0, 0)
	rightLayout.AddStretch(0)
	
	mainLayout := widgets.NewQHBoxLayout()
	mainLayout.AddLayout(leftLayout, 0)
	mainLayout.AddLayout(rightLayout, 0)
	d.SetLayout(mainLayout)
	
	d.SetWindowTitle("about")
}
           

代碼也很簡單,初始化widgets之後使用

QBoxLayout

進行布局,然後連接配接一下

closeButton

,使用

QDialog::done

退出dialog。

我們設定

aboutButton

初始為不可點選狀态,直到有輸入内容存在在改變它的狀态,這一步由自動連接配接的

enableAboutButton

槽來完成;

然後是點選

aboutButton

時會檢查

isDialogCheck

的值來确定彈出哪種對話框,這一步由

aboutClicked

槽來完成:

func (d *MyDialog) aboutClicked(_ bool) {
	text := d.edit.Text()
	
	if d.isDialogCheck.IsChecked() {
		d.ShowAbout(text)
	} else {
		d.ShowAboutQt()
	}
}

func (d *MyDialog) enableAboutButton(text string) {
	if text != "" {
		d.aboutButton.SetEnabled(true)
	} else {
		d.aboutButton.SetEnabled(false)
	}
}
           

然後就是主函數,将顯示About對話框的信号和相應的處理函數連接配接,然後顯示我們的元件:

func main() {
	app := widgets.NewQApplication(len(os.Args), os.Args)
	
	dialog := NewMyDialog(nil, 0)
    // 顯示About Qt
	dialog.ConnectShowAboutQt( func() {
		app.AboutQtDefault()
	})
    // 顯示自定義内容的About
	dialog.ConnectShowAbout( func(text string) {
		widgets.NewQMessageBox(dialog).About(dialog, "About Dialog", text)
	})
	
	dialog.Show()
	
	app.Exec()
}
           

顯示About Qt時的效果:

【golang-GUI開發】struct tags系統(二)qt的自定義元件和構造函數

怎麼樣,是不是很簡單,下一篇文章裡我們将結束對qt struct tags的探索,如果有任何疑問或者建議,歡迎在評論指出!

祝玩得愉快!