How can I make a gtk4::Box
clickable in gtk_rs
?
In GTK3 it seems that using an EventBox
was the way to achieve this, however in GTK4:
Stop using
GtkEventBox
GtkEventBox
is no longer needed and has been removed.All widgets receive all events.
https://docs.gtk.org/gtk4/migrating-3to4.html#stop-using-gtkeventbox
So it seems that click handlers should now be attached to widgets directly. However I can't find any clear documentation or examples on how to do this.
If someone could give me an example of attaching a click listener to a gtk4::Box
it would be much appreciated.
You can do this using gtk::GestureClick
like shown in this example.
Here is a full example (click somewhere inside the window as the box is not actually visible):
use gtk::prelude::*;
use gtk::{Application, ApplicationWindow};
fn main() {
// Create a new application
let app = Application::builder()
.application_id("org.gtk-rs.example")
.build();
// Connect to "activate" signal of `app`
app.connect_activate(|app| {
build_ui(app);
});
// Run the application
app.run();
}
fn build_ui(app: &Application) {
// Create a window and set the title
let window = ApplicationWindow::builder()
.application(app)
.title("My GTK App")
.build();
// Create a box
let gtk_box = gtk::builders::BoxBuilder::new()
.height_request(200)
.width_request(300)
.build();
// Assign a click listener
let gesture = gtk::GestureClick::new();
gesture.connect_released(|gesture, _, _, _| {
gesture.set_state(gtk::EventSequenceState::Claimed);
println!("Box pressed!");
});
gtk_box.add_controller(&gesture);
// Add the box
window.set_child(Some(>k_box));
// Present window to the user
window.present();
}
Say you wanted to actually also see the box and maybe provide some user feedback on mouse hover. Then you will need to use CSS rules to achieve that.
Change your main.rs
to:
use gtk::gdk::Display;
use gtk::{CssProvider, StyleContext, prelude::*};
use gtk::{Application, ApplicationWindow};
fn main() {
// Create a new application
let app = Application::builder()
.application_id("org.gtk-rs.example")
.build();
// Connect to "activate" signal of `app`
app.connect_activate(|app| {
// Load a CSS stylesheet from the included bytes.
let provider = CssProvider::new();
provider.load_from_data(include_bytes!("style.css"));
// Give the CssProvider to the default screen so the CSS rules are
// applied to the window.
StyleContext::add_provider_for_display(
&Display::default().expect("Error initializing gtk css provider."),
&provider,
gtk::STYLE_PROVIDER_PRIORITY_APPLICATION,
);
build_ui(app);
});
// Run the application
app.run();
}
fn build_ui(app: &Application) {
// Create a window and set the title
let window = ApplicationWindow::builder()
.application(app)
.title("My GTK App")
.build();
// Create a box
let gtk_box = gtk::builders::BoxBuilder::new()
.height_request(200)
.width_request(300)
.margin_bottom(20)
.margin_end(20)
.margin_start(20)
.margin_top(20)
.css_classes(vec![String::from("hover-box")])
.build();
// Assign a click listener
let gesture = gtk::GestureClick::new();
gesture.connect_released(|gesture, _, _, _| {
gesture.set_state(gtk::EventSequenceState::Claimed);
println!("Box pressed!");
});
gtk_box.add_controller(&gesture);
// Add the box
window.set_child(Some(>k_box));
// Present window to the user
window.present();
}
and create a style.css
file in the src/
directory (the same directory where the main.rs
is located) with this content:
.hover-box {
background-color: blue;
border-radius: 5px;
}
.hover-box:hover {
background-color: rgb(11, 133, 240);
border-radius: 5px;
}
Now you get a gtk4::Box
with a 5px
border radius and blue
background color that changes when you hover the mouse above the box.