Re: How to improve performance of this example?



hi,

the problem isn't the mouse going "too fast" (this is "not possible", if it can go fast, it can), it's that you're wanting to draw a line using points.

drawing a real line between the last point received by the drag event and the new/next point will get you what you want, example code below.

and to answer your question, yes it can be made more efficient.

cheers,

richard

p.s. be careful re: your callback parameters, your drag function defined the 2nd argument wrong.

======== BEGIN CODE EXAMPLE�========

#include <string.h>
#include <gtk/gtk.h>

enum {
MOUSE_CLICK,
MOUSE_DRAG,
TTL_MOUSE_EVENTS
};

static inline void brush(cairo_t *cr, double x1, double y1, double x2, double y2)
{
cairo_move_to(cr, x1, y1);
cairo_line_to(cr, x2, y2);
cairo_stroke(cr);
}

static gboolean handle_mouse(GtkWidget *widget, void *e, gpointer *t)
{
static struct {
gboolean isdragging;
cairo_t *cr;
double x, y;
} mouseState;
gint type = GPOINTER_TO_INT(t);
switch(type)
{
case MOUSE_CLICK:
{
GdkEventButton *event = (GdkEventButton*) e;
switch(event->type)
{
case GDK_BUTTON_PRESS:
{
mouseState.isdragging = TRUE;
mouseState.cr = gdk_cairo_create(widget->window);
cairo_set_source_rgb(mouseState.cr, 0, 0, 0);
cairo_set_line_width(mouseState.cr, 2);
mouseState.x = event->x; mouseState.y = event->y;
}
break;
case GDK_BUTTON_RELEASE:
{
cairo_destroy(mouseState.cr);
memset(&mouseState, 0, sizeof(mouseState));
}
break;
default:
break;
}
}
break;
case MOUSE_DRAG:
{
GdkEventMotion *event = (GdkEventMotion*) e;
static GdkWindow *gdkWindow;

if (!gdkWindow)
{ // initialize
gdkWindow = gdk_get_default_root_window();
memset(&mouseState, 0, sizeof(mouseState));
return TRUE;
}

if (!mouseState.isdragging ||
� ��(mouseState.x == event->x && mouseState.y == event->y))
return TRUE;

brush(mouseState.cr, mouseState.x, mouseState.y, event->x, event->y);
mouseState.x = event->x; mouseState.y = event->y;

{
// even though we don't use the resulting information from this call,�
// calling it is an indication to the main_loop()�
// that we are ready to receive the next mouse motion notify event
gint x, y;
GdkModifierType state;
gdk_window_get_pointer(gdkWindow, &x, &y, &state);
}
}
break;
default:
break;
}

return TRUE;
}

int main( int argc,
� � � � � char *argv[] )
{
� GtkWidget *window;
� GtkWidget *main_vbox;

� gtk_init (&argc, &argv);
��
� window = gtk_window_new(GTK_WINDOW_TOPLEVEL);
� gtk_signal_connect (GTK_OBJECT (window), "destroy", GTK_SIGNAL_FUNC (gtk_main_quit), "WM destroy");
� gtk_widget_set_usize (GTK_WIDGET(window), 300, 200);
��
� main_vbox = gtk_vbox_new (FALSE, 1);
� gtk_container_border_width (GTK_CONTAINER (main_vbox), 1);
� gtk_container_add (GTK_CONTAINER (window), main_vbox);
� gtk_widget_show (main_vbox);
� ��
� //gtkdrawable + cairo
� GtkWidget *canvas = gtk_drawing_area_new(); �
� gtk_widget_set_size_request (canvas, 500, 600);
��
� //gtk_widget_add_events(canvas, GDK_BUTTON_PRESS_MASK);
� gtk_widget_add_events(canvas, GDK_ALL_EVENTS_MASK);
� g_signal_connect(canvas, "button-press-event", G_CALLBACK(handle_mouse), GINT_TO_POINTER(MOUSE_CLICK));
� g_signal_connect(canvas, "button-release-event", G_CALLBACK(handle_mouse), GINT_TO_POINTER(MOUSE_CLICK));
� g_signal_connect(canvas, "motion-notify-event",G_CALLBACK(handle_mouse), GINT_TO_POINTER(MOUSE_DRAG));

� gtk_box_pack_start (GTK_BOX (main_vbox), canvas, FALSE, TRUE, 0);
��
� //ends gtkdrawable + cairo example � �
� gtk_widget_show_all (window);
� gtk_main ();
��
� return(0);
}

