【问题标题】:Gtk+ 3.0 Signal that trigger upon change in variableGtk+ 3.0 变量变化时触发的信号
【发布时间】:2014-12-18 20:25:41
【问题描述】:

我正在尝试使用 Gtk 3.0 实时可视化节点网络。节点网络将产生新节点,并且节点之间将实时形成新的连接。我正在考虑使用一个线程来配置 Gtk 并开始 Gtk 的主循环,另一个用于节点网络的开发。网络的变量将是全局的,因此网络开发线程和 Gtk 线程都可以看到网络变量。我会在两边使用互斥锁来确保同步。

我的 Gtk 事件处理函数将绘制当前网络,理想情况下,它应该在每次网络变化(例如新节点、新​​连接)时被调用。因此,我想知道 Gtk 3.0 中是否有解决方案,每次变量更改时都会发出事件处理函数的信号,比如向量大小的变化,因为我使用向量来存储节点和连接。

我编写了一个简单的测试程序,只是为了看看我想要做的事情是否可行。我有一个线程不断增加一个整数,而另一个线程执行所有 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;
}

【问题讨论】:

    标签: c++ gtk


    【解决方案1】:

    您将需要创建自己的 GObject 类,并在值更改时向该类添加一个您可以发出的信号,或者添加一个属性来表示变量并使用notify 信号。

    请注意,信号发射不能保证正确地跨越线程边界。您将需要使用gdk_threads_idle_add() 来确保在主线程上发送信号。 如果您的目标只是重绘一个控件,您可以在空闲回调中调用gtk_widget_queue_draw() 或相关而不是发出信号。

    请注意,空闲回调异步运行。如果您希望在其他线程继续之前完成回调,则需要自己编写同步方法。

    (对不起,我的回答很简洁;我很着急。)

    【讨论】:

    • 您好,感谢您的回复。我阅读了回复,但从我的角度来看有点难以理解,但我想我想使用那个“通知”信号,因为它似乎更接近我想要的,因为它会响应变化变量而不是周期性的不受控制的响应。我查阅了 Gtk+ 3 参考资料,但找不到有关通知信号的文档,请问您能告诉我在哪里可以找到有关您提到的第一个想法的更多参考资料吗?
    • 关于线程通信,这是假设整数递增线程在整数变化时具有Gtk组件信号吗?因为我以前没有这个。
    • notify 是一个 GObject 功能。您将需要编写自己的 GObject。如果您刚刚开始,您可能应该改用空闲回调方法;这会节省很多时间。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2011-10-30
    • 1970-01-01
    • 2012-11-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多