I'm trying to get the state of a gtk.CheckButton using Action since gtk docs says:
When the code must keep track of the state of a group of radio buttons, it is recommended to keep track of such state through a stateful GAction with a target for each button. Using the toggled signals to keep track of the group changes and state is discouraged.
use gtk::{Application, ApplicationWindow, Button, CheckButton};
use gtk::gio::SimpleAction;
use gtk::Orientation::Vertical;
use gtk::prelude::*;
fn main() {
let application = Application::builder().application_id("a.b").build();
application.connect_activate(|application| {
let main_box = gtk::Box::builder().orientation(Vertical).build();
let variant_a = "a".to_variant();
let variant_b = "b".to_variant();
let window = ApplicationWindow::builder().application(application).child(&main_box).build();
let action_name = "win.me";
let action = SimpleAction::new_stateful(action_name, Some(variant_a.type_()), &variant_a);
window.add_action(&action);
let button_a = CheckButton::builder().label("a").action_name(action_name)
.action_target(&variant_a).build();
main_box.append(&button_a);
let button_b = CheckButton::builder().label("b").action_name(action_name)
.action_target(&variant_b).group(&button_a).build();
main_box.append(&button_b);
let button = Button::builder().label("click").build();
action.connect_change_state(|_, state| {
println!("{:?}", state);
});
button.connect_clicked(move |_| {
println!("{} {:?}", action.name(), action.state());
});
main_box.append(&button);
window.present();
});
application.run();
}
However the CheckButtons are not sensitive. Setting sensitive to true makes them sensitive but clicking them won't make them checked.
In another try I used SimpleActionGroup and action-target-value but with the same results:
fn main() {
let application = Application::builder().application_id("a.b").build();
application.connect_activate(|application| {
let main_box = gtk::Box::builder().orientation(Vertical).build();
let variant_a = "a".to_variant();
let variant_b = "b".to_variant();
let window = ApplicationWindow::builder().application(application).child(&main_box).build();
let action_name = "my.action";
let action_group = SimpleActionGroup::new();
window.insert_action_group("my.group", Some(&action_group));
let action = SimpleAction::new_stateful(action_name, Some(variant_a.type_()), &variant_a);
action_group.add_action(&action);
let button_a = CheckButton::builder().label("a").action_name(action_name).build();
button_a.set_action_target_value(Some(&variant_a));
main_box.append(&button_a);
let button_b = CheckButton::builder().label("b").action_name(action_name).group(&button_a).build();
button_b.set_action_target_value(Some(&variant_b));
main_box.append(&button_b);
let button = Button::builder().label("click").build();
action.connect_activate(|_, state| {
println!("{:?}", state);
});
action.connect_change_state(|_, state| {
println!("{:?}", state);
});
button.connect_clicked(move |_| {
println!("{} {:?}", action.name(), action.state());
});
main_box.append(&button);
window.present();
});
application.run();
}
How do I use Action to get the state of the grouped CheckButtons?
Okay, I'm not a RUST programmer, but your code is missing a few things:
Besides creating a SimplesAction, you also have to create a SimplesActionGroup to put the SimpleAction inside. You cannot add a SimpleAction directly to the window.
You should not use
.action_target(&variant...), but.action_target_value(&variant...)In the Action's callback function, you have to manually call
set_state()to set the "state" of the Action to the value received as a parameter in the callback when the "change_state" signal is triggered, which is the target_value of the clicked button .The initial state defined in the Action will cause the checkbutton that has this target_value to be rendered as active. When you click on another button, the callback will receive the state of the button and
set_state()will set this new state to the Action, which will automatically activate the clicked button, whosetarget_valuecorresponds to this new state.