我有一个问题。
我需要使用函数Xlib(XDrawLine等)在小部件类型GtkDrawingArea上绘制。
为什么?
我使用的是用Xlib绘制的库。我需要在渲染函数drawSome(...)中传递任何参数(Display,Window,GC)。一切都很好。我获取这些参数(通过gdk_x11 _...(),GdkDrawable,GdkGC)并使用获得的参数调用drawSome(...)。
但是有问题 - 绘画并不总是这样。最大化窗口,拖动,调整DrawingArea等大小时,不会显示图像。图像仅在顶部窗口的异常操作下显示。
然后我测试了XDrawPoint / Line / Rectangle函数 - 同样的问题。如果我们使用gdk_draw_rectangle(...) - 一切正常。
以下是以下代码:
...
GtkDrawingArea* area;
...
int main (int argc, char *argv[])
{
...
area=GTK_DRAWING_AREA(gtk_builder_get_object(builder,"area"));
gtk_widget_realize (GTK_WIDGET(area));
...
g_signal_connect (G_OBJECT(area), "expose_event", G_CALLBACK(expose_event_callback), NULL);
...
}
...
gboolean expose_event_callback (GtkWidget *widget, GdkEventExpose *event, gpointer data)
{
Display *dpy = gdk_x11_drawable_get_xdisplay(widget->window);
Window win =gdk_x11_drawable_get_xid(widget->window);
GC gc = DefaultGC(dpy, DefaultScreen(dpy));
//draw image on (0,0) in widget DrawingArea and a small black rectangle over image
drawSome(dpy, win, gc, ...);
XFillRectangle(dpy, win, gc, 0, 0, 10, 10);
return FALSE;
}
...
图像和仅在一种情况下显示的小黑色矩形:如果窗口移出桌面并返回桌面,则会显示图像。在其他情况下,它不会显示。 印象是另一个功能会删除DrawingArea。
谁能告诉我这是什么问题?
我将不胜感激!
而且......抱歉这么糟糕的英语!
答案 0 :(得分:1)
我想您需要做的就是添加XFlush(dpy);在XFillRectangle命令之后。我写了一个简短的例程,它似乎起作用。
#include <X11/Xlib.h> //-lX11
#include <gtk/gtk.h> //$$(pkg-config --cflags --libs gtk+-3.0)
#include <gdk/gdkx.h>
void DrawOnWidget(GtkWidget *widget)
{
GdkDisplay *gdk_dis = gdk_display_get_default();
Display *dis = gdk_x11_display_get_xdisplay (gdk_dis);
GC gc = DefaultGC(dis, DefaultScreen(dis));
GdkWindow *gdk_window = gtk_widget_get_window(widget);
Window win = gdk_x11_window_get_xid(gdk_window);
unsigned long valuemask = GCForeground;
XGCValues vColor;
vColor.foreground = 0x000000FF;
XChangeGC(dis, gc, valuemask, &vColor);
XFillRectangle(dis, win, gc, 0, 0, 100, 100);
XFlush(dis);
}
答案 1 :(得分:0)
您需要使用这些函数X Window System Interaction但要注意,但可能还有其他陷阱。我想你还需要使用gtk_widget_set_double_buffered
为你的GtkDrawingArea禁用双缓冲答案 2 :(得分:0)
这是我对该问题的第二个答案...我的第一个答案可能是针对原始问题的,因此我将其保留不变。虽然,当我第一次发现此线程时没有找到更通用的解决方案,因此,我还是决定发布一个更通用的解决方案。
简而言之,我创建了一个gtk图像小部件,该小部件可以独立显示或附加到其他小部件(如按钮)。然后,我将图像小部件发送到了绘图功能。在绘图功能中,查询所有xlib参数,以创建一个Pixmap作为xlib可绘制对象,在该位置绘制所有xlib绘图。然后创建GdkPixbuf,并将Pixmap像素复制到GdkPixbuf,然后将其设置为图像小部件...
有一些注释行可用于更改行为,解释将留给读者确定。
应该注意的是,使用xlib是可能的;开罗实施起来似乎不太麻烦。
#include <gtk/gtk.h> //$$(pkg-config --cflags --libs gtk+-3.0)
#include <gdk/gdkx.h>
#include <X11/Xlib.h> //-lX11
void DrawOnWidget(GtkWidget *widget, int width, int height)
{
GdkDisplay *gdk_dis = gdk_display_get_default();
Display *dis = gdk_x11_display_get_xdisplay (gdk_dis);
GC gc = DefaultGC(dis, DefaultScreen(dis));
GdkWindow *gdk_window = gtk_widget_get_window(widget);
Window win = gdk_x11_window_get_xid(gdk_window);
GdkPixbuf *pb = gdk_pixbuf_new(GDK_COLORSPACE_RGB, true, 8, width, height);
//GdkPixbuf *pb = gtk_image_get_pixbuf((GtkImage *) widget);
char *data = (char *) gdk_pixbuf_read_pixels((const GdkPixbuf *) pb); //RGB(A)
//int width = gdk_pixbuf_get_width(pb);
//int height = gdk_pixbuf_get_height(pb);
int pb_depth = gdk_pixbuf_get_n_channels(pb);
int depth = DefaultDepth(dis, DefaultScreen(dis)) / 8;
Pixmap pm = XCreatePixmap(dis, win, width, height, depth * 8);
unsigned long valuemask = GCForeground;
XGCValues vColor;
vColor.foreground = 0x00FF0000;
XChangeGC(dis, gc, valuemask, &vColor);
XFillRectangle(dis, pm, gc, 0, 0, width, height);
XFlush(dis);
XImage *ximage = XGetImage(dis, pm, 0, 0, width, height, AllPlanes, ZPixmap); //BGRX
for(int i=0, j=0; i<width*height*pb_depth; i+=pb_depth, j+=4)
{
data[i+0] = ximage->data[j+2];
data[i+1] = ximage->data[j+1];
data[i+2] = ximage->data[j+0];
if(pb_depth == 4) data[i+3] = 255;
}
gtk_image_set_from_pixbuf((GtkImage *) widget, pb);
XFreePixmap(dis, pm);
g_object_unref(pb);
return;
}
static void destroy( GtkWidget *widget, gpointer data )
{
gtk_main_quit();
}
static void test( GtkWidget *widget, gpointer data )
{
DrawOnWidget((GtkWidget *) data, 200, 200);
}
void GTK_Win()
{
GtkWidget *window, *grid;
GtkWidget *button_Exit, *button_Test;
window = gtk_window_new (GTK_WINDOW_TOPLEVEL);
g_signal_connect (window, "destroy", G_CALLBACK (destroy), NULL);
grid = gtk_grid_new ();
gtk_container_add (GTK_CONTAINER (window), grid);
button_Exit = gtk_button_new_with_label ("x");
g_signal_connect (button_Exit, "clicked", G_CALLBACK (destroy), NULL);
//GdkPixbuf *pixbuf = gdk_pixbuf_new(GDK_COLORSPACE_RGB, true, 8, 200, 200);
//GtkWidget *image = gtk_image_new_from_pixbuf(pixbuf);
GtkWidget *image = gtk_image_new();
button_Test = gtk_button_new_with_label ("Test");
g_signal_connect (button_Test, "clicked", G_CALLBACK (test), image);
//gtk_button_set_image((GtkButton *) button_Test, image);
gtk_grid_attach (GTK_GRID (grid), button_Exit, 0, 0, 1, 1);
gtk_grid_attach (GTK_GRID (grid), button_Test, 0, 1, 1, 1);
gtk_grid_attach (GTK_GRID (grid), image, 0, 2, 1, 1);
gtk_widget_show_all (window);
gtk_main();
}
int main(int argc, char** argv)
{
gtk_init (&argc, &argv);
GTK_Win();
return 0;
}