Re: How to improve performance of this example?
- From: Carlos López Camey <c lopez kmels net>
- To: richard boaz <ivor boaz gmail com>
- Cc: gtk-list gnome org
- Subject: Re: How to improve performance of this example?
- Date: Sat, 23 Jul 2011 15:17:50 -0600
Thank you Richard, the code you wrote works for me and it gave me
ideas on how to re-structure mine.
2011/7/23 richard boaz <ivor boaz gmail com>:
> 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ópez 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]