Please refer to the snippet below.
//gcc `pkg-config --cflags --libs gtk4` multiple_graphs.c -lcairo -lgtk-4 -lglib-2.0 -lgio-2.0 -lgobject-2.0 && ./a.out
#include<gtk/gtk.h>
const int graph_height = 200;
const int graph_width = 300;
const int num_of_graphs = 3;
struct node
{
int position;
int execute_count;
GtkWidget *button;
GtkWidget *box;
GtkWidget *drawing_area;
cairo_surface_t *surface;
cairo_t *cr;
};
void on_draw_event( GtkDrawingArea *drawing_area, cairo_t *cr, int width, int height, gpointer param )
{
struct node * const param_node = param;
const GdkRGBA rgba =
{
.red = ((float)(random()%101))/100,
.green = ((float)(random()%101))/100,
.blue = ((float)(random()%101))/100,
.alpha = 1,
};
const int x1 = random()%width;
const int x2 = random()%width;
const int y1 = random()%height;
const int y2 = random()%height;
gdk_cairo_set_source_rgba( param_node->cr, &rgba );
cairo_move_to( param_node->cr, x1, y1 );
cairo_line_to( param_node->cr, x2, y2 );
cairo_stroke( param_node->cr );
cairo_set_source_surface( cr, param_node->surface, 0, 0 );
cairo_paint( cr );
param_node->execute_count++;
}
gboolean draw_graphs( gpointer param )
{
struct node *all_nodes = param;
for( int i=0; i<num_of_graphs; i++ )
{
gtk_widget_queue_draw( all_nodes[i].drawing_area );
}
return G_SOURCE_CONTINUE;
}
struct node * prv_node;
static gboolean button_clicked( GtkButton *button, gpointer param )
{
struct node * const param_node = param;
gtk_widget_set_visible( prv_node->box, false );
prv_node = param_node;
gtk_widget_set_visible( param_node->box, true );
return G_SOURCE_CONTINUE;
}
static gboolean close_request_received( GtkWindow *main_window, gpointer param )
{
struct node *all_nodes = param;
for( int i=0; i<num_of_graphs; i++ )
{
printf( "Graph %d count: %d\n", i, all_nodes[i].execute_count );
}
gtk_window_destroy( main_window );
}
static void activate( GtkApplication *app, gpointer argv )
{
GtkWidget *main_window = gtk_application_window_new( app );
GtkWidget *main_vbox = gtk_box_new( GTK_ORIENTATION_VERTICAL, 5 );
gtk_window_set_child( (GtkWindow*)main_window, main_vbox );
GtkWidget *button_hbox = gtk_box_new( GTK_ORIENTATION_HORIZONTAL, 5 );
gtk_box_append( (GtkBox*)main_vbox, button_hbox );
struct node *all_nodes = calloc( sizeof(struct node), num_of_graphs );
if( g_signal_connect( main_window, "close-request", G_CALLBACK(close_request_received), all_nodes ) <= 0 )
{
fprintf( stderr, "%s %d\n", __func__, __LINE__ );
exit( EXIT_FAILURE );
}
char button_name[20];
for( int i=0; i<num_of_graphs; i++ )
{
all_nodes[i].position = i;
sprintf( button_name, "Graph %d", i );
all_nodes[i].button = gtk_button_new_with_label( button_name );
gtk_box_append( (GtkBox*)button_hbox, all_nodes[i].button );
if( g_signal_connect( G_OBJECT(all_nodes[i].button), "clicked", G_CALLBACK( button_clicked ), &all_nodes[i] ) <= 0 )
{
fprintf( stderr, "%s %d\n", __func__, __LINE__ );
exit( EXIT_FAILURE );
}
all_nodes[i].box = gtk_box_new( GTK_ORIENTATION_VERTICAL, 5 );
all_nodes[i].drawing_area = gtk_drawing_area_new();
gtk_box_append( (GtkBox*)all_nodes[i].box, all_nodes[i].drawing_area );
gtk_box_append( (GtkBox*)main_vbox, all_nodes[i].box );
gtk_widget_set_size_request( all_nodes[i].drawing_area, graph_width, graph_height );
all_nodes[i].surface = cairo_image_surface_create( CAIRO_FORMAT_ARGB32, graph_width, graph_height );
all_nodes[i].cr = cairo_create( all_nodes[i].surface );
gtk_drawing_area_set_draw_func( (GtkDrawingArea*)all_nodes[i].drawing_area, on_draw_event, &all_nodes[i], NULL );
}
prv_node = &all_nodes[0];
gtk_widget_set_visible( main_window, true );
for( int i=0; i<num_of_graphs; i++ )
{
gtk_widget_set_visible( all_nodes[i].box, false );
}
gtk_widget_set_visible( prv_node->box, true );
g_timeout_add_seconds( 5, draw_graphs, all_nodes );
}
int main( const int argc, char * argv[] )
{
GtkApplication * const app = gtk_application_new( "TrueTraffik.Gui", 0 );
if( g_signal_connect( app, "activate", G_CALLBACK( activate ), argv ) <= 0 )
{
fprintf( stderr, "%s %d\n", __func__, __LINE__ );
exit( EXIT_FAILURE );
}
const int status = g_application_run( G_APPLICATION( app ), 0, NULL );
g_object_unref( app );
return status;
}
result I am seeing after closing the window is
Graph 0 count: 3
Graph 1 count: 2
Graph 2 count: 1
Because of certain constraints, I can display only one graph at any given time.
May be because of this reason, on_draw_event
function is being executed only if visibility is true.
Would like to understand if there is a way to ensure the execution of on_draw_event
irrespective of visibility status.