使用Designer
上一节我们手撸了一个Hello World,然而对于稍微复杂一些的界面,手撸就实在太没有效率了。Designer才是GUI设计的神器。therecipe/qt集成了uic工具,可以方便地将Designer生成的ui文件转换成go文件(其实有的地方也不很方便,之后会提到)。
绘制界面
打开Designer,新建一个窗口,随便拖几个小部件上去,还是以Hello World为例,如下图:
为了简单考虑,objectName
就不改了,都按照默认的来,窗口是Dialog
,按钮是pushButton
。在工程目录下新建一个ui文件夹,将窗口保存为window.ui。
在ui文件夹下新建一个window.go(叫什么名无所谓),就一句话,package ui
。修改hello_world.go,改为:
package main
import (
"main/ui"
"os"
"github.com/therecipe/qt/widgets"
)
func main() {
widgets.NewQApplication(len(os.Args), os.Args)
window := ui.NewDialog(nil)
window.Show()
widgets.QApplication_Exec()
}
执行qtdeploy build desktop hello_world.go
,编译完成后,运行deploywindowshello_world.exe
。
复盘
我们已经完成了两个demo了,可以注意到,由于Go语言的特性,对于Qt的接口存在一些改动。比如所有的接口函数的首字母都大写了,这是因为在Go语言中,只有首字母大写的函数才会被外部访问到。某些函数的后边增加了数字,这是因为Go语言没有泛型,因此不同参数的函数必须通过函数名进行区分。这就体现出了VSCode的重要性了,当你不清楚一个函数后边的尾缀时,可以按Ctrl+空格
进行代码补全,此时可以查看函数的名称和参数类型。
言归正传,让我们看看qtdeploy
都做了什么。当执行完qtdeploy
之后,在ui目录下会生成一个uic_window.go的文件,这个文件就是根据ui文件自动生成的go文件。
通常来讲,这个文件不应该手动修改,因为每次运行qtdeploy
之后文件内容都会被还原。
可以看到,在这个文件中定义了一个名为NewDialog
的函数,它的作用就是创立一个窗口,也就是对应hello_world.go的第12行。
我们在上一步的时候新建了window.go,其目的是定义了ui
包,否则在hello_world.go里边找不到ui
包,qtdeploy
会直接报错,跑不到uic的这一步。
连接信号和槽
Qt是一个事件驱动的GUI库,当用户执行某些操作的时候会产生信号(signal),如果将信号和一个槽(slot)连接起来,那么当信号触发时,就会调用相应的槽函数。让我们尝试将按钮的clicked
信号和窗口的close
槽连接起来,实现按按钮退出窗口的功能。
在therecipe/qt中,连接信号和槽的方法与PyQt5有所不同(应该与C++的也不一样,C++不熟,没有考证),连接信号的函数为Connect+信号名
的格式。需要注意的是,待连接的槽的参数如果和信号不一致是不能直接连接的。让我们修改window.go:
package ui
func (c *Dialog) init() {
c.PushButton.ConnectClicked(func(s bool) { c.Close() })
}
再次执行qtdeploy
,并运行生成的程序,可以发现,点按钮之后窗口可以退出了。
其实还有另一种更方便的连接信号的槽的方式,让我们先将window.go还原,之后直接在Designer里边进行连接,如图:
保存,并执行qtdeploy,生成的程序效果是一样的。