使用C中的GTK3,我有一个带按钮的界面。我希望使用鼠标的用户能够按下一个按钮,或者使用键盘上的一个按钮来做同样的事情。
MWE(修改自GTK3 Hello World示例(:
/*
* Ignore keyboard cursor in GTK3 C
*/
#include <gtk/gtk.h>
void thing() {
printf("did a thingn");
}
void otherthing() {
printf("did something differentn");
}
static gboolean key_event(GtkWidget *widget, GdkEventKey *event) {
gchar* val = gdk_keyval_name (event->keyval);
if (strcmp(val, "Left") == 0) {
thing();
}
return 0;
}
static void activate (GtkApplication *app, gpointer user_data) {
GtkWidget *window;
GtkWidget *button;
GtkWidget *button2;
GtkWidget *button_box;
window = gtk_application_window_new (app);
gtk_window_set_title (GTK_WINDOW (window), "Window");
gtk_window_set_default_size (GTK_WINDOW (window), 200, 200);
button_box = gtk_button_box_new (GTK_ORIENTATION_HORIZONTAL);
gtk_container_add (GTK_CONTAINER (window), button_box);
button = gtk_button_new_with_label ("Do the thing");
button2 = gtk_button_new_with_label ("xxx");
g_signal_connect(window, "key-release-event", G_CALLBACK(key_event), NULL);
g_signal_connect (button, "clicked", G_CALLBACK (thing), window);
g_signal_connect (button2, "clicked", G_CALLBACK (otherthing), window);
gtk_container_add (GTK_CONTAINER (button_box), button2);
gtk_container_add (GTK_CONTAINER (button_box), button);
gtk_widget_show_all (window);
}
int main (int argc, char **argv) {
GtkApplication *app;
int status;
app = gtk_application_new ("org.gtk.example", G_APPLICATION_FLAGS_NONE);
g_signal_connect (app, "activate", G_CALLBACK (activate), NULL);
status = g_application_run (G_APPLICATION (app), argc, argv);
g_object_unref (app);
return status;
}
在该程序中,用户可以按下向左箭头键来执行thing
。用户也可以点击gui按钮执行thing
。但是,点击某些键盘键,如空格或回车键,会"点击"gui按钮来执行thing
。
在这种情况下,如何防止键盘"点击"键盘光标所在的按钮?
假按钮破解
我已经用一个无用的按钮在我的代码中破解了一个变通方法。我不会把这个答案标记为已解决,因为它非常草率,但它会起作用,直到有更好的东西可用。
说明
这个黑客添加了另一个没有分配功能的按钮。使用gtk_widget_grab_focus
,我们强制这个无用的"fakebutton"保持键盘焦点。每次按下按钮时,我们都会重新发出此命令。
问题
将焦点移回fakebutton是很慢的。用户可以快速发出一系列命令(在MWE的情况下,按下左和空格MWE
/*
* Ignore keyboard cursor in GTK3 C
*/
#include <gtk/gtk.h>
GtkWidget *fakebutton;
void thing() {
printf("did a thingn");
}
void otherthing() {
printf("did something differentn");
}
static gboolean key_event(GtkWidget *widget, GdkEventKey *event) {
gchar* val = gdk_keyval_name (event->keyval);
if (strcmp(val, "Left") == 0) {
thing();
gtk_widget_grab_focus(fakebutton);
} else {
gtk_widget_grab_focus(fakebutton);
}
return 0;
}
static void activate (GtkApplication *app, gpointer user_data) {
GtkWidget *window;
GtkWidget *button;
GtkWidget *button2;
GtkWidget *button_box;
window = gtk_application_window_new (app);
gtk_window_set_title (GTK_WINDOW (window), "Window");
gtk_window_set_default_size (GTK_WINDOW (window), 200, 200);
button_box = gtk_button_box_new (GTK_ORIENTATION_HORIZONTAL);
gtk_container_add (GTK_CONTAINER (window), button_box);
button = gtk_button_new_with_label ("Do the thing");
button2 = gtk_button_new_with_label ("xxx");
fakebutton = gtk_button_new();
g_signal_connect(window, "key-release-event", G_CALLBACK(key_event), NULL);
g_signal_connect (button, "clicked", G_CALLBACK (thing), window);
g_signal_connect (button2, "clicked", G_CALLBACK (otherthing), window);
gtk_container_add (GTK_CONTAINER (button_box), button2);
gtk_container_add (GTK_CONTAINER (button_box), fakebutton);
gtk_container_add (GTK_CONTAINER (button_box), button);
gtk_widget_show_all (window);
}
int main (int argc, char **argv) {
GtkApplication *app;
int status;
app = gtk_application_new ("org.gtk.example", G_APPLICATION_FLAGS_NONE);
g_signal_connect (app, "activate", G_CALLBACK (activate), NULL);
status = g_application_run (G_APPLICATION (app), argc, argv);
g_object_unref (app);
return status;
}