由于GtkToggleButton是一个通用按钮,它会随着所有用户交互而切换,我们必须防止它在某些条件下切换。在这种情况下,被切换后的按钮不能在自身上再次切换,而是通过另一个切换按钮。要实现这一目标,您必须:
为了实现 1) 我们可以将回调连接到GtkWidget "button-press-event"信号并根据需要的条件返回,TRUE 阻止信号传播,否则 FALSE。
然后,为了处理 2),我们可以使用 g_object_bind_property 作为GtkToggleButton "active"带有G_BINDING_INVERTED_BOOLEAN标志的属性来获得所需的行为。请注意,我们必须将其中一个设置为 active 作为开始条件。
所以,一个简单的例子可能是:
#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;
}
Run Code Online (Sandbox Code Playgroud)
为简化起见,我用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>
Run Code Online (Sandbox Code Playgroud)
编译:
gcc -o main main.c `pkg-config --cflags --libs gtk+-3.0`
Run Code Online (Sandbox Code Playgroud)
输出应该是这样的:
切换按钮是相互排斥的,在活动时按下它们不会产生任何视觉效果。
PS:假设没有键盘处理,否则我们必须处理这些信号并采取相应的行动。