簡體   English   中英

使用Glade和GTK +(在C語言中)將切換按鈕彼此綁定

[英]Binding Toggle Buttons to each other using Glade & GTK+ (in C)

我有兩個名為RUN和KILL的切換按鈕。 當我打開(即按下)RUN按鈕時,我只希望通過按下KILL切換按鈕將其關閉(而不是通過關閉RUN按鈕來關閉)。 我希望隨后的所有鼠標在RUN按鈕上單擊均不執行任何操作,除非按下KILL按鈕。 同樣,當打開“殺死”按鈕時,我只希望通過按下“運行”按鈕將其關閉(同樣,不要通過關閉“殺死”按鈕來關閉)。 我不確定如何構造將這兩個切換按鈕的動作綁定在一起的事件處理程序。 我將GTK +與Glade一起使用,並使用C進行編程。

由於GtkToggleButton是通用按鈕,它將與所有用戶交互進行切換,因此我們必須防止其在某些情況下切換。 在這種情況下,切換后的按鈕無法再次在其自身上進行切換,而只能通過另一個切換按鈕進行切換。 為此,您必須:

  1. 在某些情況下防止按鈕事件切換按鈕
  2. 將兩個按鈕綁定為反向邏輯(互斥)

要實現1),我們可以將回調函數連接到GtkWidget "button-press-event"信號並根據所需條件返回,如果為TRUE,則阻止信號傳播,否則為FALSE。

然后,為處理2),我們可以對GtkToggleButton "active"屬性使用g_object_bind_property,並GtkToggleButton "active"帶有G_BINDING_INVERTED_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;
}

為簡化起見,我用glade( gui.ui )概述了用戶界面:

<?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`

輸出應該是這樣的:

產量

切換按鈕是互斥的,並且在激活時按下它們不會產生任何視覺效果。

PS:不假定使用鍵盤操作,否則我們必須處理這些信號並采取相應措施。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM