LinuxSir.cn,穿越时空的Linuxsir!

 找回密码
 注册
搜索
热搜: shell linux mysql
12
返回列表 发新帖
楼主: snowwood

线程无法刷新界面,请帮帮我

[复制链接]
 楼主| 发表于 2009-11-14 11:18:24 | 显示全部楼层
Post by realtang;2045400
下面是我改的,在windows xp sp3 mingw下测试通过。

  1. #include <gtk/gtk.h>

  2. static int t = 0;

  3. static gboolean on_threads_request( void * lpData)
  4. {
  5.         gtk_widget_queue_draw( GTK_WIDGET(lpData));
  6.         return FALSE;
  7. }

  8. static gboolean on_expose_event (GtkWidget * widget, GdkEventExpose * event, gpointer data)
  9. {
  10.         //printf("%d", t);

  11.         cairo_t *cr;
  12.         cr = gdk_cairo_create (widget->window);

  13.         char sztext[64] = {0};
  14.         sprintf(sztext, "%d", t);

  15.         cairo_move_to (cr, 10.0, 34.0);
  16.         cairo_show_text( cr, sztext);

  17.         cairo_destroy (cr);

  18.         return FALSE;
  19. }

  20. void * ThreadFunc(void * lpData)
  21. {
  22.         while (1)
  23.         {
  24.                 g_usleep(500000);
  25.                 t++;
  26.                 g_print(" %d\n", t);
  27.                 gdk_threads_enter();
  28.                 gdk_threads_add_idle( on_threads_request, lpData);
  29.                 gdk_threads_leave();
  30.         }
  31.         return NULL;
  32. }

  33. int main (int argc, char * argv[])
  34. {
  35.         if (!g_thread_supported())
  36.                 g_thread_init(NULL);
  37.         gtk_init (&argc, &argv);

  38.         GtkWidget *window = gtk_window_new (GTK_WINDOW_TOPLEVEL);

  39.         g_signal_connect(window, "expose-event", G_CALLBACK(on_expose_event), NULL);
  40.         g_signal_connect(window, "destroy", G_CALLBACK(gtk_main_quit), NULL);
  41.         gtk_widget_set_app_paintable(window, TRUE);

  42.         gtk_widget_show(window);

  43.         g_thread_create(ThreadFunc, window, FALSE, NULL);
  44.        
  45.         gdk_threads_enter();
  46.         gtk_main();
  47.         gdk_threads_leave();
  48.        
  49.         return 0;
  50. }

复制代码


这个方法非常好,解决了我的问题

使用了这个方法后又出现了一个新的问题:工作线程每次更新完数据后,告诉主线程去刷新界面,而界面刷新并不是马上刷新的,需要在消息队列中排队。但是工线程是不停地更新数据的,所以会造成这样的现象,就是工作线程为第一屏更新完数据后,界面还没来得刷显示第一屏,工作线程就把数据更新成了第二屏的数据,结果当界面刷新时,显示的是第二屏的数据,第一屏数据就无法显示了。

请问realtang这个问题又廖如何解决?
回复 支持 反对

使用道具 举报

发表于 2009-11-14 12:57:53 | 显示全部楼层
先试试用gdk_window_invalidate_rect取代gtk_widget_queue_draw()。
基本上实时刷新很难,窗口系统对界面的显示一般都是异步的,即使是DX或者OPENGL之类的技术也是在垂直同步发生的时候对界面进行刷新。如果你一定要更快的刷新界面,可以考虑采用gtkglext。
回复 支持 反对

使用道具 举报

发表于 2009-11-29 17:42:52 | 显示全部楼层
Post by realtang;2045734
先试试用gdk_window_invalidate_rect取代gtk_widget_queue_draw()。
基本上实时刷新很难,窗口系统对界面的显示一般都是异步的,即使是DX或者OPENGL之类的技术也是在垂直同步发生的时候对界面进行刷新。如果你一定要更快的刷新界面,可以考虑采用gtkglext。

如果cpu的开销没有达到100%的时候为什么做不到的呢?
我觉得可以提高绘图线程的优先级让其优先执行,一旦任务完成就pthread_cond_wait住,所以只要楼主所说的“工作线程”速度够快,绘图线程就应该能够即时响应!
回复 支持 反对

使用道具 举报

您需要登录后才可以回帖 登录 | 注册

本版积分规则

快速回复 返回顶部 返回列表