gtk-rs 现已支持 GTK4 绑定

gtk-rs 现已支持 GTK4 绑定

6 月 22 日 gtk-rs 官方博客就发文了

距离上次发布已经过去很长时间了,正如您所猜测的,在这段时间内发生了很多事情。让我们从最重要的开始:

gtk-rs 现在为 GTK4 库提供绑定!

它们都可以在 gtk4-rs 仓库中找到。

甚至还写了一本介绍书来教用户如何使用 gtk4-rs。你可以在这里阅读它。接下来几天将发布有关 GTK4 的更详细的博客文章。

我们利用这个机会彻底重新设计了网站并制作了一个logo。既然你已经来了,不要犹豫,去看看吧!

GNOME 圈子

gtk-rs 现在是 “GNOME 圈子“ 的一部分!除了一些其他好处之外,它还允许我们的贡献者加入 GNOME 基金会。查看网站了解更多详情。

git 仓库更改

此版本还对 gtk-rs 仓库结构进行了更改。我们现在有三个主要仓库:

gtk-rs-core:它包含被认为是“核心”的 crate,因为它们同时被 GTK3 和 GTK4 使用,但也被其他项目如 gstreamer-rs 使用:

  • cairo
  • gdk-pixbuf
  • gio
  • glib
  • glib-macros
  • graphene
  • pango
  • pangocairo

gtk3-rs:包含属于 GTK3 生态系统的 crate:

  • atk
  • gdk
  • gdkx11
  • gtk3-macros

gtk4-rs:包含属于 GTK4 生态系统一部分的 crate:

  • gdk4
  • gdk4-wayland
  • gdk4-x11
  • gsk4
  • gtk4
  • gtk4-macros

关于这一点的另一个重点是:一个存储库中的所有 crate 现在共享相同的版本号。之前它有点乱,所以我们决定简化它。所以这里是每个存储库的版本号:

文档改进

gtk-rs crates 使用 C 文档,但是我们改进了它的渲染以使其对 Rust 开发人员更有用:

  • 现在可以正确生成条目的链接。
  • 如果代码示例不是用 Rust 编写的,我们现在添加警告以避免混淆。
  • 我们添加了文档别名,因此您现在可以直接搜索信号名称甚至 C 函数名称。
  • 现在还记录了全局函数、构建器模式、常量和静态。
  • 不再呈现 C 特定的参数,因此不在 Rust 绑定中使用。

依赖项被重新导出

我们举个例子,而不是冗长的解释。您有一个 GTK 应用程序,并且还使用 Cairo 和 GDK。在此版本之前,您需要将所有 3 个依赖项添加到 Cargo.toml 文件中以便能够使用它们。现在,您只需要导入 GTK 即可:

use gtk::{cairo, gdk};

就是这样!它将使您对依赖项的管理更加简单。需要注意的是,它们也在前奏中,因此导入它将使您可以访问它们:

use gtk::prelude::*;

// ...
let x = cairo::something();
let y = gdk::something();

关于重新导出的最后一条说明: -sys crates 也以 ffi 的名称重新导出:

use gtk::ffi;

// You now have access to all raw C-functions of GTK.
// 您现在可以访问 GTK 的所有原始 C 函数。

重构 Value trait

主要的变化是对于不可为空的类型 Value::get() 永远不会返回 None,取代了之前令人困惑的 Value::get_some()

此外,现在可以直接将 Value::get() 设为可空类型,而无需 Option 包装。如果该值实际上是 None 这将返回一个 Err。在值为 None 的情况下,这避免了一层展开。

