使用Glade&;将切换按钮相互绑定;GTK&x2B;(C)中

使用Glade&;将切换按钮相互绑定;GTK&x2B;(C)中,c,gtk,gtk3,glade,C,Gtk,Gtk3,Glade,我有两个名为RUN和KILL的切换按钮。当我打开(即按下)运行按钮时,我只希望通过按下KILL toggle按钮(而不是关闭RUN按钮)将其关闭。我希望任何后续的鼠标点击RUN按钮都不做任何事情,除非按下KILL按钮。同样,当KILL按钮打开时,我只希望通过按下RUN按钮(同样,不是关闭KILL按钮)来关闭KILL按钮。我不知道如何构造将这两个切换按钮的操作绑定在一起的事件处理程序。我将GTK+与Glade一起使用,并使用C进行编程。因为GtkToggleButton是一个通用按钮,它将在所有用

我有两个名为RUN和KILL的切换按钮。当我打开(即按下)运行按钮时,我只希望通过按下KILL toggle按钮(而不是关闭RUN按钮)将其关闭。我希望任何后续的鼠标点击RUN按钮都不做任何事情,除非按下KILL按钮。同样,当KILL按钮打开时,我只希望通过按下RUN按钮(同样,不是关闭KILL按钮)来关闭KILL按钮。我不知道如何构造将这两个切换按钮的操作绑定在一起的事件处理程序。我将GTK+与Glade一起使用,并使用C进行编程。

