HOME | Links | About | Read

Gtk上的cairo(二)——画线小程序

https://houye.xyz/images/cairo-example2.png

#include <gtk/gtk.h>

struct {
        double x[2];
        double y[2];
} glob;

static cairo_surface_t *surface = NULL;

/*
 * 在surface上绘制一条直线
 */
static void 
do_drawing(GtkWidget *widget)
{
        cairo_t *cr;
        cr = cairo_create (surface);
        cairo_set_source_rgb (cr, 1, 0, 0);
        cairo_set_line_width (cr, 1);

        cairo_move_to (cr, glob.x[0], glob.y[0]);
        cairo_line_to (cr, glob.x[1], glob.y[1]);

        cairo_stroke (cr);
        cairo_destroy (cr);
        gtk_widget_queue_draw (widget);
}

/*
 * 清空surface
 */
static void
clear_surface (GtkWidget *widget)
{
        cairo_t *cr;

        cr = cairo_create (surface);

        cairo_set_source_rgb (cr, 1, 1, 1);
        cairo_paint (cr);
        cairo_destroy (cr);
        gtk_widget_queue_draw (widget);
}

/*
 * 鼠标左键按下时,记录坐标
 * 鼠标右键按下时,清空绘图区域。
 */
static gboolean 
button_press (GtkWidget *widget, 
                                                        GdkEventButton *event,
                                                        gpointer user_date)
{
        if (event->button == 1)
        {
                glob.x[0] = event->x;
                glob.y[0] = event->y;
                //g_print ("button = 1, x = %lf y = %lf\n", event->x, event->y);
        }
        if (event->button == 3)
                clear_surface(widget);
                //g_print ("button = 3, x = %lf   y = %lf\n", event->x, event->y);
        return TRUE;
}

/*
 * 鼠标左键松开时,记录下第二个坐标并绘制直线
 */
static gboolean
button_release (GtkWidget *widget,
                                GdkEventButton *event,
                                gpointer user_date)
{
        if (event->button == 1)
        {
                glob.x[1] = event->x;
                glob.y[1] = event->y;
                do_drawing(widget);
                //g_print ("in release button = 1, x = %lf      y = %lf\n", event->x, event->y);
        }
        return TRUE;
}

/*
 * 根据cr绘制surface
 */
static void
draw_event (GtkWidget *widget,
                        cairo_t *cr,
                        gpointer user_date)
{
        cairo_set_source_surface (cr, surface, 0, 0);
        cairo_paint (cr);
}


/*
 * 当widget大小改变时,重新创建一个适合大小的surface并清空新surface。
 */
static gboolean
configure_event (GtkWidget *widget,
                                GdkEventConfigure *event,
                                gpointer data)
{
        if (surface)
                cairo_surface_destroy (surface);
        surface = gdk_window_create_similar_surface (gtk_widget_get_window(widget), CAIRO_CONTENT_COLOR, gtk_widget_get_allocated_width(widget), gtk_widget_get_allocated_height (widget));

        clear_surface(widget);

        return TRUE;
}

int 
main (int argc, char *argv[])
{
        GtkWidget *window;
        GtkWidget *darea;

        gtk_init (&argc, &argv);

        window = gtk_window_new (GTK_WINDOW_TOPLEVEL);

        darea = gtk_drawing_area_new ();
        gtk_container_add (GTK_CONTAINER(window), darea);
        gtk_widget_set_size_request (darea, 400, 400);

        g_signal_connect (window, "destroy", G_CALLBACK (gtk_main_quit), NULL);

        /*鼠标按钮下压信号*/
        g_signal_connect (darea, "button-press-event", G_CALLBACK(button_press),NULL);
        /*鼠标按钮释放信号*/
        g_signal_connect (darea, "button-release-event", G_CALLBACK(button_release), NULL);
        /*重绘时发出信号*/
        g_signal_connect (darea, "draw", G_CALLBACK (draw_event), NULL);
        /*控件大小改变时发出信号,包括窗口创建时*/
        g_signal_connect (darea, "configure-event", G_CALLBACK (configure_event), NULL);

        gtk_widget_set_events (darea, GDK_BUTTON_PRESS_MASK|GDK_BUTTON_RELEASE_MASK);

        gtk_widget_show_all (window);

        gtk_main ();

        return 0;
}