还有一个新的通用的 ValueType trait,它由可在 Value 中使用的所有类型实现,并允许 存储/检索 此值的类型 into/from 一个Value (这里有点绕,觉得没翻译正确,原谅老灯吧 :( )。 我贴出原文:There is also a new generic ValueType trait that is implemented by all types that can be used inside a Value and that allows storing/retrieving types of this value into/from a Value.

添加了 GTK 复合模板支持

要从 UI 文件构建小部件,您可以使用 gtk::Builder 或复合模板。对于前者,您必须保留一个 gtk::Builder 实例。使用复合模板时,您可以让您的自定义小部件(gtk::Widget 的子类)在内部使用该模板,区别在于能够通过定义在不同的 UI 文件中使用您的 CustomWidget:

<object class="CustomWidget">
  <property name="some-property">some-value</property>
</object>

您现在可以让您的 CustomWidget 使用 #[CompositeTemplate] 派生宏。这项工作最初是为 GTK4 Rust 绑定完成的,但也向后移植到 GTK3。有关示例,请参见此处此处

复合模板还允许您使用在 CustomWidget 上定义的方法作为直接来自 UI 文件的信号的回调,即使宏目前不支持 GTK3/GTK4 绑定......但别担心,我们正在努力解决

新的和改进的宏

除了 glib::object_subclass 属性宏(请参阅有关子类化改进的段落的链接)之外,glib 现在还提供了一些其他宏,以使应用程序开发更容易并减少样板:

glib::clone!:这个宏允许自动克隆或创建弱引用加上闭包的升级,并大大简化了信号处理程序闭包的创建。该文档包含几个示例。虽然这个宏存在于

最后一个版本,它被完全重写并变得更强大,并获得了一个伴随的派生宏 glib::Downgrade,它使用所需的机制扩展自定义类型,用于克隆上下文中的弱引用!宏。 glib::GBoxedglib::GSharedBoxed:这些派生宏允许在 glib::Values 中使用自定义 Rust 类型,这是 GObject 属性和信号参数/返回值或 GTK 树视图的内容所必需的。第一个宏总是在必要时克隆底层值,而第二个宏使用引用计数而不是正常克隆。 glib::gflags!和 glib::GEnum:这些宏允许在 glib::Values 中使用 Rust 枚举和位标志。有关示例,请参阅子subclassing docsglib::GErrorDomain:这个派生宏允许使用合适的 Rust 枚举作为 glib::Errors 的错误域。

有关 glib::GBoxedglib::gflagsglib::GEnum 宏的更多示例,另请参阅子subclassing文档。

子类化(subclassing)的改进

由于引入了 glib::object_subclass derive 派生宏,因此实现 GObject 更加简单。此外,注册属性和信号现在需要更少的样板。请参阅此页面以获取完整示例,但最小示例现在如下所示:

mod imp {
    #[derive(Default)]
    pub struct MyObject;

    #[glib::object_subclass]
    impl ObjectSubclass for MyObject {
        const NAME: &'static str = "MyObject";

        type Type = super::MyObject;
        type ParentType = glib::Object;
    }

    impl ObjectImpl for MyObject {}
}

glib::wrapper! {
    pub struct MyObject(ObjectSubclass<imp::MyObject>);
}

impl MyObject {
    pub fn new() -> Self {
        glib::Object::new(&[]).unwrap()
    }
}

更好的cairo错误处理

使用 cairo 现在更符合人体工程学:fill() 或stroke() 等函数返回结果,而不需要手动检查Context::status()。此外,所有在 cairo 状态上对 expect() 的内部调用都被删除了,使调用者能够处理错误情况,而不是引起 panic.

Gir教程

gtk-rs crates 大多能自动生成,这要归功于 gir 项目。如果您还想生成自己的基于 GObject 的 crate 绑定,也可以使用它!为了帮助您,我们开始了一本教程书,可在此处获取。

命名改进

我们重命名了许多函数/方法,以使它们更符合 Rust 标准。具体来说,getter 函数从 get_something() 重命名为 something() 或 is_something(),而 setter 保持为 set_something()。此外,GObject 属性 getter/setter 失去了名称中的属性名称(即 set_property_something() 被 set_something() 取代)。

在此注意事项:

应用程序开发人员注意事项

应用程序开发人员应该使用 fix-getters-calls 来简化应用程序的迁移。如果您还希望 get 函数定义符合此版本中应用的 API 标准,请使用 fix-getters-def

最低支持版本

gtk-rs 最低支持的 Rust 版本现在是 1.51

  • ATK: 2.18
  • Cairo: 1.14
  • GDK3: 3.18
  • GDK4: 4.0
  • GDK4-Wayland: 4.0
  • GDKX11: 3.18
  • GDK4-X11: 4.0
  • GDK-Pixbuf: 2.32
  • Gio: 2.48
  • GLib: 2.48
  • Graphene: 1.10
  • GSK4: 4.0
  • GTK3: 3.20
  • GTK4: 4.0
  • Pango: 1.38
  • PangoCairo: 1.38

迁移到 Rust 2018 版

gtk-rs crates 全部迁移到 Rust 2018 版本。正好因为 2021 年版越来越近了!

Refs

https://gtk-rs.org/gtk4-rs/stable/latest/book/

https://gtk-rs.org/blog/2021/06/22/new-release.html