GTK+ Drawing_Area Изображение перерисовывается с Expose Event
У меня есть программа на C, которая в основном считывает изображение в буфер символов, выполняет некоторые манипуляции с его пикселями, прежде чем отобразить изображение обратно на экран.
Пока что изображение отображается нормально; но я столкнулся с двумя проблемами ниже:
- Когда я сворачиваю окно GTK и снова поднимаю его, изображение просто исчезает, оставляя Drawing_Area пустым.
- Как мне перерисовать / обновить изображение в Drawing_Area нажатием кнопки?
Вот функция, которая делает рисунок:
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 ответа
gtk_widget_queue_draw
потребует перерисовки виджета.
Минимизация и минимизация не должны приводить к появлению пустого окна, пахнет ошибкой в коде, который вы не предоставили.
Я нашел решение здесь: http://blog.csdn.net/zhongguomin/article/details/7088575
После отладки двух дней знаю дорогу.
Внимание: un-minim будет вызывать событие expose.
Нарисуйте (pix,line,arc,rect,pixbuf) на растровом изображении, а затем queue_draw (выдаст expose_event), поместите gdk_draw_drawable(pixmap) в expose_event.
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, растровое изображение вылетает.
Тогда я делаю if (pixmap) g_object_unref (pixmap);, авария исчезла, это действительно большая дыра!
Затем я делаю новое растровое изображение нового размера, размер может измениться!
И еще не применяют alloc.width, alloc.height до queue_draw, нельзя использовать pixmap = gdk_pixmap_new (GDK_DRAWABLE (drawarea->window), widget->alloc.width, widget->alloc.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);
......