В связи со скудностью документации по библиотеке GtkExtra, мною был составлен довольно подробно комментированный простенький пример, по которому можно понять принципы построения графиков с помощью GtkExtra, его и выкладываю в блоге.
Пример во многом аналогичен примеру testiterator из стандартной поставки GtkExtra и выглядит так:

Собственно текст примера:
// Пример дынных для отрисовки -->
    // Количество точек = 12
    int nt = 12;

    // Структура для пар координат "время - значение"
    struct pair
    {
        double x;   // По X - Время
        double y;   // По Y - Значение
    };

    // Область памяти с парами координат "время - значение"
    struct pair mem[12] =
    {
        {   0,      0.2},   // 1
        {   1.5,    0},
        {   2.4,    1},
        {   3.7,    0},
        {   4.44,   0.55},  // 5
        {   6.3,    0.73},
        {   7,      0.21},
        {   8.9,    0.1},
        {   11,     0.2},
        {   14.6,   0.2},   // 10
        {   17,     0.2},
        {   20,     1}      // 12
    };
// Пример дынных для отрисовки <--


// Стандартные для GTK вещи -->
    #include <math.h>
    #include <stdio.h>
    #include <stdlib.h>
    #include <gtk/gtk.h>
    #include <gdk/gdk.h>

    void quit ()
    {
      gtk_main_quit();
    }
// Стандартные для GTK вещи <--


#include <gtkplotcanvas.h> 
#include <gtkplotcanvastext.h> 
#include <gtkplotcanvasplot.h> 
#include <gtkplotdata.h> 


// Массив текста для подписей к точкам
static gchar point_label[100];

// Функция, запускаемая для получения точек
// (функция запускается по разу для каждой точки)
static void graph_iter
    (
    GtkPlot *plot,
    GtkPlotData *data,
    gint iter,
    gdouble *x,
    gdouble *y,
    gdouble *z,
    gdouble *a,
    gdouble *dx,
    gdouble *dy,
    gdouble *dz,
    gdouble *da,
    gchar **label,
    gboolean *error
    )
{
    // Достаем из объекта data указатель на область памяти с координатами точек
    double *memory = (double *) g_object_get_data(G_OBJECT(data), "Dots_memory_pointer");

    // Распаковываем координаты из памяти
    *x = *(
                memory          // Начало области памяти
                + 0             // X - первый в парах, так что без смещения
                + 2 * iter);    // Смещение к нужной паре
    *y = *(
                memory          // Начало области памяти
                + 1             // Y - второй в парах, смещение к нему
                + 2 * iter);    // Смещение к нужной паре

    // Подписи к точкам
    sprintf(point_label, "Точка #%d\n", iter + 1);
    *label = point_label;

    *error = FALSE;
}


