How can I connect signals from an UI file via `gtk4::Builder`?

58 views Asked by At

I'm trying to connect the signal from this UI file:

<interface>
  <object class="GtkApplicationWindow" id="appwin1">
    <child>
      <object class="GtkButton" id="sarma">
            <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>
            <signal name="clicked" handler="sarma_button_clicked"/>
      </object>
    </child>
  </object>
</interface>

I have defined a callback function:

fn sarma_button_clicked(button :&Button) {
    println!("clicked!");
}

I've also tried this format which I've found on the internet:

fn sarma_button_clicked(param: &[glib::Value]) -> Option<glib::Value> {
    println!("clicked!");
    None
}

The code I've tried to use has been found on the internet but it seems it is for Older Gtk version:

   let builder = Builder::from_file("gui/main.ui");

    builder.connect_signals(|builder, handler_name| {
        match handler_name {
            // handler_name as defined in the glade file => handler function as defined above
            "sarma_button_clicked" => Box::new(sarma_button_clicked),
            _ => Box::new(|_| {None})
        }
    });

The code above doesn't compile in the latest Gtk4 and latest Rust.

1

There are 1 answers

0
Predrag Manojlovic On

The right approach in Gtk4 is to create an empty builder, add scope to it, and then load the source UI file:

let builder = Builder::new();

let scope = gtk::BuilderRustScope::new();
scope.add_callback("sarma_button_clicked", |values| {
    let button = values[0].get::<gtk::Button>().unwrap();
    println!("clicked!");
    None
});

builder.set_scope(Some(&scope));
let _ = builder.add_from_file("gui/main.ui");

This is a simplified answer without error handling.