Diego Allen
Diego Allen

Reputation: 4653

Redrawing a widget in Gtk

I'm trying to redraw a GtkDrawingArea using the gtk_widget_queue_draw function, but the widget is not redrawing.

Here's the code, the gtk_widget_queue_draw is inside a button-press-event callback function.

static gboolean click(GtkWidget *board,GdkEventButton *event,gpointer parentWindow){
    static int origen = -1;
    static int destino = -1;

    if(origen == -1){
        mapeo(&origen, event->x, event->y);
    }else{
       mapeo(&destino, event->x, event->y);
    if(!movimiento_fichas(JUGADOR_DOS, origen - 1, destino - 1)){
        dialogoMovInvalido(parentWindow); //displays a warning dialog
        g_print("%d %d", origen, destino); //debugging console output
        origen = -1; destino = -1;
    }else{
        g_print("%d %d", origen, destino); //debugging console output
        gtk_widget_queue_draw(board); //Here's where the redrawing is supossed to occur.
       }
    }

    return 0;
}

Expose-event callback

static gboolean onExposeEvent(GtkWidget *widget,GdkEventExpose *event,gpointer data){
    cairo_t *cr;
    cairo_surface_t *fondo;
    cairo_surface_t *ficha_roja;
    cairo_surface_t *ficha_blanca;

gint i,j;

cr = gdk_cairo_create(widget->window);

fondo = cairo_image_surface_create_from_png("interfaz.png");
ficha_roja = cairo_image_surface_create_from_png("ficha_roja.png");
ficha_blanca = cairo_image_surface_create_from_png("ficha_blanca.png");

cairo_set_source_surface(cr, fondo, 0, 0);
cairo_paint(cr);

for(i=0; i<24; i++){
    if(tablero[i].player == JUGADOR_UNO){
        cairo_set_source_surface(cr, ficha_blanca, posiciones[i].x, posiciones[i].y);
        for(j=1; j<=tablero[i].num; j++){
            cairo_paint(cr);
            cairo_set_source_surface(cr, ficha_blanca, posiciones[i].x, posiciones[i].y);
            if(i < 12)
                cairo_set_source_surface(cr, ficha_blanca, posiciones[i].x, posiciones[i].y - (j*25));
            else
                cairo_set_source_surface(cr, ficha_blanca, posiciones[i].x, posiciones[i].y + (j*25));
        }
    }else if(tablero[i].player == JUGADOR_DOS){
        cairo_set_source_surface(cr, ficha_roja, posiciones[i].x, posiciones[i].y);
        for(j=1; j<=tablero[i].num; j++){
            cairo_paint(cr);
            if(i < 12)
                cairo_set_source_surface(cr, ficha_roja, posiciones[i].x, posiciones[i].y - (j*25));
            else
                cairo_set_source_surface(cr, ficha_roja, posiciones[i].x, posiciones[i].y + (j*25));
        }
    }
}

cairo_destroy(cr);

return 0;
}

Expose-event & button-press-event connections (both inside the function that creates the top level window).

  g_signal_connect(G_OBJECT(board),"expose-event",G_CALLBACK(onExposeEvent),NULL);
  g_signal_connect(G_OBJECT(board),"button-press-event",G_CALLBACK(click),window);

Main function.

int main(int argc, char *argv[]){
    gtk_init(&argc, &argv);

    mainWindow(); //Creates the main window

    gtk_main();

    return 0;
}

Upvotes: 3

Views: 3769

Answers (2)

Diego Allen
Diego Allen

Reputation: 4653

Found the answer, there's nothing wrong with the gtk code. Code specific to my program was causing the error.

Upvotes: 0

user319799
user319799

Reputation:

It is not possible to tell conclusively what's wrong, since you didn't paste all the relevant code. Anyway, I think there might be two errors/misunderstanding that result in your problem.

  • You should draw only in expose-event signal handler. While drawing outside it is possible, such drawing will not be updated and might get completely lost for any number of reasons, including such self-initiated redrawing.
  • Redrawing will happen asynchronously. I.e. in a different main loop run. This might be problematic if you run the main loop in a non-standard way, e.g. using gtk_events_pending()/gtk_main_iteration().

Finally, check that board is actually the widget you intend to redraw. Might be that you passed wrong user data when connecting click().

Upvotes: 4

Related Questions