GTK4 - Rust, I can't even do the documentation example

I’m just trying to follow the example exposed in the documentation of the GTK4 Rust bindings to create a simple GTK4 App in Rust. I can’t figure it out why the code is not compiling. Can someone help me?

More specifically, I’m trying to follow the example in Composite Template:
https://gtk-rs.org/gtk4-rs/git/book/composite_templates.html

My Cargo.toml is:

[package]
name = "caju"
version = "0.1.0"
edition = "2021"

[dependencies]
glib = "0.20.4"
gtk = { version = "0.9.2", package = "gtk4", features = ["v4_14"] }
serde = { version = "1.0", features = ["derive"] }
toml = "0.8.19"

[build-dependencies]
glib-build-tools = "0.20.0"

My gresource is at the path ./assets/resources.gresource.xml, and it looks like this:

<?xml version="1.0" encoding="UTF-8"?>
<gresources>
  <gresource prefix="/org/gtk_rs/caju/">
    <file compressed="true" preprocess="xml-stripblanks">caju_gtk_gui.ui</file>
  </gresource>
</gresources>

My UI description is at the path ./assets/caju_gtk_gui.ui, and it looks like this:

<?xml version="1.0" encoding="UTF-8"?>
<interface>
  <template class="CajuGtkAppWindow" parent="GtkApplicationWindow">
    <property name="title">Caju Application</property>
    <child>
      <object class="GtkButton" id="button">
        <property name="label">Press me!</property>
        <property name="margin-top">12</property>
        <property name="margin-bottom">12</property>
        <property name="margin-start">12</property>
        <property name="margin-end">12</property>  
      </object>
    </child>
  </template>
</interface>

My src/main.rs is:

mod window;
use gtk::prelude::*;
use gtk::{gio, glib, Application};
use window::Window;

const APP_ID: &str = "org.caju.application";

fn main() -> glib::ExitCode {
    // Register and include resources
    gio::resources_register_include!("caju.gresource").expect("Failed to register resources.");

    // Create a new application
    let app = Application::builder().application_id(APP_ID).build();

    // Connect to "activate" signal of `app`
    app.connect_activate(build_ui);

    // Run the application
    app.run()
}

fn build_ui(app: &Application) {
    // Create new window and present it
    let window = Window::new(app);
    window.present();
}

My src/window/mod.rs is:

mod imp;
use glib::Object;
use gtk::{gio, glib, Application};

glib::wrapper! {
    pub struct Window(ObjectSubclass<imp::Window>)
        @extends gtk::ApplicationWindow, gtk::Window, gtk::Widget,
        @implements gio::ActionGroup, gio::ActionMap, gtk::Accessible, gtk::Buildable,
                    gtk::ConstraintTarget, gtk::Native, gtk::Root, gtk::ShortcutManager;
}

impl Window {
    pub fn new(app: &Application) -> Self {
        // Create new window
        Object::builder().property("application", app).build()
    }
}

And my src/window/imp.rs is:

// Object holding the state
#[derive(CompositeTemplate, Default)]
#[template(resource = "/org/gtk_rs/caju/caju_gtk_gui.ui")]
pub struct Window {
    #[template_child]
    pub button: TemplateChild<Button>,
}

// The central trait for subclassing a GObject
#[glib::object_subclass]
impl ObjectSubclass for Window {
    // `NAME` needs to match `class` attribute of template
    const NAME: &'static str = "CajuGtkAppWindow";
    type Type = super::Window;
    type ParentType = gtk::ApplicationWindow;

    fn class_init(klass: &mut Self::Class) {
        klass.bind_template();
    }

    fn instance_init(obj: &InitializingObject<Self>) {
        obj.init_template();
    }
}

// Trait shared by all GObjects
impl ObjectImpl for Window {
    fn constructed(&self) {
        // Call "constructed" on parent
        self.parent_constructed();

        // Connect to "clicked" signal of `button`
        self.button.connect_clicked(move |button| {
            // Set the label to "Hello World!" after the button has been clicked on
            button.set_label("Hello World!");
        });
    }
}

I guess I’m missing some use statements on the top of src/window/imp.rs and this might be causing the errors. But the documentation does not mention to add use statements on this file, so, I just didn’t.

When I try to compile the project with cargo run, there are tons of error messages, some of them are:

error[E0277]: the trait bound `imp::Window: ObjectSubclass` is not satisfied
  --> src/window/imp.rs:10:1
   |
10 | #[glib::object_subclass]
   | ^^^^^^^^^^^^^^^^^^^^^^^^ the trait `ObjectSubclass` is not implemented for `imp::Window`
note: required by a bound in `ObjectImplRef`
  --> /home/pedro-dev/.cargo/registry/src/index.crates.io-6f17d22bba15001f/glib-0.20.4/src/subclass/object_impl_ref.rs:17:29
   |
17 | pub struct ObjectImplRef<T: ObjectSubclass>(T::Type);
   |                             ^^^^^^^^^^^^^^ required by this bound in `ObjectImplRef`

There are various differences to the docs:

  • You’re missing the build.rs
  • The paths in your gresource XML are wrong
  • You’re missing the various use statements in src/window/imp.rs
  • Probably more

Please double-check against gtk4-rs/book/listings/composite_templates/1 at 0.9 · gtk-rs/gtk4-rs · GitHub

Thank you @sdroege !

This topic was automatically closed 14 days after the last reply. New replies are no longer allowed.