【问题标题】:Read GTK Radio Button signal only when selected仅在选中时读取 GTK 单选按钮信号
【发布时间】:2012-11-14 18:31:19
【问题描述】:

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

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

【问题讨论】:

    标签: gtk gtkmm


    【解决方案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); 
    });
    

    【讨论】:

    • 我是否认为这也可以通过连接activated 信号而不是toggled 信号来实现?
    【解决方案2】:
    // 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);
        // ...
      }
    
    };
    

    【讨论】:

      【解决方案3】:
      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);
      }
      

      【讨论】:

      • 您能否澄清一下这如何解决所提出的问题?
      • 是的,先生,我在第一行中添加了该示例显示我如何找到选择了哪个单选按钮。在回复您时,我现在意识到我使用的是 gtkmm 而不是 gtk+,因为问题可能会问。如果是这样的话,我认为这段代码无论如何都是有用的。
      • 我还想澄清一下,我编写了不同的方法来连接信号。第一个是我在 C++11 中的做法。您可以使用#if 1 来选择它,如果您将if 更改为#if 0,您将获得gtkmm 手册中解释的表格。但是,在这种情况下,我还编写了三个替代方案来编写信号。
      猜你喜欢
      • 1970-01-01
      • 2020-02-19
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2019-06-15
      • 1970-01-01
      • 2021-07-03
      • 2020-06-22
      相关资源
      最近更新 更多