本书介绍了如何使用GTK小部件工具包和Nim编程语言来设计和创建图形用户界面。这本书的重点是Linux操作系统(OS)。尽管Nim编程语言确实支持所有主流操作系统,但GTK却主要将重点放在Linux OS上。 GTK支持Windows和macOS,但没有真正的本机外观。 GTK不支持Android和iOS,但是Purism公司生产的Libremmobile设备有一些早期的实验支持。由于GTK紧凑且具有模块化设计,因此它也可以用于资源有限的设备(如Raspberry Pi系列)。尽管通常不使用GTK创建Web应用程序,但可以通过使用百老汇GTK后端在Web浏览器中本地运行GTK应用程序。
本书中的示例使用了围绕A.Rumpfin先生v1.4版本的团队的Nim实现,该版本是2020年末推出的第一个GTK 4版本,以及gintro软件包在0.8.4版中提供的Nim GTK绑定。对于其他Nim实施或不同的GTK绑定,可能需要对提供的示例进行修改。
GTK是用于设计和创建图形用户界面(GUI)的工具箱的名称,它允许用户通过使用图形元素(例如按钮,滑块,下拉菜单和输入字段)与计算机程序进行交互。这些元素称为小部件。可以将小部件分组以构建更大的实体,例如文件或消息对话框。顶层窗口小部件通常是一个矩形容器,称为一个包含所有其他窗口小部件的窗口。 GTK的最初版本出现在1998年,名为GIMP工具包,并标记为GTK +。正如TheName GTK所暗示的那样,它已与著名的GIMP绘图程序(GNUimage操作程序)紧密绑定,并旨在代替较早的Motif Unix GUI for GIMP。
图形用户界面是在计算机发明之后几十年引入的,其目的是通过取代传统的基于终端的文本用户界面来简化人与计算机之间的交互。 GUI甚至允许未经培训的人员与计算机进行直观的交互,而无需学习和记住许多文本命令。与图形用户界面紧密相连的是计算机鼠标,它是一个固定在桌子上的小工具,可以将其移动映射到计算机屏幕上绘制的指针,以便与小部件进行交互。如今,计算机鼠标通常由触摸板或触摸显示器支持或代替。
GTK发行后,该工具包也被其他软件使用,并且在2002年出现了GTK 2.0版。 GTK 2已经有了更多的模块化设计,并且与GIMP没有那么紧密的联系。在2011年出现了GTK 3.0,它提供了许多新功能。最重要的是由层叠样式表(CSS)支持的新的可定制设计,以及使用诸如cairo之类的库来绘制图形元素,以及使用pango的库来字体呈现。 2020年末将发布GTK 4正式版,该版本再次具有改进的内部设计,改进的应用程序编程接口(API),并支持OpenGL和Vulkan硬件绘图以使小部件最大化性能,同时保持较低的CPU负载。
GTK可以在Windows和macOS计算机上使用,但通常在Linux上使用,并且通常与Gnome桌面环境结合使用。 Gnomefoundation是GTK开发的最重要支持者。 GTK不支持用于移动设备的Android或iOS操作系统。与GTK相关的库使用LGPL软件许可证,而Nim编译器和大多数Nim的外部软件包都使用MIT软件许可证。这两个许可证都允许创建专有的封闭源代码软件,只要使用LGPL许可库的动态链接即可。
像大多数传统的GUI工具包一样,GTK使用保留模式,该模式仅在必要时更新和重绘图形场景。与过去几年的保留模式GUI相比,即时模式GUI变得很流行。这些GUI通常在游戏的简单GUI中具有其来源,并永久地重新绘制整个场景,通常与屏幕刷新率同步。永久性重绘当然会产生一些CPU负载,但是对于游戏来说通常并不重要,因为CPU和GPU负载由游戏本身决定,并且使用OpenGL或Vulkan硬件支持绘制时,GUI不会导致CPU负载过高。最后,像GTK这样的现代保留模式GUI不再真正静态,因为它们包含许多动画。因此,保留模式GUI和即时模式GUI之间的区别不是那么明显。
最初是GTK +,GIMP工具包。 GTK模块构建了GTKwidget工具套件的核心,并包含所有小部件。
GObject模块为使用C编程语言的面向对象编程(OOP)提供了API。
GTK Scene Graph Kit用于优化图形和小部件刷新。
其他与GTK相关的模块包括用于高级文本布局支持的GtkSourceView(用于gedit等文本编辑器),用于支持可缩放矢量图形(SVG)的rsvg模块以及用于创建终端窗口的VTE模块。 GtkSourceView和VTE尚不适用于GTK4。
对于Linux,GTK工具包和计算机硬件之间还有一个抽象层,即路标显示服务器,是原始X Window系统的现代化实现。
所有这些组件都是用C编程语言编写的。 C是一种非常古老的,受限制的,有时甚至是不安全的语言,它会导致非常冗长的代码,难以维护。由于GTK具有面向对象的设计,但是Clanguage不支持OOP样式,因此从头开始为GTK编写了一个名为gobject的整个对象系统。而且由于C不支持高级数据结构,如可调整大小的字符串,哈希图,异步输入输出操作以及现代语言通常提供的更重要的功能,因此它也是从头开始编写的,并在支持glib和gio的库中提供。由于C不支持自动内存管理,因此在GTK中有时需要手动释放内存,这可能会导致众所周知的问题,例如内存泄漏或释放问题后使用。
显然,考虑到很小的GTK和Gnome社区,所有这些肿的旧东西几乎是无法维护的。今天,当我们有这么多现代的编程语言可用时,几乎没有人打算用C编写应用程序。考虑到GTK甚至不支持流行的移动设备Android OS的事实,我们可能会问为什么我们应该关心对于GTK来说仍然如此。
的确,GTK的流行竞争对手是带有KDE Linux桌面环境的Qt GUI工具箱。 Qt早在1995年就出现了,它的许可证模型不太适合免费的开源软件(FOSS),现在可以在版本6中使用,而受限制的许可证要少得多。 Qt是用C ++编写的,不幸的是,它比GTK膨胀得多,它使用所谓的元对象编译器(MOC)作为某种形式的C ++预处理程序。 Qt确实很大,包含很多与GUI无关的东西,例如网络,Web和数据库功能或支持任何自定义数据类型。所有这些都可以通过现代C ++或专门的库获得,因此Qt可以被视为几乎整个操作系统上都a肿的应用程序框架。 Qt的优点是它是主动开发的,并支持所有重要操作系统,包括具有原生外观的移动Android和iOS系统。
由于诸如Windows,macOS,Android和iOS之类的专有操作系统都具有其自己的本地GUI,因此当我们计划仅为其中一个系统开发应用程序时,我们不需要单独的工具包。实际上,用户通常偏爱仅使用nativeGUI且避免使用GTK或Qt等附加层的应用程序。
对于许多Windows或macOS用户,GTK的缺点是GTK会自己绘制所有itwidget,它不使用专有系统的本机图形元素。 GTK允许使用级联样式表(CSS)进行主题设置,因此可以将其调整为在Windows和macOS上看起来不太奇怪,但外观通常并不映射到本机应用程序。 Qt在Linux上自己绘制其窗口小部件,但从4.0版开始,可以尝试在Windows或macOS上使用本机元素,这可能会提供更本机的外观。
一个更重要的GUI工具包是wxWidgets,它在Linux上使用GTK,在Windows和macOS上使用本机GUI元素。有些人喜欢wxWidgets,因为它实际上是具有本机外观的跨平台GUI工具包,但至少对于Linuxit而言,它只是GTK之上的另一层。而且它不支持移动操作系统Android和iOS。
除了大型工具箱Qt和GTK之外,还有许多其他小型工具箱,例如已经提到的wxWidgets,用C ++编写的FLTK工具箱,或诸如LessTif或TK之类的老旧俗名。
最后,我们始终可以选择完全不使用GUI工具包,而是基于HTML和JavaScript创建可与Web浏览器一起使用的GUI。
GTK是用C编写的,因此很难维护,这同时带来了很大的好处:由于C是一种简单的语言,没有类,模板,继承或自动内存管理等高级概念,因此通常很容易创建与其他编程语言的C库。对于GTK,GTK gobject-introspection数据库甚至支持该事实,该数据库允许在半自动过程中创建与所有GTK相关库的绑定。
因此,大多数新的现代计算机编程语言都具有与GTK工具包的绑定。对于用C ++编写的Qt,创建绑定要困难得多,因为C类,模板和MOC预处理器等C概念使自动生成绑定变得困难。
因此,Qt通常直接从C ++中使用,或者使用其受支持的Python绑定。存在许多其他编程语言的Qt语言绑定,但是很难使它们保持最新。有时Qt GUI也使用QML创建,它允许以声明的方式创建用户界面。 QML绑定可用于各种编程语言。
尽管GTK仍经常直接从C使用,但它提供了一组官方支持的语言绑定,包括C ++(gtkmm),JavaScript,Python,Rust,Perl和Vala。 D和Go也得到很好的支持,对于许多其他编程语言,至少存在GTK子集的绑定。
在本书中,我们将使用基于gobject-introspection的绑定以Nim编程语言编写GTK应用程序。 Nim是一种现代的编译静态类型语言,可以从干净的高级源代码生成快速的本机可执行文件。由于Nimdoes不会像Java这样的语言通过继承来强制OOP设计,因此我们的Nimexamples遵循了GTK核心开发人员提供的原始C示例。一些其他现代语言(例如Go或Rust)通常使用类似的方法,并且不强制执行OOP和继承,而传统的OOP语言(例如Java,Python或Ruby)通常强制对GTK应用程序使用类和继承。带有gtkmm GTK绑定的C ++也将其用户推向了OOP设计。
在本书中,我们将使用由gintro软件包生成的半自动生成的GTK 4和GTK 3绑定,其中g代表所有与gtk相关的库,而intro代表自省,因为绑定是通过使用gobject-introspection生成的。
您应该注意,对于Nim编程语言,还有更多的GUI工具箱可用,其中一些也基于GTK但具有不同的API设计,而另一些基于其他库或直接用Nim编写,例如NimX模块。
这些绑定中的某些当前可能无法使用最新的Nim编译器进行编译,或者可能不支持新的ARC内存管理。但是我们建议您在决定使用gintro之前进行调查,也许其中之一更适合您的需求。当您仅打算为Windows开发时,wNim应该是一个不错的选择,nimx可能是最有趣的,因为它纯粹是Nim,fdget看起来非常不错,nigui支持Windows的本机外观,最后nimgui是对亲爱的imgui立即模式库的绑定。以上大多数绑定都托管在github上,您可以使用github,google或nimblesearch来找到软件包。
请注意,对于本书,我们假设您已经熟悉计算机程序设计和Nim编程语言。至少您应该能够打开终端窗口并输入并执行一些命令。一些C语言的基本知识也将有所帮助,因为我们有时会使用C代码作为Nim程序的起点。
GTK是事件驱动的工具箱。也就是说,我们创建了诸如按钮或文本输入字段之类的小部件,并将它们与一个或多个功能相关联,然后当GTK发现诸如按钮按下或文本输入之类的输入事件时,将自动调用这些小部件。
为了创建GUI,我们创建并安排了所有小部件,然后将小部件动作与我们的处理函数(称为回调)连接起来。回调可以执行任意任务,这包括通过更改小部件的外观,删除小部件或添加新的小部件来修改GUI。
通常,GTK会自动为我们管理窗口小部件的实际布局,即窗口小部件会自动排列和调整大小以创建干净漂亮的外观,并且当我们调整顶层窗口的大小或添加或删除窗口小部件时,布局会自动适应自身。此行为由GtkBox代表的概念的盒子中的盒子来归档-我们创建垂直或水平盒子,我们可以填充小部件,然后可以递归方式将这些盒子再次放入其他较大的盒子中。这样,我们可以指定所需的布局,但具体布局会自动完成。例如,当标签文本或字体大小更改时,按钮可以自动调整大小。水平或垂直框由二维网格或特殊的容器(如标题栏)支撑。我们可以通过指定小部件之间的边距或距离来调整布局,也可以使用CSS修改外观。但是通常,我们不会在为GUI元素指定精确像素位置的位置上创建布局。 GTK还使用GtkFixed和GtkLayout容器提供了固定的定位和大小调整模型,但这仅在极少数情况下使用。最近,GTK还获得了由Emmanuele Bassi开发的新的基于约束的布局管理器,该管理器可以轻松创建更灵活的布局。
我们可以直接在我们的Nim源代码中创建所需的小部件,例如通过调用newButton(" Sort List"),或者我们可以决定以声明的方式在外部XML文件中创建所有小部件。在XML文件中,我们可以按分层布局安排和分组所有小部件,并且可以将属性(例如大小,颜色或文本标签)附加到小部件。我们可以手动创建该XML文件,也可以决定使用交互式Glade工具来创建XML文件。
使用XML文件和Glade工具可能看起来更简单,更直观,更灵活。当我们直接使用C语言创建GTK程序时,这可能是正确的,因为C是一种晦涩而冗长的语言,这使更改变得非常困难。对于像Nim或Python这样的高级语言,情况并非如此,因此,始终不清楚使用外部XML文件是否真的有好处。基于XML的布局具有以下优点:可以在不重新编译程序源代码的情况下修改GUI布局,因此,即使没有程序源代码的用户也可以修改GUI布局。但是,这仅在我们不附带源代码而交付软件以及将XML文件以其原始形式用作外部文本文件时才具有优势。但是在大多数情况下,我们会再次将XML文件集成到我们的主可执行文件中,以简化部署。使用XMLfiles的另一个缺点是Glade工具可能不支持所有的窗口小部件类型及其属性,因此可能需要手动修改XML文件。
因此,对于本书的第一部分,我们将直接在Nimsource代码中创建GUI布局。稍后,我们将介绍XML文件的使用和布局,并描述如何使用GTK构建器库组件导入XML文件和访问小部件。
如果您对在Nim上使用GTK感兴趣,我们应该假定您已经安装在计算机上并可以使用它们。
在Linux计算机上,GTK通常默认安装,或者至少由Linux发行版的软件包管理器提供。如果您仍然应该使用尚未提供GTK4的旧Linux系统,则可以将其安装在GTK3旁边。例如,您可以从git安装最新的GTK4,这些命令在Linux终端窗口中输入:
#https://discourse.gnome.org/t/installing-gtk4-for-testing-on-opt-ii/3349/4git clone https://gitlab.gnome.org/GNOME/gtk.gitcd gtkmeson --prefix可能还需要/ opt / gtk builddirninja -C builddirninja -C builddir install#:导出GI_TYPELIB_PATH = / opt / gtk / lib64 / girepository-1.0export LD_LIBRARY_PATH = $ LD_LIBRARY_PATH:/ opt / gtk / lib64 / export PKG_CONFIG_PATH =" / opt / gtk / lib64 / pkgconfig /"#您可以使用以下命令测试安装:GSETTINGS_SCHEMA_DIR = / opt / gtk / share / glib-2.0 / schemas / opt / gtk / bin / gtk4-demo
如果您在安装过程中遇到问题,则可以在GTKinternet论坛上寻求支持:
在本书的其余部分中,我们假定您还安装了Nim编译器和gcc或clang之类的C编译器。
如果尚未安装Nim GTK绑定,则可以在终端窗口中输入:
gintro软件包通过查询gobject-introspection数据库在您的计算机上本地生成GTK库和Nimlanguage之间的绑定。生成的模块取决于您的操作系统(Linux,Windows,Mac,32位,64位)和可用的GTK版本。如果您更新了GTK系统,则可能需要通过灵活卸载gintro来更新gintro。敏捷安装gintro。当有新的gintro版本可用时,也建议执行该序列。您也可以使用敏捷安装gintro @ head来获取具有最新的,未经测试的修复程序的最新gintro。
GTK 3引入了GtkApplication框架,该框架由GTK 4继承,通常是创建GTK应用程序的推荐方法。基于GtkApplication的程序似乎比具有传统GTK 2启动代码的程序复杂一些,但是GtkApplication样式提供了一些好处,例如管理多个程序实例,参数传递,并且它可以使用带有标题栏和汉堡菜单的新的现代布局。因此,我们将在本书的其余部分中使用GtkApplication样式。
由于您仍会找到许多仍使用旧GTK 2程序启动代码的示例程序,因此我们将首先在此处显示该程序的形状。以下名为simplegtk3.c的C程序使用旧的GTK 2样式,可以使用以下命令进行编译:
该程序将打开一个包含单个按钮的小窗口。单击该按钮会将消息写入终端窗口。您可以通过在程序窗口右上角的十字上单击鼠标来终止程序。
//基于https://gitlab.gnome.org/GNOME/gtk/-//blob/master/tests/simple.c // // gcc -o simplegtk3 simplegtk3.c`pkg-config --libs --cflags gtk +- 3.0` #include< gtk / gtk.h>静态void hello(void){g_print(" hello world \ n"); } int main(int argc,char * argv []){GtkWidget * window,* button; gtk_init(& argc,& argv); window = gtk_window_new(GTK_WINDOW_TOPLEVEL); gtk_window_set_title(GTK_WINDOW(window)," hello world"); gtk_window_set_resizable(GTK_WINDOW(window),FALSE); g_signal_connect(window," destroy",G_CALLBACK(gtk_main_quit),NULL
......