void graph_open
    (
        GtkWidget *container,   // Контейнер, в котором рисовать график
        int dots_number,        // Количесвто точек
        void *memory            // Область памяти, содержащее координаты этих точек
    )
{
    // Создаем холст canvas 900x700 пикселей в окне -->
        GtkWidget *canvas;      // Виджет
        canvas = gtk_plot_canvas_new(   // Создаем
            900, 700,                   // Размер
            1.);                        // В натуральную величину (например для уменьшения в два раза следует поставить 0.5)
        gtk_container_add(GTK_CONTAINER(container), canvas);    // Помещаем в контейнер
    // Создаем холст canvas 900x700 пикселей в окне <--


    // Создадим подпись вверху холста -->
        GtkWidget *top_label;
        
        top_label = (GtkWidget *) gtk_plot_canvas_text_new(
                "Times-BoldItalic",             // Шрифт (можно выставить NULL для шрифта по умолчанию)
                                                    // Доступные шрифты можно посмотреть в файле gtkplotps.c
                20,                             // Высота шрифта
                0,                              // Угол наклона надписи
                NULL,                           // Цвет шрифта
                NULL,                           // Цвет фона надписи
                TRUE,                           // Прозрачность
                GTK_JUSTIFY_CENTER,             // Выравнивание
                "My first plot (первый плот).");// Собственно текст

        gtk_plot_canvas_put_child(          // Помещаем на холст
                GTK_PLOT_CANVAS(canvas),            // Холст
                (GtkPlotCanvasChild *) top_label,   // Что помещать (child)
                            // Координаты:
                .50,                                // x1 - отступ по горизонтали, в процентах от холста (зд. 50%, т.е. посередине)
                .05,                                // y1 - отступ по вертикалии, в процентах от холста (зд. 5%, т.е. почти наверху)
                0.,                                 // x2
                0.);                                // y2
    // Создадим подпись вверху холста <--


    // Устанавливаем цвет холста -->
        GdkColor color;
        gdk_color_parse("light blue", &color);
        gdk_color_alloc(gtk_widget_get_colormap(canvas), &color);
        gtk_plot_canvas_set_background(GTK_PLOT_CANVAS(canvas), &color);
    // Устанавливаем цвет холста <--


    // Создаем график plot (точнее основу графика - оси, подписи и т.п., без значений) -->
        GtkWidget *plot;    

        plot = gtk_plot_new_with_size(
            NULL,       // GdkDrawable виджет
            .65, .45);  // Высота и ширина виджета графика

        // Цвет графика -->
            gdk_color_parse("light yellow", &color);
            gdk_color_alloc(gtk_widget_get_colormap(plot), &color);
            gtk_plot_set_background(GTK_PLOT(plot), &color);
        // Цвет графика <--
        
        gtk_plot_set_range(     // По умолчанию график 1x1 деление,...
            GTK_PLOT(plot),     // ...выставим другие значения:
            0., 20.,            // По X - 20 делений
            0., 1.);            // По Y - 1 деление

        // Выставим с каким шагом проставлять метки координат на графике
        gtk_plot_set_ticks(GTK_PLOT(plot),
            GTK_PLOT_AXIS_X,    // По оси X
            2,                  // Цифры проставлять с шагом 2
            1);                 // Ставить засечки с шагом 1
        gtk_plot_set_ticks(GTK_PLOT(plot), GTK_PLOT_AXIS_Y, .1, 1);

        gtk_plot_grids_set_visible(GTK_PLOT(plot), // Координатная сетка
            TRUE,       // Вертикальная сетка сплошной линией относительно проставленных на оси цифр
            TRUE,       // Вертикальная сетка штриховой линией относительно проставленных на оси меток
            TRUE,       // Горизонтальная сетка сплошной линией относительно проставленных на оси цифр
            TRUE);      // Горизонтальная сетка штриховой линией относительно проставленных на оси меток

        gtk_widget_show(plot);  // Нужно вызвать функцию отрисовки графика заранее,
                                // иначе потом не удасться добавить к графику данные
    // Создаем график plot (точнее основу графика - оси, подписи и т.п., без значений) <--


    // Подписи к графику -->
        // Верхнюю и правую просто скроем:
        gtk_plot_axis_hide_title(gtk_plot_get_axis(GTK_PLOT(plot), GTK_PLOT_AXIS_TOP));
        gtk_plot_axis_hide_title(gtk_plot_get_axis(GTK_PLOT(plot), GTK_PLOT_AXIS_RIGHT));

        // Остальные пропишем:
        gtk_plot_axis_set_title(gtk_plot_get_axis(GTK_PLOT(plot), GTK_PLOT_AXIS_LEFT), "Значение");
        gtk_plot_axis_set_title(gtk_plot_get_axis(GTK_PLOT(plot), GTK_PLOT_AXIS_BOTTOM), "Время");
    // Подписи к графику <--


    // Создаем child с только что созданным графиком plot и рисуем его на холсте (put_child) -->
        GtkPlotCanvasChild *child;

        child = (GtkPlotCanvasChild *) gtk_plot_canvas_plot_new(GTK_PLOT(plot)); // Создание структуры child

        gtk_plot_canvas_put_child(          // Помещаем на холст
                GTK_PLOT_CANVAS(canvas),    // Холст
                child,                      // Что помещать (child)
                            // Координаты:
                .15,                            // x1 - отступ по горизонтали, в процентах от холста
                .25,                            // y1 - отступ по вертикалии, в процентах от холста
                .80,                            // x2 - ширина графика
                .85);                           // y2 - высота графика
    // Создаем child с только что созданным графиком plot и рисуем его на холсте (put_child) <--


    // Строим на графике значения (пока просто линии между точками) -->
        GtkPlotData *dataset;

        dataset = (GtkPlotData *) gtk_plot_data_new_iterator(   // Заполняем структуру данных (значения и параметры)
            (GtkPlotIterator)graph_iter,                                    // Функция, запускаемая для получения (распаковки) точек
            dots_number,                                                    // Количество точек
            GTK_PLOT_DATA_X|GTK_PLOT_DATA_Y|GTK_PLOT_DATA_LABELS);          // Маска параметров
        
        // Здесь мы сохраним указатель на адрес области памяти с данными о точках...
        // ...в объекте dataset (см. GObject Reference Manual)
        g_object_set_data(G_OBJECT(dataset), "Dots_memory_pointer", memory);

        gtk_plot_data_show_labels(dataset, TRUE);   // Отображать подписи к точкам
        gdk_color_parse("dark green", &color);
        gdk_color_alloc(gtk_widget_get_colormap(plot), &color);
        gtk_plot_data_labels_set_attributes(dataset,
                "Helvetica-Bold",                   // Шрифт (можно выставить NULL для шрифта по умолчанию)
                14,                                 // Высота шрифта
                90,                                 // Угол наклона подписи
                &color,                             // Цвет шрифта
                NULL);                              // Цвет фона подписи

        gtk_plot_add_data(GTK_PLOT(plot), dataset); // Добавляем значения на график...
        gtk_widget_show(GTK_WIDGET(dataset));       // ...и отображаем их
    // Строим на графике значения (пока просто линии между точками) <--


    // Легенда графика
    gtk_plot_data_set_legend(dataset, "Легенда");


    // Настроим вид точек <--
        gdk_color_parse("green", &color);   // Цвет - зеленый
        gdk_color_alloc(gdk_colormap_get_system(), &color);

        gtk_plot_data_set_symbol(dataset,
             GTK_PLOT_SYMBOL_DIAMOND,       // Символ - ромб
             GTK_PLOT_SYMBOL_OPAQUE,        // Стиль - непрозрачный
             20, 2,                         // Размеры
             &color, &color                 // Цвета
             );
    // Настроим вид точек -->


    // Настроим вид линий -->
        gdk_color_parse("red", &color);     // Цвет - красный
        gdk_color_alloc(gdk_colormap_get_system(), &color);
        gtk_plot_data_set_line_attributes(dataset,
            GTK_PLOT_LINE_SOLID,            // GtkPlotLineStyle
            0,                              // GdkCapStyle (как рисовать концы линий, см. GDK Reference Manual)
            0,                              // GdkJoinStyle (как объединяются сегменты линий, см. GDK Reference Manual)
            3,                              // Ширина линии
            &color);                        // Цвет
    // Настроим вид линий <--
}


