I am trying to use Gtk 3.0 to visualize a network of nodes in real-time. The network of nodes will make new nodes and new connections will be formed between the nodes in real-time. I'm thinking of using one thread to configure Gtk and begin Gtk's main loop, and another for the development of the nodal network. The variables of the network will be global so that both the network developing thread and the Gtk thread can see the network variables. I will use a mutex on both sides to ensure synchronization.
My Gtk event-handler function will draw the current network, and idealistically, it should get called every time the network changes (eg new nodes, new connections). Therefore I would like to know if there is a solution in Gtk 3.0 where the event-handler function gets signaled every time a variable changes, say a change in vector's size, because I am using vector to store the nodes and connections.
I wrote a simple test program just to see if what I'm trying to do is possible. I have a thread which keeps incrementing an integer whereas another thread does all the Gtk configurations and initiates the main loop. In this code below, the Gtk thread draws the current value of the integer which keeps getting incremented. This code however is a modification of another and it does not draw the current value only at times when the value changes. Moreover, this code doesn't compile in Gtk 3.0. Is there any way to make this code compile in Gtk 3.0? In addition, is it possible to make it signal the drawing function only when the integer's value change?
#include <gtk/gtk.h>
#include <math.h>
#include <thread>
#include <mutex>
#include <string>
unsigned long long counter;
std::mutex mtx;
gboolean timeout(gpointer data) {
GtkWidget *widget = GTK_WIDGET(data);
if (!widget->window) return TRUE;
gtk_widget_queue_draw(widget);
}
gboolean expose(GtkWidget *widget, GdkEventExpose *event, gpointer data) {
cairo_t *cr = gdk_cairo_create(widget->window);
cairo_rectangle(cr, event->area.x, event->area.y, event->area.width, event- >area.height);
cairo_clip(cr);
cairo_set_source_rgb(cr, 0.1, 0.1, 0.1);
cairo_select_font_face(cr, "Purisa", CAIRO_FONT_SLANT_NORMAL, CAIRO_FONT_WEIGHT_BOLD);
std::string str;
mtx.lock();
str = std::to_string(counter);
cairo_move_to(cr, 20, 30);
cairo_show_text(cr, str.c_str());
mtx.unlock();
return FALSE;
}
void setupGtk() {
gtk_init(NULL,NULL);
GtkWidget *window = gtk_window_new(GTK_WINDOW_TOPLEVEL);
g_signal_connect(GTK_WINDOW(window), "destroy",G_CALLBACK(gtk_main_quit), NULL);
GtkWidget *drawing_area = gtk_drawing_area_new();
g_signal_connect(drawing_area,"expose_event",G_CALLBACK(expose),NULL);
gtk_container_add(GTK_CONTAINER(window), drawing_area);
gtk_widget_show(drawing_area);
g_timeout_add(10, timeout, window);
if (!GTK_WIDGET_VISIBLE (window))
gtk_widget_show_all(window);
else {
gtk_widget_destroy (window);
window = NULL;
}
gtk_main();
}
void count() {
while(counter<100000000) {
mtx.lock();
counter++;
mtx.unlock();
}
}
int main(int argc, char *argv[]) {
std::thread gtk(setupGtk);
std::thread process(count);
gtk.join();
process.join();
return 1;
}