我正在尝试使用Gtk 3.0实时显示节点网络。节点网络将实现新节点,并且将在节点之间实时形成新连接。我正在考虑使用一个线程来配置Gtk并开始Gtk的主循环,另一个用于开发节点网络。网络的变量将是全局的,因此网络开发线程和Gtk线程都可以看到网络变量。我将在两侧使用互斥锁以确保同步。
我的Gtk事件处理函数将绘制当前网络,理想情况下,它应该在每次网络更改时被调用(例如,新节点,新连接)。因此,我想知道在Gtk 3.0中是否存在一个解决方案,其中事件处理函数在每次变量发生变化时都会发出信号,比如矢量大小的变化,因为我使用vector来存储节点和连接
我写了一个简单的测试程序,看看我尝试做的事情是否可行。我有一个不断递增整数的线程,而另一个线程执行所有Gtk配置并启动主循环。在下面的代码中,Gtk线程绘制整数的当前值,该值继续递增。但是,此代码是对另一个代码的修改,并且仅在值更改时才会绘制当前值。而且,这段代码不能在Gtk 3.0中编译。有没有办法让这个代码在Gtk 3.0中编译?另外,是否可以仅在整数值改变时使其发出绘图函数?
#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;
}
答案 0 :(得分:0)
您需要创建自己的GObject类,并在值更改时向您发出的信号添加信号,或添加属性以表示变量并使用notify
信号。
请注意,信号发射不能保证正确穿过线程边界。您需要使用gdk_threads_idle_add()
来确保信号在主线程上发送。
如果你的目标只是重绘一个控件,你可以在空闲回调中调用gtk_widget_queue_draw()
或相关而不是发出信号。
请注意,空闲回调是异步运行的。如果希望在其他线程继续之前完成回调,则需要自己编写同步方法。
(对不起简短的回答;我很匆忙。)