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`