GTK + Drawing_Area使用Expose事件重绘图像

时间:2014-03-21 03:47:51

标签: c events gtk redraw drawingarea

我在C中有一个基本上将图像读入char缓冲区的程序,在将图像显示回屏幕之前对其像素执行一些操作。

到目前为止,图像显示正常;但我遇到了以下两个问题:

  1. 当我最小化GTK窗口并再次将其重新启动时,图像就会消失,使Drawing_Area变空。
  2. 如何使用按钮推送重绘/更新Drawing_Area中的图像?
  3. 这是执行绘图的功能:

    void Draw_Img(GtkWidget *widget, unsigned char **buffer,int x_offset,int y_offset,int x1, int y1,int x2, int y2)
    {
      int i,j;
      int width,height;
    
      width=x2-x1+1;
      height=y2-y1+1;
    
      for(j=0;j<width*height;j++)
        tmp_buf[j]=0;
    
      for(j=y1;j<=y2;j++)
        for(i=x1;i<=x2;i++)
          tmp_buf[j*width+i-x1]=buffer[j][i];
    
      gdk_draw_gray_image(widget->window,
          widget->style->fg_gc[GTK_STATE_NORMAL], x_offset, y_offset,
         width, height, GDK_RGB_DITHER_NONE, tmp_buf, width);
    }
    

    主要功能:

    int main(int argc,char **argv)
    {
      gtk_init (&argc, &argv);    
      window = gtk_window_new(GTK_WINDOW_TOPLEVEL);
    
      gtk_window_set_title(GTK_WINDOW (window), "RESET DEMO");
      gtk_window_set_resizable(GTK_WINDOW(window), FALSE);
      g_signal_connect (G_OBJECT (window), "destroy",
          G_CALLBACK (gtk_main_quit), NULL);
    
      button = gtk_button_new_from_stock (GTK_STOCK_CLOSE);
      g_signal_connect_swapped (button, "clicked", G_CALLBACK (display), drawing_area);
    
      vbox = gtk_vbox_new (FALSE, 0);
      gtk_container_add (GTK_CONTAINER (window), vbox);
      gtk_widget_show (vbox);
    
      gtk_widget_set_size_request(drawing_area, Test_Size*3, Test_Size);
      gtk_box_pack_start (GTK_BOX (vbox), drawing_area, TRUE, TRUE, 0);
      gtk_widget_show(drawing_area);
    
      gtk_box_pack_start (GTK_BOX (vbox), button, TRUE, TRUE, 0);
      gtk_widget_set_can_default (button, TRUE);
      gtk_widget_grab_default (button);
      gtk_widget_show (button);
      gtk_widget_show(window);
    
      /*
        reads image into buffer before calling the "display" function in which 
        calls the Draw_Img function
      */
      myinit();
      g_signal_connect (G_OBJECT (drawing_area), "expose_event",
           G_CALLBACK (display), NULL);
    
      gtk_main();
    }
    

    提前感谢任何帮助/输入。

2 个答案:

答案 0 :(得分:0)

gtk_widget_queue_draw将重新排列要重绘的小部件。

最小化和取消最小化应该导致空白窗口,闻起来像你没有提供的代码中的错误。

答案 1 :(得分:0)

Show my work

我在这里找到了解决方案:http://blog.csdn.net/zhongguomin/article/details/7088575

调试两天后,我知道了。
注意:取消最小化会导致暴露事件。

在pixmap上绘制(pix,line,arc,rect,pixbuf),然后使用queue_draw(将发出expose_event),在expose_event中放置一个gdk_draw_drawable(pixmap)。

g_signal_connect (G_OBJECT (drawarea), "expose_event", G_CALLBACK (expose_event_callback), NULL);
gboolean expose_event_callback (GtkWidget * widget, GdkEventExpose * event, gpointer data)
{
  g_message ("expose_event");
  gdk_draw_drawable (widget->window, gc, pixmap, 0, 0, 0, 0, widget->allocation.width, widget->allocation.height);
  return TRUE;
}
......
gdk_draw_line (pixmap, gc, xa, ya, xb, yb);
gtk_widget_queue_draw (drawarea);
gdk_draw_rectangle (pixmap, gc, FALSE, x, y, w, h);
gtk_widget_queue_draw (drawarea);
gdk_draw_arc (pixmap, gc, FALSE, xb, ya, w, h, 0, 360 * 64);
gtk_widget_queue_draw (drawarea);
//image from file !!!
filename = gtk_file_chooser_get_filename (GTK_FILE_CHOOSER (FCD));
GdkPixbuf *pixbuf = gdk_pixbuf_new_from_file (filename, &error);
gdk_draw_pixbuf (pixmap, gc, pixbuf, 0, 0, 0, 0, -1, -1, GDK_RGB_DITHER_NORMAL, 0, 0);
gtk_widget_queue_draw (drawarea);

但我仍有问题,当我尝试调整drawarea的大小时,pixmap会崩溃。

然后我del if(pixmap)g_object_unref(pixmap); ,崩溃消失了,真是个大洞!

然后我制作一个新尺寸的新像素图,大小可以改变!

而allocate.width,allocation.height在queue_draw之前不生效,你不能使用 pixmap = gdk_pixmap_new(GDK_DRAWABLE(drawarea-&gt; window),widget-&gt; allocation.width,widget-&gt; allocation.height,-1); 现在!

int wpb = gdk_pixbuf_get_width (pixbuf);
int hpb = gdk_pixbuf_get_height (pixbuf);
g_message ("%d X %d", wpb, hpb);
gtk_widget_set_size_request(drawarea,wpb,hpb);    
pixmap = gdk_pixmap_new (GDK_DRAWABLE (drawarea->window),wpb,hpb, -1);
......