因为
GtkToggleButton
是一个通用按钮,它将在所有用户交互中切换,我们必须防止它在特定条件下切换。在这种情况下,切换后的按钮不能在自身上再次切换,而是通过另一个切换按钮。要实现这一点,您必须:

  • 防止按钮事件在某些情况下切换按钮
  • 用反向逻辑绑定两个按钮(互斥)
  • 为了实现1)我们可以将回调连接到
    GtkWidget
    “按钮按下事件”
    信号,并根据需要的条件返回,TRUE防止信号传播,否则为FALSE

    然后,为了处理2),我们可以对
    GtkToggleButton“active”
    属性使用g_object_bind_属性和
    g_BINDING_inversed_BOOLEAN
    标志来获得所需的行为。请注意,我们必须将其中一个设置为活动状态作为启动条件

    因此,一个简单的例子可以是:

    #include <gtk/gtk.h>
    
    gboolean on_toggle_button_press_event(GtkWidget *widget, GdkEventButton *event, gpointer user_data) {
       if (gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(widget)) == TRUE) {
          return TRUE;
       }
    
       return FALSE;
    }
    
    void on_run_toggle_active(GObject *obj, GParamSpec *pspec, gpointer user_data) {
       g_return_if_fail (user_data != NULL);
    
       GtkLabel *label = GTK_LABEL(user_data);
       GtkToggleButton *button = GTK_TOGGLE_BUTTON(obj);
    
       if (gtk_toggle_button_get_active(button) == TRUE) {
          gtk_label_set_text (label, "Running...");
       } else {
          gtk_label_set_text (label, "Idle");
       }
    }
    
    gint main(gint argc, gchar **argv) {
       GtkLabel *status;
       GtkWindow *window;
       GtkBuilder *builder;
       GtkToggleButton *run_toggle;
       GtkToggleButton *kill_toggle;
    
       gtk_init(&argc, &argv);
    
       builder = gtk_builder_new_from_file("gui.ui");
    
       window      = GTK_WINDOW(gtk_builder_get_object(builder, "window1"));
       status      = GTK_LABEL(gtk_builder_get_object(builder, "status"));
       run_toggle  = GTK_TOGGLE_BUTTON(gtk_builder_get_object(builder, "toggle"));
       kill_toggle = GTK_TOGGLE_BUTTON(gtk_builder_get_object(builder, "kill"));
    
       g_object_bind_property (G_OBJECT(run_toggle), "active", G_OBJECT(kill_toggle), "active", G_BINDING_INVERT_BOOLEAN);
       g_object_bind_property (G_OBJECT(kill_toggle), "active", G_OBJECT(run_toggle), "active", G_BINDING_INVERT_BOOLEAN);
    
       g_signal_connect(G_OBJECT(run_toggle), "button-press-event", G_CALLBACK(on_toggle_button_press_event), NULL);
       g_signal_connect(G_OBJECT(kill_toggle), "button-press-event", G_CALLBACK(on_toggle_button_press_event), NULL);
       g_signal_connect(G_OBJECT(run_toggle), "notify::active", G_CALLBACK(on_run_toggle_active), status);
       g_signal_connect(G_OBJECT(window), "destroy", G_CALLBACK(gtk_main_quit), NULL);
    
       gtk_widget_show_all(GTK_WIDGET(window));
    
       gtk_main();
    
       return 0;
    }
    
    输出应该是这样的:

    切换按钮是互斥的,在激活时按下它们不会产生任何视觉效果


    PS:假设没有键盘处理,否则我们必须处理这些信号并相应地采取行动。

    这是非常不实际的,因为按钮之间的关系不一定很明显。不要让小部件以与外观不同的方式运行。您是否考虑过只使用一个切换按钮,在按下时将名称从RUN更改为KILL?也许使用一个普通的按钮就足够了,而不是在那种情况下切换按钮。
    <?xml version="1.0" encoding="UTF-8"?>
    <!-- Generated with glade 3.20.2 -->
    <interface>
      <requires lib="gtk+" version="3.18"/>
      <object class="GtkWindow" id="window1">
        <property name="can_focus">False</property>
        <child>
          <object class="GtkGrid">
            <property name="visible">True</property>
            <property name="can_focus">False</property>
            <property name="halign">center</property>
            <property name="valign">center</property>
            <property name="row_spacing">20</property>
            <child>
              <object class="GtkLabel" id="status">
                <property name="visible">True</property>
                <property name="can_focus">False</property>
                <property name="label" translatable="yes">Idle</property>
              </object>
              <packing>
                <property name="left_attach">0</property>
                <property name="top_attach">1</property>
                <property name="width">2</property>
              </packing>
            </child>
            <child>
              <object class="GtkBox">
                <property name="visible">True</property>
                <property name="can_focus">False</property>
                <child>
                  <object class="GtkToggleButton" id="toggle">
                    <property name="visible">True</property>
                    <property name="can_focus">False</property>
                    <property name="focus_on_click">False</property>
                    <property name="receives_default">True</property>
                    <child>
                      <object class="GtkBox">
                        <property name="visible">True</property>
                        <property name="can_focus">False</property>
                        <property name="spacing">3</property>
                        <child>
                          <object class="GtkImage">
                            <property name="visible">True</property>
                            <property name="can_focus">False</property>
                            <property name="icon_name">media-playback-start-symbolic</property>
                          </object>
                          <packing>
                            <property name="expand">False</property>
                            <property name="fill">True</property>
                            <property name="position">0</property>
                          </packing>
                        </child>
                        <child>
                          <object class="GtkLabel" id="label1">
                            <property name="visible">True</property>
                            <property name="can_focus">False</property>
                            <property name="label" translatable="yes">Run</property>
                          </object>
                          <packing>
                            <property name="expand">False</property>
                            <property name="fill">True</property>
                            <property name="position">1</property>
                          </packing>
                        </child>
                      </object>
                    </child>
                  </object>
                  <packing>
                    <property name="expand">False</property>
                    <property name="fill">True</property>
                    <property name="position">0</property>
                  </packing>
                </child>
                <child>
                  <object class="GtkToggleButton" id="kill">
                    <property name="visible">True</property>
                    <property name="can_focus">True</property>
                    <property name="receives_default">True</property>
                    <property name="active">True</property>
                    <child>
                      <object class="GtkBox">
                        <property name="visible">True</property>
                        <property name="can_focus">False</property>
                        <property name="spacing">3</property>
                        <child>
                          <object class="GtkImage">
                            <property name="visible">True</property>
                            <property name="can_focus">False</property>
                            <property name="icon_name">user-trash-symbolic</property>
                          </object>
                          <packing>
                            <property name="expand">False</property>
                            <property name="fill">True</property>
                            <property name="position">0</property>
                          </packing>
                        </child>
                        <child>
                          <object class="GtkLabel" id="label2">
                            <property name="visible">True</property>
                            <property name="can_focus">False</property>
                            <property name="label" translatable="yes">Kill</property>
                          </object>
                          <packing>
                            <property name="expand">False</property>
                            <property name="fill">True</property>
                            <property name="position">1</property>
                          </packing>
                        </child>
                      </object>
                    </child>
                  </object>
                  <packing>
                    <property name="expand">False</property>
                    <property name="fill">True</property>
                    <property name="position">1</property>
                  </packing>
                </child>
                <style>
                  <class name="linked"/>
                </style>
              </object>
              <packing>
                <property name="left_attach">0</property>
                <property name="top_attach">0</property>
                <property name="width">2</property>
              </packing>
            </child>
          </object>
        </child>
        <child type="titlebar">
          <placeholder/>
        </child>
      </object>
      <object class="GtkSizeGroup">
        <widgets>
          <widget name="label1"/>
          <widget name="label2"/>
        </widgets>
      </object>
    </interface>
    
    gcc -o main main.c `pkg-config --cflags --libs gtk+-3.0`