这是我对这个问题的第二个答案......我的第一个答案可能解决了原始问题,所以我保持不变。虽然,当我第一次发现这个线程时我正在寻找的更通用的解决方案没有得到解决,但我决定也发布一个更通用的解决方案。
简而言之,我创建了一个 gtk 图像小部件,它可以独立显示或附加到其他小部件(如按钮)。然后我将图像小部件发送到绘图功能。在绘图函数中,所有的 xlib 参数都被查询,以便创建一个像素图作为 xlib 可绘制对象,这是所有 xlib 绘图的呈现位置。然后创建 GdkPixbuf,并将 Pixmap 像素复制到 GdkPixbuf,然后将其设置为图像小部件......
有一些注释行可用于更改行为,解释将留给读者确定。
应该注意的是,虽然使用 xlib 是可能的;cairo 似乎实施起来不那么繁琐。
#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;
}