用 Ruby 创建一个简单的 GTK+ ToDo 应用程序

2018-01-30 10:44:13来源:https://www.oschina.net/translate/creating-a-gtk-todo-applic作者:开源中国翻译文章人点击

分享
第七城市th7cn

最近,我正在试用 GTK+ 和它的 Ruby 程序包(binding)。我决定写一个教程介绍一下这个功能。在本文中,我们将会用 gtk3 gem —— 即 GTK+ 的 Ruby 程序包——来创建一个简单的 ToDo 程序。这个程序有点像我们在 Ruby on Rails 上创建的 这个程序 。


注:本教程的代码可以在 GitHub 上下载。


什么是 GTK+

引用工具箱 页面 上的一句话,GTK+ 就是:


GTK+,即 GIMP Toolkit(工具箱)的缩写,是一个可以用来创建用户界面的多平台工具箱。它提供了一整套小部件,适用于各种场合,小到一个简单的工具程序,大到一个完整的应用套件。


另外,关于 GTK+ 的起源:


GTK+ 最初是为 GIMP(GNU Image Manipulation Program 的缩写,即 GNU 图像处理程序)开发的,也是在其环境下应用的。它被称为“ GIMP 工具箱”,就是要大家记住这个项目的起源。如今,它更多地以一个简短的名字—— GTK+ 示人,并且被应用更多的场景中,包括 GNU 项目的 GNOME 桌面系统在内。



准备工作
GTK +版本

确保你已经安装了 GTK +。


我开发教程应用程序的操作系统是 Ubuntu 16.04 ,默认安装了 GTK +(版本:3.18)。


你可以使用以下命令检查设备:


dpkg -l libgtk-3-0
Ruby

你应该在你的系统上安装 ruby 。 我使用 RVM 来管理我的系统上安装的多个 ruby 版本。 如果你也想这样做,你可以在 主页 上找到安装该工具的说明,以及安装 ruby 版本(a.k.a. rubies)的 相关文档页面 。


本教程使用 Ruby 2.4.2 。 你可以用如下命令检查版本号:ruby --version 或通过 RVM 的 rvm list 。




Glade

再次引用 该工具页面 :


Glade 是一个 RAD 工具,可以快速轻松地开发用于 GTK +工具包和 GNOME 桌面环境的用户界面。


我们将使用 Glade 来设计我们的应用程序的用户界面。 如果你使用 Ubuntu ,请安装 Glade :


sudo apt install glade
gtk3 gem

gem 提供了 GTK +工具包的 Ruby 绑定。 换句话说,它允许我们使用 Ruby 语言与 GTK + API 进行交流。


通过以下方式安装 gem :


gem install gtk3

应用程序规范

我们将建立一个应用程序:



它将有一个用户界面(桌面应用程序)


它将允许用户为每个项目设置杂项属性(如优先级)


它将允许用户创建和编辑 ToDo 项目


所有的项目将作为文件保存在用户的主目录中一个名为 .gtk-todo-tutorial 的文件夹中


它将允许用户存档 ToDo 事项


归档的项目应该放在自己的 archived 文件夹中



应用程序结构
gtk-todo-tutorial # root directory
|-- application
|-- ui # everything related to the ui of the application
|-- models # our models
|-- lib # the directory to host any utilities we might need
|-- resources # directory to host the resources of our application
gtk-todo # the executable that will start our application

开始创建项目吧!



构建 ToDo 应用程序
初始化应用程序

创建一个目录,我们将在其中保存应用程序所需的所有文件。如上面的部分所示,我命名 gtk-todo-tutorial 为我的主目录文件夹。


在那里创建一个名为 gtk-todo 的文件(这是正确的,没有扩展名),并添加以下内容:


#!/usr/bin/env ruby
require 'gtk3'
app = Gtk::Application.new 'com.iridakos.gtk-todo', :flags_none
app.signal_connect :activate do |application|
window = Gtk::ApplicationWindow.new(application)
window.set_title 'Hello GTK+Ruby!'
window.present
end
puts app.run

这是用来启动应用程序的脚本文件。


