I want to use expose-event
to draw something then update or redraw. That's to say, there are a drawing area and a button in window. When clicking button, the drawing area will be redrawn accordingly. My problems are
In the following code, if I changed
gtk_container_add (GTK_CONTAINER (box), canvas);
togtk_box_pack_start(GTK_BOX(box), canvas, FALSE, FALSE, 0);
, nothing is drawn. Usually we usegtk_box_pack_start
to add something into box. Why doesn't it work this time?The function
build_ACC_axis
refreshed(deleted what has drawn) drawing area and prepared for new draw. But it didn't delete what has drawn. Why? How to refresh the drawing area?
If the source file is test.c, then compilation is
gcc -o test test.c `pkg-config --cflags --libs gtk+-2.0`
The code is below:
#include <gtk/gtk.h>
#include <glib.h>
static void draw (GdkDrawable *d, GdkGC *gc)
{
/* Draw with GDK */
gdk_draw_line (d, gc, 0, 0, 50, 50);
gdk_draw_line (d, gc, 50, 50, 50, 150);
gdk_draw_line (d, gc, 50, 150, 0, 200);
gdk_draw_line (d, gc, 200, 0, 150, 50);
gdk_draw_line (d, gc, 150, 50, 150, 150);
gdk_draw_line (d, gc, 150, 150, 200, 200);
gdk_draw_line (d, gc, 50, 50, 150, 50);
gdk_draw_line (d, gc, 50, 150, 150, 150);
}
static gboolean expose_cb (GtkWidget *canvas, GdkEventExpose *event, gpointer user_data)
{
GdkGC *gc;
gc = gdk_gc_new (canvas->window);
draw (canvas->window, gc);
g_object_unref (gc);
return FALSE;
}
void build_ACC_axis (GtkWidget *button, GtkWidget *widget)
{
GdkRegion *region;
GtkWidget *canvas = g_object_get_data(G_OBJECT(widget), "plat_GA_canvas");
region = gdk_drawable_get_visible_region(canvas->window);
gdk_window_invalidate_region(canvas->window, region, TRUE);
gtk_widget_queue_draw(canvas);
/* gdk_window_process_updates(canvas->window, TRUE); */
gdk_region_destroy (region);
}
int main (int argc, char **argv)
{
GtkWidget *window;
GtkWidget *canvas, *box, *button;
gtk_init (&argc, &argv);
window = gtk_window_new (GTK_WINDOW_TOPLEVEL);
gtk_widget_set_size_request(window, 500, 300);
g_signal_connect (G_OBJECT (window), "destroy", G_CALLBACK (gtk_main_quit), NULL);
box = gtk_vbox_new(FALSE, 0);
gtk_container_add (GTK_CONTAINER (window), box);
canvas = gtk_drawing_area_new ();
g_object_set_data(G_OBJECT(window), "plat_GA_canvas", canvas);
/* gtk_box_pack_start(GTK_BOX(box), canvas, FALSE, FALSE, 0); */
gtk_container_add (GTK_CONTAINER (box), canvas);
g_signal_connect (G_OBJECT (canvas), "expose-event", G_CALLBACK (expose_cb), NULL);
button = gtk_button_new_with_label ("ok");
gtk_box_pack_start(GTK_BOX(box), button, FALSE, FALSE, 0);
/* gtk_container_add (GTK_CONTAINER (box), button); */
gtk_signal_connect(GTK_OBJECT(button), "clicked", GTK_SIGNAL_FUNC(build_ACC_axis), window);
gtk_widget_show_all (window);
gtk_main ();
}
I would like to answer my second question. After clicking button, it would send expose-event
signal and run expose_cb
. Since there is no change in draw
function, we can't see the refreshing. Following is the updated code that can show refreshing. The point is to add variable factor
. But for the first question, I still didn't know why.
#include <gtk/gtk.h>
#include <glib.h>
int factor;
static void draw (GdkDrawable *d, GdkGC *gc, double fac)
{
/* Draw with GDK */
gdk_draw_line (d, gc, 0, 0, 50, 50 * fac);
gdk_draw_line (d, gc, 50, 50, 50, 150);
gdk_draw_line (d, gc, 50, 150, 0, 200);
gdk_draw_line (d, gc, 200, 0, 150, 50);
gdk_draw_line (d, gc, 150, 50, 150, 150);
gdk_draw_line (d, gc, 150, 150, 200, 200);
gdk_draw_line (d, gc, 50, 50, 150, 50);
gdk_draw_line (d, gc, 50, 150, 150, 150);
}
static gboolean expose_cb (GtkWidget *canvas, GdkEventExpose *event, gpointer user_data)
{
GdkGC *gc;
gc = gdk_gc_new (canvas->window);
draw (canvas->window, gc, factor);
g_object_unref (gc);
return FALSE;
}
void build_ACC_axis (GtkWidget *button, GtkWidget *widget)
{
GdkRegion *region;
GtkWidget *canvas = g_object_get_data(G_OBJECT(widget), "plat_GA_canvas");
region = gdk_drawable_get_visible_region(canvas->window);
gdk_window_invalidate_region(canvas->window, region, TRUE);
/* gtk_widget_queue_draw(canvas); */
gdk_window_process_updates(canvas->window, TRUE);
gdk_region_destroy (region);
factor++;
}
int main (int argc, char **argv)
{
GtkWidget *window;
GtkWidget *canvas, *box, *button;
gtk_init (&argc, &argv);
factor = 1;
window = gtk_window_new (GTK_WINDOW_TOPLEVEL);
gtk_widget_set_size_request(window, 500, 300);
g_signal_connect (G_OBJECT (window), "destroy", G_CALLBACK (gtk_main_quit), NULL);
box = gtk_vbox_new(FALSE, 0);
gtk_container_add (GTK_CONTAINER (window), box);
canvas = gtk_drawing_area_new ();
g_object_set_data(G_OBJECT(window), "plat_GA_canvas", canvas);
/* gtk_box_pack_start(GTK_BOX(box), canvas, FALSE, FALSE, 0); */
gtk_container_add (GTK_CONTAINER (box), canvas);
g_signal_connect (G_OBJECT (canvas), "expose-event", G_CALLBACK (expose_cb), NULL);
button = gtk_button_new_with_label ("ok");
gtk_box_pack_start(GTK_BOX(box), button, FALSE, FALSE, 0);
/* gtk_container_add (GTK_CONTAINER (box), button); */
gtk_signal_connect(GTK_OBJECT(button), "clicked", GTK_SIGNAL_FUNC(build_ACC_axis), window);
gtk_widget_show_all (window);
gtk_main ();
}