这方面的资料确实比较少,通过自己摸索,实现了在GTK+ 2.0下进行图片显示,然后在图片上可以自己绘图的一个程序。啥也不说了,发上源码,以供大家参考。希望对学习GTK+的人有点帮助。
#include <gtk/gtk.h>
#include <stdlib.h>
#include <gdk-pixbuf/gdk-pixbuf.h>
#define DA_WIDTH 300
#define DA_HEIGHT 300
#define SCALE_FACTOR 1.2
#define PEN_MOVE 0
#define PEN_UP 1
#define PEN_DOWN 2
GdkPixmap *pixmap = NULL;
GtkWidget *window, *vbox, *tool_bar, *drawing_area;
gboolean status;
gboolean fdiscard = TRUE;
gint prev_x, prev_y;
GdkGC *my_gc_red;
GdkColor color;
struct ImageData {
GtkWidget *drawing_area;
int width, height;
GdkPixbuf *pixbuf;
float scale;
};
struct ImageData data;
static void expose_cb(GtkWidget *da, GdkEventExpose *event, struct ImageData *data)
{
gdk_pixbuf_render_to_drawable_alpha(data->pixbuf, da->window, 0, 0,
0, 0, data->width, data->height,
GDK_PIXBUF_ALPHA_FULL, 0,
GDK_RGB_DITHER_NONE, 0, 0);
}
static void zoom(struct ImageData *data, float scale)
{
GdkPixbuf *pixbuf;
int width = data->width * scale;
int height = data->height * scale;
pixbuf = gdk_pixbuf_scale_simple(data->pixbuf, width, height,
GDK_INTERP_BILINEAR);
if (pixbuf) {
gdk_pixbuf_unref(data->pixbuf);
data->pixbuf = pixbuf;
data->width = width;
data->height = height;
}
gdk_window_clear(data->drawing_area->window);
expose_cb(data->drawing_area, NULL, data);
}
static void zoom_in_cb(GtkWidget *widget, struct ImageData *data)
{
zoom(data, SCALE_FACTOR);
}
static void zoom_out_cb(GtkWidget *widget, struct ImageData *data)
{
zoom(data, 1.0 / SCALE_FACTOR);
}
static void clear(GtkWidget *widget)
{
int width, height;
gtk_window_get_size(window, &width, &height);
printf("width=%d, height=%d/n",width,height);
gdk_draw_rectangle(pixmap ,
drawing_area->style->white_gc ,
TRUE , 0 , 0 ,
width,height);
//drawing_area->allocation.width ,
//drawing_area->allocation.height);
gtk_widget_queue_draw(drawing_area);
}
static gboolean configure_event( GtkWidget *widget,
GdkEventConfigure *event )
{
if (pixmap)
g_object_unref (pixmap);
pixmap = gdk_pixmap_new (widget->window,
widget->allocation.width,
widget->allocation.height,
-1);
gdk_draw_rectangle (pixmap,
widget->style->white_gc,
TRUE,
0, 0,
//1,1);
widget->allocation.width,
widget->allocation.height);
my_gc_red = gdk_gc_new(widget->window);
color.red = 0;
color.green = 0;
color.blue = 0;
gdk_gc_set_rgb_fg_color(my_gc_red , &color);
gint line_width =2;
GdkLineStyle line_style= GDK_LINE_SOLID;
GdkCapStyle cap_style=GDK_CAP_NOT_LAST;
GdkJoinStyle join_style=GDK_JOIN_MITER;
gdk_gc_set_line_attributes (my_gc_red,line_width, line_style, cap_style,join_style);
return TRUE;
}
static void draw_line(GtkWidget *widget, gint prev_x, gint prev_y, gint x, gint y) //Miao
{
GdkRectangle update_rect;
if(prev_x < x) update_rect.x = prev_x; else update_rect.x = x;
if(prev_y < y) update_rect.y = prev_y; else update_rect.y = y;
if(prev_x < x) update_rect.width = x-prev_x; else update_rect.width = prev_x-x;
if(prev_y < y) update_rect.height = y-prev_y; else update_rect.height = prev_y-y;
if(update_rect.width == 0 && update_rect.height == 0)
return;
gdk_draw_line(/*pixmap*/drawing_area->window, my_gc_red, prev_x, prev_y, x, y);
// gtk_widget_queue_draw_area(widget ,
// update_rect.x-5 , update_rect.y-5 , update_rect.width+10, update_rect.height+10);
}
static gboolean button_press_event( GtkWidget *widget,
GdkEventButton *event )
{
status = PEN_DOWN;
prev_x =event->x;
prev_y =event->y;
return TRUE;
}
static gboolean button_release_event(GtkWidget *widget,
GdkEventButton *event)
{
status = PEN_UP;
// printf("Up: x=%d, y=%d/n",(gint)prev_x,(gint)prev_y);
return TRUE;
}
static gboolean motion_notify_event( GtkWidget *widget,
GdkEventMotion *event )
{
int x, y;
GdkModifierType state;
if (event->is_hint)
{
gdk_window_get_pointer (event->window, &x, &y, &state);
}
else
{
x = event->x;
y = event->y;
state = event->state;
}
fdiscard = (fdiscard == FALSE ? TRUE: FALSE);
if(status == PEN_DOWN && pixmap != NULL)
{
if(fdiscard == TRUE)
{
draw_line(widget,prev_x, prev_y,x,y);
prev_x = x;
prev_y = y;
}
}
return TRUE;
}
int main(int argc, char *argv[])
{
// GtkWidget *window, *vbox, *tool_bar, *drawing_area;
GdkPixbuf *pixbuf;
// struct ImageData data;
#ifdef DEBUG
int wid, heig;
#endif
/*
if (argc != 2) {
printf("Usage: %s image_file/n", argv[0]);
exit(1);
}
*/
gtk_init (&argc, &argv);
/* Create top level window */
window = gtk_window_new(GTK_WINDOW_TOPLEVEL);
gtk_window_set_title(GTK_WINDOW(window), "Laser Gesture Operation");
gtk_widget_set_size_request(GTK_WINDOW(window), 800, 800);
gtk_signal_connect(GTK_OBJECT(window), "destroy",
GTK_SIGNAL_FUNC(gtk_main_quit), NULL);
#ifdef DEBUG
gtk_window_get_size(GTK_WINDOW(window), &wid, &heig);
printf("Top level window size: x=%d, y=%d/n",wid,heig);
#endif
/* Create an image if any */
pixbuf = gdk_pixbuf_new_from_file(/*argv[1]*/"1.jpg",NULL);
if (pixbuf == NULL) {
printf("Error: can't load picture file /"%s/"/n", argv[1]);
exit(2);
}
data.pixbuf = pixbuf;
data.width = gdk_pixbuf_get_width(pixbuf);
data.height = gdk_pixbuf_get_height(pixbuf);
data.scale = 1.0;
/* Create box container */
vbox = gtk_vbox_new(FALSE, 0);
gtk_container_add(GTK_CONTAINER(window), vbox);
/* Create tool bar */
// tool_bar = gtk_toolbar_new(GTK_ORIENTATION_HORIZONTAL, GTK_TOOLBAR_BOTH);
tool_bar = gtk_toolbar_new();
gtk_toolbar_set_style (GTK_TOOLBAR(tool_bar), GTK_TOOLBAR_TEXT);
// gtk_toolbar_set_space_style (GTK_TOOLBAR(tool_bar), GTK_TOOLBAR_SPACE_LINE);
gtk_box_pack_start(GTK_BOX(vbox), tool_bar, FALSE, FALSE, 2);
/* Create zoom tools */
gtk_toolbar_append_item(GTK_TOOLBAR(tool_bar), "+", "Zoom in",
NULL, NULL, /* icon */
GTK_SIGNAL_FUNC(zoom_in_cb), &data);
gtk_toolbar_append_item(GTK_TOOLBAR(tool_bar), "-", "Zoom out",
NULL, NULL, /* icon */
GTK_SIGNAL_FUNC(zoom_out_cb), &data);
gtk_toolbar_append_item(GTK_TOOLBAR(tool_bar), "Clear", "Clear",
NULL, NULL, /* icon */
GTK_SIGNAL_FUNC(clear), NULL);
gtk_toolbar_append_item(GTK_TOOLBAR(tool_bar), "Quit", NULL,
NULL, NULL, /* icon */
GTK_SIGNAL_FUNC(gtk_main_quit), NULL);
/* Create a drawing area. */
drawing_area = gtk_drawing_area_new();
#ifdef DEBUG
gtk_widget_set_size_request(GTK_WIDGET(drawing_area), wid, heig);
#else
gtk_wdiget_set_size_request(GTK_WIDGET(drawing_area), DA_WIDTH, DA_HEIGHT);
#endif
gtk_box_pack_start (GTK_BOX(vbox), drawing_area, TRUE, TRUE, 2);
gtk_widget_set_events (drawing_area, GDK_EXPOSURE_MASK
| GDK_LEAVE_NOTIFY_MASK
| GDK_BUTTON_PRESS_MASK
| GDK_POINTER_MOTION_MASK
| GDK_BUTTON_RELEASE_MASK
| GDK_POINTER_MOTION_HINT_MASK);
gtk_signal_connect(GTK_OBJECT(drawing_area), "expose_event",
GTK_SIGNAL_FUNC(expose_cb), &data);
gtk_signal_connect(GTK_OBJECT(drawing_area), "configure_event",
G_CALLBACK(configure_event),NULL);
g_signal_connect (G_OBJECT(drawing_area), "motion_notify_event",
G_CALLBACK (motion_notify_event), NULL);
g_signal_connect (G_OBJECT(drawing_area), "button_press_event",
G_CALLBACK (button_press_event), drawing_area);
g_signal_connect (G_OBJECT(drawing_area), "button_release_event",
G_CALLBACK (button_release_event), drawing_area);
data.drawing_area = drawing_area;
/* Show and go */
// gtk_widget_show(drawing_area);
// gtk_widget_show(tool_bar);
// gtk_widget_show(vbox);
gtk_widget_show_all (window);
gtk_main();
return(0);
}