注意第一行中的 shebang (#!)。这就是我们如何定义在 UNIX / Linux 操作系统下使用哪个解释器来执行脚本。 这样,我们不必使用 ruby gtk-todo ,而只需要使用脚本名称 gtk-todo 。


现在不要去尝试运行,因为我们没有改变文件的模式。 为此,请在导航到应用程序根目录后,在终端中键入以下命令:


chmod +x ./gtk-todo # make the script executable

现在从控制台执行:


./gtk-todo # execute the script

Ta daaaaaa




注意事项:

我们上面定义的应用程序对象和所有的 GTK + 小部件通常会发出触发事件的信号。一旦应用程序开始运行,例如,它发出一个信号来触发 activate 事件。我们所要做的就是定义这个信号发射时我们想要发生的事情。我们通过使用 signal_connect 实例方法并将其传递给将在给定事件上执行的代码块来完成此操作。我们将在整个教程中做很多工作。


当我们初始化 Gtk :: Application 对象时,我们传递了两个参数:



com.iridakos.gtk-todo:这是我们的应用程序的 ID ,一般来说它应该是一个反向的 DNS 样式标识符。有关其使用情况和最佳做法的更多信息,请点击 此处 。


:flags_none:这是一个定义应用程序行为的标识。在我们的例子中,我们使用了默认行为。在 这里 检查所有的标志和他们定义的应用程序的类型。您可以使用 Gio :: ApplicationFlags.constants 中定义的 Ruby 等效标志。例如,不是使用:flags_none,而是使用 Gio :: ApplicationFlags :: FLAGS_NONE



假设我们之前创建的应用程序对象(Gtk :: Application)在 activate 信号触发者在我们想要连接更多信号时有很多工作要做。我们最终会创建一个巨大的 gtk-todo 脚本文件,这将难以读取/维护。(甚至)花费时间重构。



如 应用程序结构 部分所述,创建一个名为 application 的文件夹及其子文件夹 ui、models 和 lib 。



在 ui 文件夹中,我们将放置与用户界面相关的所有文件。


在 models 文件夹中,我们将放置与模型相关的所有文件。


在 lib 文件夹中,我们将放置所有不属于上述文件夹的其他文件。



我们将为我们的应用程序定义一个新的 Gtk :: Application 类的子类。 在 application / ui / todo 下创建一个名为 application.rb 的文件,其内容如下。


module ToDo
class Application < Gtk::Application
def initialize
super 'com.iridakos.gtk-todo', Gio::ApplicationFlags::FLAGS_NONE
signal_connect :activate do |application|
window = Gtk::ApplicationWindow.new(application)
window.set_title 'Hello GTK+Ruby!'
window.present
end
end
end
end

并相应地更改 gtk-todo 脚本:


#!/usr/bin/env ruby
require 'gtk3'
app = ToDo::Application.new
puts app.run

更简洁,不是吗? 是的,但它不起作用。 你应该得到像这样的东西:


./gtk-todo:5:in `<main>': uninitialized constant ToDo (NameError)

现在的问题是我们没有要求在 application 文件夹中放置任何 ruby 文件。 如下更改脚本文件并再次执行。


#!/usr/bin/env ruby
require 'gtk3'
# Require all ruby files in the application folder recursively
application_root_path = File.expand_path(__dir__)
Dir[File.join(application_root_path, '**', '*.rb')].each { |file| require file }
app = ToDo::Application.new
puts app.run

这下就没问题了。



资源

在本教程开始我们说过会使用Glade 设计应用程序的用户界面。Glade 实际上产生的 XML 文件与相应的元素和属性,反映了我们设计的用户界面。我们需要使用这些文件,这样我们的应用程序就可以得到我们设计的 UI 。


这些文件是与 GResource API 提供了一种包装在一起的一个二进制文件,然后从内部访问他们已经加载的资源,读取文件系统的位置等等,相对于手动来处理有明显的优势。 点此了解更多API相关 。



描述资源文件

首先,我们需要创建一个描述应用程序资源的文件。 创建一个名为 gresources.xml 的文件,并将其直接放置在 resources 文件夹下。


<?xml version="1.0" encoding="UTF-8"?>
<gresources>
<gresource prefix="/com/iridakos/gtk-todo">
<file preprocess="xml-stripblanks">ui/application_window.ui</file>
</gresource>
</gresources>

在这个“描述文件”中,实际上说:我们有一个位于 ui 目录下的资源(相对于这个 xml 文件),名字是 main_window.ui 。 在加载此资源之前,请删除空白。 谢谢。 当然,由于我们还没有通过 Glade 创建资源,所以现在还不能工作。 不要担心,事情一件一件来做。


注意:xml-stripblanks 指令将使用 xmllint 命令删除空白。 在 Ubuntu 中,你必须安装 libxml2-utils 软件包来获取它。



建立二进制资源文件


为了生成二进制资源文件,我们将使用另一个名为 glib-compile-resources 的 GLib 库实用程序。 检查是否已经安装了 dpkg -l libglib2.0-bin 。 你应该看到如下内容:


iilibglib2.0-bin 2.48.2-0ubuntu amd64Programs for the GLib library

如果没有,就要先安装软件包(在 Ubuntu 中使用命令 :sudo apt install libglib2.0-bin )。


让我们建立文件。 我们将在脚本中添加代码,以便每次执行时都会生成资源。 更改 gtk-todo 脚本,如下所示。


#!/usr/bin/env ruby
require 'gtk3'
require 'fileutils'
# Require all ruby files in the application folder recursively
application_root_path = File.expand_path(__dir__)
Dir[File.join(application_root_path, '**', '*.rb')].each { |file| require file }
# Define the source & target files of the glib-compile-resources command
resource_xml = File.join(application_root_path, 'resources', 'gresources.xml')
resource_bin = File.join(application_root_path, 'gresource.bin')
# Build the binary
system("glib-compile-resources",
"--target", resource_bin,
"--sourcedir", File.dirname(resource_xml),
resource_xml)
at_exit do
# Before existing, please remove the binary we produced, thanks.
FileUtils.rm_f(resource_bin)
end
app = ToDo::Application.new
puts app.run

并执行它。 这将会在控制台输出如下内容,这很好,我们稍后会修复它:


/.../gtk-todo-tutorial/resources/gresources.xml: Failed to locate 'ui/main_window.ui' in any source directory.

我们做了什么:



为 fileutils 库添加了一个 require 语句,以便我们可以在 at_exit 调用中使用它


定义了 glib-compile-resources 命令的源文件和目标文件


执行了 glib-compile-resources 命令


设置了一个钩子,以便在退出脚本之前(应用程序退出之前)删除二进制文件,方便下次再次构建




第七城市th7cn

最新文章

123

最新摄影

闪念基因

微信扫一扫

第七城市微信公众平台