Results 1 to 3 of 3
I'm making a widget layout editor as part of a project I'm working on.
I managed to use a GtkEventBox per widget (on a gtkFixed container) to intercept mouse drag ...
Enjoy an ad free experience by logging in. Not a member yet? Register.
- 03-21-2008 #1Just Joined!
- Join Date
- Mar 2008
- Posts
- 34
gtk: moving a widget with the mouse?
I'm making a widget layout editor as part of a project I'm working on.
I managed to use a GtkEventBox per widget (on a gtkFixed container) to intercept mouse drag events.
The mouse coordinates looked fine and dandy, until I started moving the widget then I started getting a bunch of spurious wildly off mouse event coordinates as the widget moved of the gtkFixed container
(I tried a number of things to attempt to filter these events with no joy)
I tried putting a single gtkEventBox over the widgets to be moved, but this seemed to visually obscure the widgets??
I tried a bunch of different things, and I'm at the point of starting again, has anyone else moved gtkWidgets about with the mouse?
I'll probably look at the glade source, but is quite a large code base and its gonna be hard to track down what I need.
Any ideas?
Thanks
C
- 03-22-2008 #2Just Joined!
- Join Date
- Mar 2008
- Posts
- 34
turns out you dont even need to use GtkEventBox's....
Code:#include <gtk/gtk.h> static gboolean delete_event( GtkWidget *widget, GdkEvent *event, gpointer data ) { g_print ("delete event occurred\n"); /* Change TRUE to FALSE and the main window will be destroyed with * a "delete_event". */ return false; } /* Another callback */ static void destroy( GtkWidget *widget, gpointer data ) { gtk_main_quit (); } GtkWidget *window; GtkWidget *button; GtkWidget *button2; GtkWidget *fixed; int sx,sy; static gboolean button_press_event( GtkWidget *widget, GdkEventButton *event ) { if (event->button == 1 ) printf("but down %i , %i\n", (int)event->x, (int)event->y); sx=(int)event->x; sy=(int)event->y; return TRUE; } static gboolean motion_notify_event( GtkWidget *widget, GdkEventMotion *event ) { int x, y; GdkModifierType state; gdk_window_get_pointer (window->window, &x, &y, &state); if (state & GDK_BUTTON1_MASK) { printf(" %i , %i \n", x-sx, y-sy); gtk_fixed_move( (GtkFixed*)fixed,(GtkWidget*)widget, x-sx, y-sy ); } return TRUE; } int main( int argc, char *argv[] ) { gtk_init (&argc, &argv); window = gtk_window_new (GTK_WINDOW_TOPLEVEL); button = gtk_button_new_with_label ("A button"); button2 = gtk_button_new_with_label ("Another button"); fixed=gtk_fixed_new(); gtk_container_add((GtkContainer*)window,(GtkWidget*)fixed); gtk_fixed_put( (GtkFixed*)fixed,button,50,50 ); gtk_fixed_put( (GtkFixed*)fixed,button2,250,100 ); g_signal_connect (G_OBJECT (window), "delete_event",G_CALLBACK (delete_event), NULL); g_signal_connect (G_OBJECT (window), "destroy",G_CALLBACK (destroy), NULL); gtk_signal_connect (GTK_OBJECT (button), "button_press_event",(GtkSignalFunc) button_press_event, NULL); gtk_signal_connect (GTK_OBJECT (button), "motion_notify_event",(GtkSignalFunc) motion_notify_event, NULL); gtk_signal_connect (GTK_OBJECT (button2), "button_press_event",(GtkSignalFunc) button_press_event, NULL); gtk_signal_connect (GTK_OBJECT (button2), "motion_notify_event",(GtkSignalFunc) motion_notify_event, NULL); gtk_container_set_border_width (GTK_CONTAINER (window), 0); gtk_widget_set_events(window, GDK_EXPOSURE_MASK | GDK_LEAVE_NOTIFY_MASK | GDK_BUTTON_PRESS_MASK | GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK); gtk_widget_set_events(button, GDK_EXPOSURE_MASK | GDK_LEAVE_NOTIFY_MASK | GDK_BUTTON_PRESS_MASK | GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK); gtk_widget_set_events(button2, GDK_EXPOSURE_MASK | GDK_LEAVE_NOTIFY_MASK | GDK_BUTTON_PRESS_MASK | GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK); gtk_widget_show (button); gtk_widget_show (button2); gtk_widget_show (fixed); gtk_widget_show (window); gtk_main (); return 0; }
- 10-04-2012 #3Just Joined!
- Join Date
- Oct 2012
- Posts
- 1
Follow-up
Hi Chris -
Thanks very much for posting your code. It helped me a lot getting my project off the ground. I thought I might share my rendition as well for anyone that might be able to benefit from it. This is based on your code (as I'm sure you'll recognize), but it also adds a bit of logic to do the following:
1) prevent the moving widget from leaving its container
2) allow the client to select the level of movement sensitivity thereby allowing a performance vs. smoothness tweak
I'm sure this could be done better, and I would love for someone to reply with more improvements. Cheers!
Ian
Code:#include <gtk/gtk.h> // higher values make movement more performant // lower values make movement smoother const gint Sensitivity = 10; const gint EvMask = GDK_BUTTON_PRESS_MASK | GDK_BUTTON1_MOTION_MASK; GtkWidget *fixed; int offsetx, offsety, px, py, maxx, maxy; inline static int Min(const int a, const int b) { return b < a ? b : a; } inline static int Max(const int a, const int b) { return b > a ? b : a; } inline static int RoundDownToMultiple(const int i, const int m) { return i/m*m; } inline static int RoundToNearestMultiple(const int i, const int m) { if (i % m > (double)m / 2.0d) return (i/m+1)*m; return i/m*m; } static void destroy( GtkWidget *widget, gpointer data ) { gtk_main_quit (); } static gboolean button_press_event( GtkWidget *w, GdkEventButton *event ) { if (event->button == 1) { GtkWidget* p = w->parent; // offset == distance of parent widget from edge of screen ... gdk_window_get_position(p->window, &offsetx, &offsety); // plus distance from pointer to edge of widget offsetx += (int)event->x; offsety += (int)event->y; // maxx, maxy both relative to the parent // note that we're rounding down now so that these max values don't get // rounded upward later and push the widget off the edge of its parent. maxx = RoundDownToMultiple(p->allocation.width - w->allocation.width, Sensitivity); maxy = RoundDownToMultiple(p->allocation.height - w->allocation.height, Sensitivity); } return TRUE; } static gboolean motion_notify_event( GtkWidget *widget, GdkEventMotion *event ) { // x_root,x_root relative to screen // x,y relative to parent (fixed widget) // px,py stores previous values of x,y // get starting values for x,y int x = (int)event->x_root - offsetx; int y = (int)event->y_root - offsety; // make sure the potential coordinates x,y: // 1) will not push any part of the widget outside of its parent container // 2) is a multiple of Sensitivity x = RoundToNearestMultiple(Max(Min(x, maxx), 0), Sensitivity); y = RoundToNearestMultiple(Max(Min(y, maxy), 0), Sensitivity); if (x != px || y != py) { px = x; py = y; gtk_fixed_move(GTK_FIXED(fixed), widget, x, y); } return TRUE; } GtkWidget* make_button(const gchar* const text) { GtkWidget* b = gtk_button_new_with_label(text); gtk_widget_add_events(b, EvMask); gtk_signal_connect(GTK_OBJECT(b), "button_press_event", (GtkSignalFunc)button_press_event, NULL); gtk_signal_connect(GTK_OBJECT(b), "motion_notify_event", (GtkSignalFunc)motion_notify_event, NULL); gtk_widget_show(b); return b; } int main(int argc, char *argv[] ) { gtk_init (&argc, &argv); // top level window GtkWidget* window = gtk_window_new (GTK_WINDOW_TOPLEVEL); gtk_container_set_border_width (GTK_CONTAINER (window), 0); g_signal_connect (G_OBJECT (window), "destroy",G_CALLBACK (destroy), NULL); // fixed container fixed=gtk_fixed_new(); gtk_container_add((GtkContainer*)window,(GtkWidget*)fixed); gtk_widget_show (fixed); // buttons gtk_fixed_put(GTK_FIXED(fixed), make_button("A button"), 50, 50); gtk_fixed_put(GTK_FIXED(fixed), make_button("Another button"), 250, 100); gtk_widget_show (window); gtk_main (); return 0; }




