crazy behaviour of GtkFixed children



Hello,

I'm trying to achieve a canvas-like functionality using a GtkFixed widget. I know, there's GnomeCanvas, but I can't use it, it's buggy on win32. The problem is, when I'm trying to move a widget it starts shaking, like having a double. You can try it for yourself.
Where am I doing wrong? Is there any alternative?

Here's the code. Click on the label above the button and try moving it.


#include <gtk/gtk.h>

/* I'm going to be lazy and use some global variables to
 * store the position of the widget within the fixed
 * container */
gint x = 50;
gint y = 50;

/* This callback function moves the button to a new position
 * in the Fixed container. */
void move_button( GtkWidget *widget,
                  GtkWidget *fixed )
{
  x = (x + 30) % 300;
  y = (y + 50) % 300;
  gtk_fixed_move (GTK_FIXED (fixed), widget, x, y); 
}

int dragging, item_x, item_y, new_x, new_y;

void do_move (GtkWidget *w)
{
			   GtkWidget *vbox = g_object_get_data(w, "vbox");
			   GtkWidget *fixed = g_object_get_data(w, "fixed");
				   gtk_fixed_move (GTK_FIXED (fixed), vbox, new_x, new_y); 
}

gint img_event (GtkWidget *w, GdkEvent *ev, int where)
{

	if (ev->type == GDK_BUTTON_PRESS ||
		ev->type == GDK_BUTTON_RELEASE ||
		ev->type == GDK_MOTION_NOTIFY) {
	}
	else {
		return FALSE;
	}
	   
	switch (ev->type) {
	case GDK_BUTTON_PRESS:
		switch (ev->button.button) {
		case 1: {
			GtkWidget *vbox = g_object_get_data(w, "vbox");
			item_x = ev->button.x;
			item_y = ev->button.y;
			gtk_grab_add (w);
			dragging = 1;
			break;
			}
		}
		break;	
   case GDK_MOTION_NOTIFY:
	   if (ev->motion.state & GDK_BUTTON1_MASK) {      
		   if (dragging) {           
			   GtkWidget *vbox = g_object_get_data(w, "vbox");
			   GtkWidget *fixed = g_object_get_data(w, "fixed");
			   GtkWidget *g = gtk_grab_get_current ();
			   g_return_val_if_fail(vbox!=NULL, FALSE);
			   new_x = ev->motion.x;
			   new_y = ev->motion.y;           
			   g_idle_add (do_move, w);

		   }
	   }
	   break;
	case GDK_BUTTON_RELEASE:				
		gtk_grab_remove(gtk_grab_get_current ());
		break;    
	}

	return FALSE;
}

int main( int   argc,
          char *argv[] )
{
  /* GtkWidget is the storage type for widgets */
  GtkWidget *window;
  GtkWidget *fixed;
  GtkWidget *button, *vbox, *label;
  gint i;

  /* Initialise GTK */
  gtk_init (&argc, &argv);
    
  /* Create a new window */
  window = gtk_window_new (GTK_WINDOW_TOPLEVEL);
  gtk_window_set_title (GTK_WINDOW (window), "Fixed Container");

  /* Here we connect the "destroy" event to a signal handler */ 
  g_signal_connect (G_OBJECT (window), "destroy",
		    G_CALLBACK (gtk_main_quit), NULL);
 
  /* Sets the border width of the window. */
  gtk_container_set_border_width (GTK_CONTAINER (window), 10);

  /* Create a Fixed Container */
  fixed = gtk_fixed_new ();
  gtk_container_add (GTK_CONTAINER (window), fixed);
  gtk_widget_show (fixed);
  
  for (i = 1 ; i <= 3 ; i++) {
    /* Creates a new button with the label "Press me" */
    button = gtk_button_new_with_label ("Press me");
  
    /* When the button receives the "clicked" signal, it will call the
     * function move_button() passing it the Fixed Container as its
     * argument. */
    g_signal_connect (G_OBJECT (button), "clicked",
		      G_CALLBACK (move_button), (gpointer) fixed);

	vbox = gtk_vbox_new (FALSE,2);
	label = gtk_label_new ("gutfhg");

	{
		GtkWidget *event_box = gtk_event_box_new ();	
		gtk_container_add (GTK_CONTAINER (event_box), label); 
		gtk_widget_add_events (event_box, GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK | GDK_BUTTON_MOTION_MASK);		
		g_signal_connect(G_OBJECT(event_box), "event", G_CALLBACK(img_event), 0);		
		gtk_box_pack_start (GTK_BOX (vbox), 		
			event_box, FALSE, FALSE, 0); 

	
		g_object_set_data (G_OBJECT(event_box), "vbox", vbox);
		g_object_set_data (G_OBJECT(event_box), "fixed", fixed);
	}

	gtk_box_pack_start(GTK_BOX(vbox), button, TRUE, TRUE, 0);



    /* This packs the button into the fixed containers window. */
    gtk_fixed_put (GTK_FIXED (fixed), vbox, i*50, i*50);
  
    /* The final step is to display this newly created widget. */
    gtk_widget_show_all (vbox);
  }

  /* Display the window */
  gtk_widget_show (window);
    
  /* Enter the event loop */
  gtk_main ();
    
  return 0;
}  

-- 
_______________________________________________
Get your free email from http://mymail.skim.com




[Date Prev][Date Next]   [Thread Prev][Thread Next]   [Thread Index] [Date Index] [Author Index]