我使用此代码进行裁剪选择:
gboolean mouse_press_callback(GtkWidget *event_box,
GdkEventButton *event,
gpointer data)
{
if (img1buffer == NULL)
return TRUE;
static gint press_x = 0, press_y = 0, rel_x = 0, rel_y = 0;
GtkAllocation ebox;
gint img1_x_offset = 0, img1_y_offset = 0;
gtk_widget_get_allocation(event_box, &ebox);
img1_x_offset = (ebox.width - width) / 2;
img1_y_offset = (ebox.height - height) / 2;
if (event->type == GDK_BUTTON_PRESS)
{
press_x = event->x - img1_x_offset;
press_y = event->y - img1_y_offset;
//g_print ("Event box clicked at coordinates %f,%f\n",
//event->x - img1_x_offset, event->y - img1_y_offset);
}
else if (event->type == GDK_BUTTON_RELEASE)
{
rel_x = event->x - img1_x_offset;
rel_y = event->y - img1_y_offset;
//g_print ("Event box released at coordinates %f,%f\n",
//event->x - img1_x_offset, event->y - img1_y_offset);
dest_x = rel_x < press_x ? rel_x : press_x;
dest_y = rel_y < press_y ? rel_y : press_y;
dest_width = abs(rel_x - press_x);
dest_height = abs(rel_y - press_y);
// mark user selection in image
GdkPixbuf *img1buffer_resized = gdk_pixbuf_scale_simple(img1buffer, width, height, GDK_INTERP_TILES);
gdk_pixbuf_composite(croppic, img1buffer_resized, dest_x, dest_y, dest_width, dest_height, 0, 0, 1, 1, GDK_INTERP_TILES, 170);
gtk_image_set_from_pixbuf(GTK_IMAGE(img1), img1buffer_resized);
}
return TRUE;
}
在主要功能中:
croppic = gdk_pixbuf_new_from_file("E:/Works for Gov Project/DOC/GUI/logogui1/crop_bg.png", NULL);
img1 = gtk_image_new();
event_box = gtk_event_box_new();
gtk_event_box_set_visible_window(GTK_EVENT_BOX(event_box), FALSE);
gtk_container_add(GTK_CONTAINER(event_box), img1);
gtk_container_add(GTK_CONTAINER(frame1), event_box);
g_signal_connect(G_OBJECT(event_box), "button_press_event", G_CALLBACK(mouse_press_callback), NULL);
g_signal_connect(G_OBJECT(event_box), "button-release-event", G_CALLBACK(mouse_press_callback), NULL);
和“crop_bg.png”是:
但我想要一个类似于绘画软件的选择形状:
您建议如何解决此任务的想法?或者我可以在互联网上的哪些资源上找到帮助?
答案 0 :(得分:1)
您正试图在GtkImage上绘图。这不是进行自定义绘图的最佳方式,正如您所注意到的,gdk_pixbuf_composite()
相当有限。
相反,您需要使用::draw
信号和cairo绘制the proper way。 cairo是GTK + 3用来绘制自己的小部件的矢量图形库,::draw
信号为你提供了一个绘制的cairo上下文:
gboolean draw(GtkWidget *widget, cairo_t *cr, void *data);
cairo本身很容易使用;它是well documented并且有a whole bunch of samples。你想要为你的目的做的是做一个虚线描边矩形。
此外,您不想使用GtkImage,而是使用GtkDrawingArea。 GtkDrawingArea专门设计用于绘制,并且可以通过一些额外的工作来处理您的活动。
最后一个难题是,当鼠标事件进入时你是如何开始绘画的?您未在cairo_t
或button-press-event
中获得button-release-event
,因此您无法在那里进行展示。实际上,GTK +已经过优化,只有在必要时才会绘制。为了表明有必要绘制,您可以使用gtk_widget_queue_draw()
方法。此方法有一些变体,仅标记要重绘的窗口小部件的子集(您可以使用cairo_clip_extents()
处理程序中的::draw
返回此子集。
请记住,小部件坐标是浮点数; cairo坐标也是如此。
让我们来证明一下。我将为此使用全局变量;你可能不想这样做。
gdouble x0, y0;
gdouble x1, y1;
这些将存储矩形的端点。当我们按下鼠标按钮时,我们想要开始绘图:
gboolean button_press_event(GtkWidget *widget, GdkEventButton *e, gpointer data)
{
// ...
x0 = e->x;
y0 = e->y;
x1 = e->x; // start with a zero-sized rectangle
y1 = e->y;
// ...
}
当我们移动鼠标时,我们想要将x1
和y1
更改为新的鼠标坐标,然后更新矩形。为了优化,我们只会更新已更改的区域:
gboolean motion_notify_event(GtkWidget *widget, GdkEventMotion *e, gpointer data)
{
// ...
// first queue both old and new rectangles for drawing
gtk_widget_queue_draw_area(widget,
x0, y0,
MAX(x1, e->x), MAX(y1, e->y));
// then set the new rectangle
x1 = e->x;
y1 = e->y;
// ...
}
您可以从上面找出button-release-event
上的内容。 draw
看起来像
gboolean draw(GtkWidget *widget, cairo_t *cr, gpointer data)
{
// ...
cairo_rectangle(cr, x0, y0, x1 - x0, y1 - y0);
// set up a dashed solid-color stroke
cairo_stroke(cr);
// ...
}
祝你好运!