В связи со скудностью документации по библиотеке GtkExtra, мною был составлен довольно подробно комментированный простенький пример, по которому можно понять принципы построения графиков с помощью GtkExtra, его и выкладываю в блоге.
Пример во многом аналогичен примеру testiterator из стандартной поставки GtkExtra и выглядит так:
Собственно текст примера:
В примере довольно универсальной функции graph_open передаются три параметра:
1) Контейнер GTK, в котором и будет отрисовн график.
2) Количество точек для отрисовки.
3) Адрес области памяти, в которой лежат значения (double) координат точек.
Вспомогательная функция graph_iter служит для распаковки точек.
main - простенькое gtk-приложение, содержащее виджет main_frame в качестве контейнера для графика.
Пример во многом аналогичен примеру 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 коммент.:
Подписаться на:
Комментарии к сообщению (Atom)