GTK's "toggled" signal fires when a radio button is selected, but before that, it also fires upon deselection of the previously selected radio button.
I am working with a GUI that uses radio buttons, each representing a group of entities. The first of the pair of "toggled" signals is triggering some unwanted updates to other fields in the GUI -- updates that I only want to happen when the newly selected button triggers the callback. How do I work around this signal and limit the callback function to only operate on selection instead of deselection? I've considered a flag variable within the class I'm coding, but perhaps there is a more GTK-approved technique.
I don't think you can only get selection signals, but you can do something else. You can write your signal handler so it gets the button that was toggled (assuming you are reusing the same handler for several buttons). Then you can check its state to see if it was selected or deselected.
The way you do this is to connect with an adapter:
// do this for each button (this one is for "buttona"):
buttona.signal_toggled().connect(
sigc::bind(
sigc::mem_fun(*this, &myclass::handle_button_toggled),
buttona
)
);
In your class, handle_button_toggled includes the button parameter:
myclass {
Gtk::ToggleButton buttona, buttonb, ...
....
void handle_button_toggled(Gtk::ToggleButton &b) {
...check state of b ...
}
}
In C++11, you can alternatively use a lambda expression:
buttona.signal_toggled().connect([this,&buttona]{
handled_button_toggled(buttona);
});
// C++11
#include <gtkmm.h>
#include <iostream>
#include <vector>
using namespace std;
class RadioBox
{
public:
Gtk::Box {Gtk::ORIENTATION_HORIZONTAL};
vector<Gtk::RadioButton*> rb_list;
string selected_text;
int selected_pos;
RadioBox(int defpos,
std::initializer_list<string> rb_name)
{
add(box);
int i = 0;
for (auto& rb_name_i : rb_name) {
Gtk::RadioButton* rb = new Gtk::RadioButton{rb_name_i};
rb_list.push_back(rb);
if (i==defpos) {
rb->set_active();
}
box.pack_start(*rb, 0, 0);
if (i != 0) {
rb->join_group(*rb_list[0]);
}
rb->signal_toggled().connect(
sigc::bind(
sigc::mem_fun(*this, &LabRadio::clicked),
rb,
i
));
i++;
}
}
void clicked(Gtk::RadioButton* rb, int pos) {
if (!rb) return;
if (rb->get_active()) {
selected_pos = pos;
selected_text = rb->get_label().c_str();
cout << "RadioButton:selected"
<< " pos:" << selected_pos
<< " text:" << selected_text
<< "\n";
}
}
~RadioBox() {
rb_count = rb_list.size();
for(int i=0; i < rb_count; ++i) {
if (rb_list[i]) delete rb_list[i];
}
}
};
//USAGE:
class mywindow : public Gtk::Window {
public:
RadioBox myradiobox {2, {"Apples", "Pears", "Oranges", "Peaches"}};
// ... your code here
mywindow() {
// ...
<somewidget>.pack_start(myradiobox.box);
// ...
}
};