int main(int argc, char *argv[])
{
    // Стандартные для GTK вещи -->
        // Здесь создаем окно и сопутствующие виджеты
        GtkWidget *window;
        gtk_init(&argc,&argv);
        window = gtk_window_new(GTK_WINDOW_TOPLEVEL);
        gtk_signal_connect (GTK_OBJECT (window), "destroy",
            GTK_SIGNAL_FUNC(quit), NULL);
        gtk_window_set_position(GTK_WINDOW(window), GTK_WIN_POS_CENTER);

        GtkWidget *main_vbox;
        main_vbox = gtk_vbox_new(FALSE, 5);
        gtk_container_add(GTK_CONTAINER(window), main_vbox);
        gtk_widget_show(main_vbox);
        
        // Frame, в который будем класть виджет с графиком
        GtkWidget *main_frame;
        main_frame = gtk_frame_new("График");
        gtk_box_pack_start(GTK_BOX(main_vbox), main_frame, TRUE, TRUE, 0);

        GtkWidget *main_hbox;
        main_hbox = gtk_hbox_new(FALSE, 0);
        gtk_box_pack_end(GTK_BOX(main_vbox), main_hbox, FALSE, FALSE, 0);

        GtkWidget *close_button;
        close_button = gtk_button_new_from_stock(GTK_STOCK_CLOSE); 
        g_signal_connect(GTK_OBJECT(close_button), "clicked", G_CALLBACK(quit), NULL);
        gtk_box_pack_end(GTK_BOX(main_hbox), close_button, FALSE, FALSE, 0);
    // Стандартные для GTK вещи <--

            // Здесь предположим у нас есть область памяти со значениями координат mem
            // и количество точек nt.
            // Эти данные и передаем в нашу функцию.
            graph_open(main_frame, nt, mem);

    // Стандартные для GTK вещи -->
        gtk_widget_show_all(GTK_WIDGET(window));
        gtk_main();
        return 0;
    // Стандартные для GTK вещи <--
}


//
// Gtk Extra Example
// http://damnsmallblog.blogspot.com
//

В примере довольно универсальной функции graph_open передаются три параметра:
1) Контейнер GTK, в котором и будет отрисовн график.
2) Количество точек для отрисовки.
3) Адрес области памяти, в которой лежат значения (double) координат точек.

Вспомогательная функция graph_iter служит для распаковки точек.
main - простенькое gtk-приложение, содержащее виджет main_frame в качестве контейнера для графика.

0 коммент.:


 

Copyright © 2007 DamnSmallBlog. Content is licensed under Creative Commons Attribution-Noncommercial.

Design: GeckoandFly and Blogcrowds.