我正在使用Go的GTK绑定进行一些实验工作。
与大多数GUI框架一样,GTK GUI应用程序通常会生成一个主窗口,并且应用程序的工作是在该窗口的上下文中完成的。
当您用C++编写GTK GUI应用程序时,您从框架窗口类gtk.Window
继承,并将应用程序的其他GUI组件声明为继承的窗口类的公共成员(或在窗口类中使用公共访问方法)。通过这种方式,它们可以由窗口控制器类进行操作。它按名称将它们作为窗口类的成员进行寻址。您只需将指向主窗口的指针传递到控制器类中,并通过编写mWindow.MyWidget.text="text"
等操作其成员。同样,AFAIK,无论使用什么GUI框架,大多数GUI应用程序的设计都是类似的。
然而,由于Go不支持继承,因此此选项是不可能的:当您在Go Gtk窗口中实例化其他GUI组件时,它们是独立变量,而不是父窗口类的成员-它们不"存在"在容器类中。这意味着你的GUI控制器类必须单独访问主窗口中的每个组件,没有连贯的结构或单一的引用。这会损害可读性和良好的代码组织,IMO-迫使你的代码结构有些糟糕。
我相信Go中这个问题的解决方案是声明一个结构/接口,它将作为所有主窗口GUI组件的容器。该接口将发布组件的访问方法,并可以传递给GUI控制器单元以操作其成员。
我需要知道,对于这样的任务,是否有一个标准的惯用Go设计模式,或者使用Go解决这个问题的正确方法是什么。
我知道Go
被设计成一种系统编程语言,并没有真正考虑到前端开发,但我听说它说"每一种好的系统语言最终都会被用于应用程序",现在没有比Go
更好的系统语言了——事实证明,GUI框架和其他应用程序任务的许多Go绑定正在出现。看看Go项目列表就知道了
我想从这一切中得到的启示是,Go的设计并不是为了让桌面GUI应用程序的开发变得容易,而桌面GUI应用是一个垂死的品种
如果我必须在Go中编写一个带有GUI的应用程序,我会将GUI部分与应用程序部分完全解耦。这种方法的一个例子是GTK服务器。
只是,您不需要单独的进程来处理GUI:您可以在goroutine中这样做,goroutine使用通道与应用程序的其他部分通信,就像Gtk服务器使用套接字/管道/消息队列一样。
我不知道有谁使用过这种方法,我自己只在一个玩具程序中使用过它,该程序构建了一个模仿Tk GUI(使用Tk是因为它有一个内置的解释器,而且还不知道gtk服务器)。但对我来说,这将是在Go中构建GUI应用程序的惯用方法。
您正在询问如何将一组东西分组到一个集合中,以便控制器可以访问所有这些东西。您注意到,在C++中,可以将此集合作为gtk的子类。窗在go中,没有类或类型层次结构,但在其他方面,解决方案是相似的。
解决方案只是定义一个结构。也许是这样的:
type MainWindow struct {
Win *gtk.Window
RedButton *gtk.Widget
GreenButton *gtk.Widget
}
窗口的控制器可以访问任何字段,而不需要其他方法或访问器:
type MainController struct {
W *MainWindow
other fields...
}
func (mc *MainController) DoSomething() {
mc.W.RedButton.MakeVisible(true)
mc.W.GreenButton.MakeVisible(false)
}
显然,这里的方法只是为了举例说明。