Nominal Animal |
04-28-2012 08:41 PM |
Quote:
Originally Posted by Keith Hedger
(Post 4665584)
Tried "button-release-event" the range widget doesn't seem to respond to this haven't looked at "key-release-event", will try tomorrow.
|
That is strange, as it works fine for me. Perhaps I'm using different library version? On my machine, both libgtk-3-0 and libgtk-3-dev are version 3.2.0-0ubuntu6.
Please try the following example program, to see if it works for you too:
Code:
#include <gtk/gtk.h>
#include <stdio.h>
void value_changed(GtkRange *range, gpointer user_data)
{
/* This does get called:
fputs("value_changed\n", stdout);
fflush(stdout);
*/
}
gboolean button_release_event(GtkWidget *widget, GdkEvent *event, gpointer user_data)
{
gdouble saved = *(gdouble *)user_data;
gdouble value = gtk_range_get_value((GtkRange *)widget);
if (saved != value) {
*(gdouble *)user_data = value;
fprintf(stdout, "button_release_event at %g\n", (double)value);
fflush(stdout);
} else {
fprintf(stdout, "button_release_event ignored\n");
fflush(stdout);
}
/* Do propagate this event further. */
return FALSE;
}
gboolean focus_out_event(GtkWidget *widget, GdkEvent *event, gpointer user_data)
{
gdouble saved = *(gdouble *)user_data;
gdouble value = gtk_range_get_value((GtkRange *)widget);
if (saved != value) {
*(gdouble *)user_data = value;
fprintf(stdout, "focus_out_event at %g\n", (double)value);
fflush(stdout);
} else {
fprintf(stdout, "focus_out_event ignored\n");
fflush(stdout);
}
/* Do propagate this event further. */
return FALSE;
}
gboolean key_release_event(GtkWidget *widget, GdkEvent *event, gpointer user_data)
{
gdouble saved = *(gdouble *)user_data;
gdouble value = gtk_range_get_value((GtkRange *)widget);
if (saved != value) {
*(gdouble *)user_data = value;
fprintf(stdout, "key_release_event at %g\n", (double)value);
fflush(stdout);
} else {
fprintf(stdout, "key_release_event ignored\n");
fflush(stdout);
}
/* Do propagate this event further. */
return FALSE;
}
int main(int argc, char *argv[])
{
GtkWidget *window;
GtkWidget *scale;
gdouble scale_old;
gtk_init(&argc, &argv);
window = gtk_window_new(GTK_WINDOW_TOPLEVEL);
gtk_window_set_default_size(GTK_WINDOW(window), 400, 50);
gtk_window_set_title(GTK_WINDOW(window), "Range");
g_signal_connect(window, "destroy", G_CALLBACK(gtk_main_quit), NULL);
scale_old = -1.0;
scale = gtk_scale_new_with_range(GTK_ORIENTATION_HORIZONTAL, 0.0, 100.0, 0.1);
gtk_container_add(GTK_CONTAINER(window), scale);
g_signal_connect(scale, "value-changed", G_CALLBACK(value_changed), NULL);
g_signal_connect(scale, "button-release-event", G_CALLBACK(button_release_event), &scale_old);
g_signal_connect(scale, "focus-out-event", G_CALLBACK(focus_out_event), &scale_old);
g_signal_connect(scale, "key-release-event", G_CALLBACK(key_release_event), &scale_old);
gtk_widget_show(scale);
gtk_widget_show(window);
gtk_main();
return 0;
}
For those not familiar with building GTK+ C programs, save the above as range.c, and compile using
Code:
gcc range.c `pkg-config gtk+-3.0 --cflags --libs` -o range
When you move the slider, the value is updated immediately (since the relevant callback, value_change, does nothing). You can uncomment the output in the value_change function to check.
When you release the slider, by releasing the mouse button, or releasing the key, or just by focusing elsewhere, one of the three callback functions ( *_event) gets called to trigger the desired action. The example program will just output the new value to standard output.
Note that all three signals could have been wired to the same callback function. I used separate functions, so I could easily observe that all desired signals do in fact occur.
Note how I used the user data pointer to point to a gdouble containing the last acted-upon value. Only when it is different to the current value, is there any work to do. When the last acted-upon value is still the same, there is nothing to do, and the signal can be ignored.
When there is work to do, the last acted-upon value should be updated. You most likely want to update it before starting the work (rather than when completing the work), so that you update it to the value you used for the large work. Otherwise you'd likely miss updates in between; the users see a different value than the other effects are.
|