仅在选择时读取GTK单选按钮信号

时间:2012-11-14 18:31:20

标签: gtk gtkmm

GTK的“切换”信号在选择单选按钮时触发,但在此之前,它也会在取消选择先前选择的单选按钮时触发。

我正在使用一个使用单选按钮的GUI,每个按钮代表一组实体。这对“切换”信号中的第一个触发了对GUI中其他字段的一些不需要的更新 - 我只希望在新选择的按钮触发回调时发生更新。如何解决此信号并将回调函数限制为仅对选择进行操作而不是取消选择?我已经考虑过我正在编写的类中的一个标志变量,但也许有更多GTK认可的技术。

3 个答案:

答案 0 :(得分:1)

我认为你只能 获取选择信号,但你可以做其他事情。您可以编写信号处理程序,以便获取切换的按钮(假设您正在为多个按钮重用相同的处理程序)。然后,您可以检查其状态,以查看它是否已被选中或取消选中。

执行此操作的方法是使用适配器进行连接:

// 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
   )
);

在您的班级中,handle_button_toggled包含按钮参数:

myclass {
  Gtk::ToggleButton buttona, buttonb, ...
  ....
  void handle_button_toggled(Gtk::ToggleButton &b) {
   ...check state of b ...
  }
}

在C ++ 11中,您也可以使用lambda表达式:

buttona.signal_toggled().connect([this,&buttona]{
  handled_button_toggled(buttona); 
});

答案 1 :(得分:0)

// 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);
    // ...
  }

};

答案 2 :(得分:0)

This is a demo code using Radio Buttons, where you can find how I find which radio button is selected:
#include <gtkmm/window.h>
#include <gtkmm/box.h>
#include <gtkmm/radiobutton.h>
#include <gtkmm/separator.h>
#include <gtkmm/application.h>
#include <iostream>

class ButtonWindow : public Gtk::Window
{
private:
   //Child widgets:
   Gtk::Box m_Box_Top, m_Box1, m_Box2;
   Gtk::RadioButton m_RadioButton1, m_RadioButton2, m_RadioButton3;
   Gtk::Separator m_Separator;
   Gtk::Button m_Button_Close;
   Gtk::RadioButton *m_SelectedButton{nullptr};

public:
   ButtonWindow()
      : m_Box_Top(Gtk::ORIENTATION_VERTICAL),
        m_Box1(Gtk::ORIENTATION_VERTICAL, 15),
        m_Box2(Gtk::ORIENTATION_VERTICAL, 0),
        m_RadioButton1("button 1"),
        m_RadioButton2("button 2"),
        m_RadioButton3("button 3"),
        m_Button_Close("close")
   {
      // Set title and border of the window
      set_title("radio buttons");
      set_border_width(0);

      // Put radio buttons 2 and 3 in the same group as 1:
      m_RadioButton2.join_group(m_RadioButton1);
      m_RadioButton3.join_group(m_RadioButton1);

      // Add outer box to the window (because the window
      // can only contain a single widget)
      add(m_Box_Top);

      //Put the inner boxes and the separator in the outer box:
      m_Box_Top.pack_start(m_Box1);
      m_Box_Top.pack_start(m_Separator);
      m_Box_Top.pack_start(m_Box2);

      // Set the inner boxes' borders
      m_Box1.set_border_width(20);
      m_Box2.set_border_width(10);

      // Put the radio buttons in Box1:
      m_Box1.pack_start(m_RadioButton1);
      m_Box1.pack_start(m_RadioButton2);
      m_Box1.pack_start(m_RadioButton3);

      // Put Close button in Box2:
      m_Box2.pack_start(m_Button_Close);

      // Connect the button signals:
#if 1 // C++11: (change this to #if 0 to use the traditional way)
      m_RadioButton1.signal_clicked().connect([&]{on_radio_button_clicked(m_RadioButton1);});
      m_RadioButton2.signal_clicked().connect([&]{on_radio_button_clicked(m_RadioButton2);});
      m_RadioButton3.signal_clicked().connect([&]{on_radio_button_clicked(m_RadioButton3);});

      m_Button_Close.signal_clicked().connect([&]{on_close_button_clicked();});
#else // Traditional:
  m_RadioButton1.signal_clicked() // Full sigc
     .connect(sigc::bind(sigc::mem_fun(*this, &ButtonWindow::on_radio_button_clicked),
                         sigc::ref(m_RadioButton1)));

  m_RadioButton2.signal_clicked() // sigc && C++98
     .connect(std::bind(sigc::mem_fun(*this, &ButtonWindow::on_radio_button_clicked),
                        std::ref(m_RadioButton2)));

  m_RadioButton3.signal_clicked() // Full C++98
     .connect(std::bind(&ButtonWindow::on_radio_button_clicked, this,
                        std::ref(m_RadioButton3)));

      m_Button_Close.signal_clicked()
         .connect(sigc::mem_fun(*this, &ButtonWindow::on_close_button_clicked));
#endif

      // Set the second button active:
      m_RadioButton2.set_active();

      // Make the close button the default widget:
      m_Button_Close.set_can_default();
      m_Button_Close.grab_default();

      // Show all children of the window:
      show_all_children();
   }
  
protected:
   //Signal handlers:
   void on_radio_button_clicked(Gtk::RadioButton& button)
   {
      if(m_SelectedButton != &button && button.get_active())
      {
         m_SelectedButton = &button;
         std::cout << "Radio "<< m_SelectedButton->get_label() << " selected.\n";
      }
   }

   void on_close_button_clicked()
   {
      hide(); // Close the application
   }
};

int main(int argc, char *argv[])
{
   auto app = Gtk::Application::create(argc, argv, "org.gtkmm.example");

   ButtonWindow button;

   //Shows the window and returns when it is closed.
   return app->run(button);
}