======== END CODE EXAMPLE�========

2011/7/23 Carlos L� Camey <c lopez kmels net>
Hello, I'm new to the list, GTK+ and C. I'm building a Paint-like
application and was trying how to simulate the Brush tool with an
example to see how it performs. I read about GtkImage, GtkBitmap and
GtkPixmap but was recommended in #gtk+ over at irc.gnome.org to use a
GtkDrawingArea + Cairo since in GTK3 some of these were deprecated,
and it's encouraged to use cairo surfaces instead.

The problem with my example is, when you click and "brush" with the
mouse moving *too fast*, the signal doesn't come fast enough. What
could/would be faster? using pixbufs + GtkImage? I couldn't find
enough documentation about that, but that's why I am asking :)

Here's what I got (or if you prefer http://paste.pocoo.org/show/444721/)

Thank you!

----- canvas-test.c ------
#include <gtk/gtk.h>

int isdragging = 0;

/* Brush, paints a single pixel in coordinate x,y*/
void brush(cairo_t *cr, double x, double y){
�cairo_set_source_rgb(cr, 0, 0, 0);
�cairo_set_line_width (cr, 1);
�cairo_rectangle(cr,x,y,1,1);
�cairo_stroke(cr);
�cairo_destroy(cr);
}

gboolean handle_mouse_click(GtkWidget *widget, GdkEventButton *event,
gpointer user_data){
�brush(gdk_cairo_create(widget->window), event->x, event->y);
�isdragging = 1;
�return TRUE;
}

gboolean handle_mouse_release(GtkWidget *widget, GdkEventButton
*event, gpointer user_data){
�if (event->button == 1) {
� �isdragging = 0;
�}

�return TRUE;
}

gboolean handle_mouse_drag(GtkWidget *widget, GdkEventButton *event,
gpointer user_data){
�if (isdragging)
� �brush(gdk_cairo_create(widget->window), event->x, event->y);
�return TRUE;
}

int main( int argc,
� � � � �char *argv[] )
{
�GtkWidget *window;
�GtkWidget *main_vbox;

�gtk_init (&argc, &argv);

�window = gtk_window_new (GTK_WINDOW_TOPLEVEL);
�gtk_signal_connect (GTK_OBJECT (window), "destroy", GTK_SIGNAL_FUNC
(gtk_main_quit), "WM destroy");
�gtk_widget_set_usize (GTK_WIDGET(window), 300, 200);

�main_vbox = gtk_vbox_new (FALSE, 1);
�gtk_container_border_width (GTK_CONTAINER (main_vbox), 1);
�gtk_container_add (GTK_CONTAINER (window), main_vbox);
�gtk_widget_show (main_vbox);

�//gtkdrawable + cairo
�GtkWidget *canvas = gtk_drawing_area_new();
�gtk_widget_set_size_request (canvas, 500, 600);

�//gtk_widget_add_events(canvas, GDK_BUTTON_PRESS_MASK);
�gtk_widget_add_events(canvas, GDK_ALL_EVENTS_MASK);
�g_signal_connect(canvas, "button-press-event",
G_CALLBACK(handle_mouse_click), NULL);
�g_signal_connect(canvas, "button-release-event",
G_CALLBACK(handle_mouse_release), NULL);
�g_signal_connect(canvas,
"motion-notify-event",G_CALLBACK(handle_mouse_drag), NULL);

�gtk_box_pack_start (GTK_BOX (main_vbox), canvas, FALSE, TRUE, 0);

�//ends gtkdrawable + cairo example
�gtk_widget_show_all (window);
�gtk_main ();

�return(0);
}
_______________________________________________
gtk-list mailing list
gtk-list gnome org
http://mail.gnome.org/mailman/listinfo/gtk-list



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