Как очистить поверхность gtk, goocanvas?

Я использую goocanvas для рисования простой диаграммы в кадре GTK, и размеры диаграммы основаны на значениях в том же окне. Диаграмма должна изменять свои размеры в режиме реального времени, когда пользователь изменяет значения в интерфейсе с помощью кнопок-спиннеров.

Мне удалось отобразить исходную диаграмму поверх gtk window->hbox->frame.

Проблема заключается в изменении значений. Он перерисовывается поверх рисунка.

Итак, есть ли какая-либо «чистая» функциональность для холста goo?

Или есть другой способ добиться желаемого результата?

Редактировать:

Текущий код:

/*
 * Compile me with:
 * gcc -o dia dia.c `pkg-config --libs --cflags gtk+-2.0 goocanvas` -rdynamic -I./headers/ -lm
 * 
 */

#include <stdio.h>
#include <gtk/gtk.h>
#include <goocanvas.h>

/*Common structs and varaibles*/

struct dia_struct
{
    gdouble diam;
    const gchar *tbp, *thtp, *wt;
};

struct dia_struct set_dia; /* intitializing the structure */

/* Goo canvas items */
GooCanvasItem *root, *path, *path2;

GtkWidget  *canvas;

/*
 * Function:  ofdra
 * --------------------
 * This is the main function to draw the diagram on screen
 *  
 *  returns: none
 */
void ofdra (double diam)
{ 
    double dfactor = diam*50;

    path = NULL;
    path2 = NULL;

    double x = (465-dfactor)/2;
    double y = 465-x;

    char buf[100];
    char buf2[100];
    sprintf(buf, "M 0 %f L 1000 %f", x, x);
    sprintf(buf2, "M 0 %f L 1000 %f", y, y);

    path = goo_canvas_path_new (root, buf, "stroke-color", "red", NULL);
    path2 = goo_canvas_path_new (root, buf2, "stroke-color", "red", NULL);

    /*goo_canvas_item_update (path, TRUE, );*/
    /*goo_canvas_item_update (path2);*/

}

/*
 * Function:  ofruta
 * --------------------
 * This is the main function to run when in a user changed a value.
 *
 *  glade_wdgets: widget-object
 *  pObList: array of objects to go through
 *  
 *  returns: none
 */
void ofruta (GtkWidget *glade_wdgets, gpointer *pObList)
{
    /* common varaibles needed */

    struct dia_struct dia; /* intitializing the structure */

    /* getters */
    dia.diam = gtk_spin_button_get_value (GTK_SPIN_BUTTON(pObList[0])); /* diameter reading */

    set_diamond.diam = diamond.diam;

    gtk_spin_button_set_value(GTK_SPIN_BUTTON(pObList[0]), set_diamond.diam);

    /* Loads all dynamically generated diagram drawing */
    ofdra(set_diamond.diam);
}

//===========================================================================
/*
 * main
 *
 * Program begins here
 */
int main( int argc, char **argv )
{
    GtkBuilder *builder;
    GtkWidget  *window;
    GError     *error = NULL;
    GtkButton *button;
    GtkLabel *label;

    cairo_surface_t *surface;

    /* Init GTK+ */
    gtk_init( &argc, &argv );

    /* Create new GtkBuilder object */
    builder = gtk_builder_new();
    /* Load UI from file. If error occurs, report it and quit application.
     * Replace "tut.glade" with your saved project. */
    if( ! gtk_builder_add_from_file( builder, "dia_glade.glade", &error ) )
    {
        g_warning( "%s", error->message );
        g_free( error );
        return( 1 );
    }

    /* Get main window pointer from UI */
    window = GTK_WIDGET( gtk_builder_get_object( builder, "window1" ) );

    gpointer spinners[] = { gtk_builder_get_object( builder, "diam" )};

    /* Connect signals */
    gtk_builder_connect_signals( builder, spinners );

    g_signal_connect(G_OBJECT(window), "delete-event", (GCallback)gtk_main_quit, NULL);
    g_signal_connect(G_OBJECT("measure"), "clicked", (GCallback)ofruta, spinners);

    canvas = goo_canvas_new ();

    gtk_widget_set_size_request (canvas, 600, 465);
    goo_canvas_set_bounds (GOO_CANVAS (canvas), 0, 0, 1000, 1000);
    gtk_widget_show (canvas);

    gtk_container_add (GTK_CONTAINER (gtk_builder_get_object( builder, "draw_area" )), canvas);

    root = goo_canvas_get_root_item (GOO_CANVAS (canvas));

    /* Destroy builder, since we don't need it anymore */
    g_object_unref( G_OBJECT( builder ) );

    /* Show window. All other widgets are automatically shown by GtkBuilder */
    gtk_widget_show( window );

    /* Start main loop */
    gtk_main();

    return( 0 );
}

При нажатии на кнопку под названием «измерить» обработчик под названием «ofruta» в «ofruta» вызывает функцию рисования.

Это правильный метод?


person inckka    schedule 29.01.2016    source источник
comment
Нарисуйте полноразмерный заполненный прямоугольник с «чистым» цветом.   -  person keltar    schedule 29.01.2016
comment
@keltar На самом деле я собираюсь использовать видеопоток в качестве фона. Это все еще возможно?   -  person inckka    schedule 29.01.2016
comment
Всё равно, если производительность будет приемлемой. Просто нарисуйте изображение, оно должно перезаписать предыдущее содержимое.   -  person keltar    schedule 29.01.2016
comment
@keltar Вы видите мой код выше (только что обновленный). Я вызываю функцию для рисования путей. Мне нужно как-то обновить/обновить кавы/предметы.   -  person inckka    schedule 29.01.2016
comment
Ну, вы создаете пути каждый раз, поэтому в результате у вас появляется все больше и больше путей для каждого вызова. Вы должны либо удалить старые пути с goo_canvas_item_remove перед созданием нового пути (но, конечно, проверить на NULL), либо использовать отдельную модель пути и изменить ее (может быть сложнее, но логически лучше). Попробуйте сначала удалить старые пути, это довольно просто.   -  person keltar    schedule 29.01.2016
comment
@keltar Эй, это сработало. Я бился 6 часов, чтобы найти это. Большой. Я очень хочу реализовать модель (что было бы правильно). Можете сделать пример?   -  person inckka    schedule 29.01.2016
comment
Я посмотрю на это позже сегодня, дам вам знать.   -  person keltar    schedule 29.01.2016


Ответы (1)


Вот пример, основанный на https://developer.gnome.org/goocanvas/unstable/goocanvas-model-view-canvas.html :

#include <stdlib.h>
#include <goocanvas.h>

static gboolean on_rect_button_press (GooCanvasItem  *view,
        GooCanvasItem  *target,
        GdkEventButton *event,
        gpointer        data);

static gboolean on_delete_event      (GtkWidget      *window,
        GdkEvent       *event,
        gpointer        unused_data);


GooCanvasItemModel *root, *rect_model, *text_model, *path;

int main (int argc, char *argv[]) {
    GtkWidget *window, *scrolled_win, *canvas;
    GooCanvasItem *rect_item;

    gtk_set_locale ();
    gtk_init (&argc, &argv);

    window = gtk_window_new (GTK_WINDOW_TOPLEVEL);
    gtk_window_set_default_size (GTK_WINDOW (window), 640, 600);
    gtk_widget_show (window);
    g_signal_connect (window, "delete_event", (GtkSignalFunc) on_delete_event,
            NULL);

    scrolled_win = gtk_scrolled_window_new (NULL, NULL);
    gtk_scrolled_window_set_shadow_type (GTK_SCROLLED_WINDOW (scrolled_win),
            GTK_SHADOW_IN);
    gtk_widget_show (scrolled_win);
    gtk_container_add (GTK_CONTAINER (window), scrolled_win);

    canvas = goo_canvas_new ();
    gtk_widget_set_size_request (canvas, 600, 450);
    goo_canvas_set_bounds (GOO_CANVAS (canvas), 0, 0, 1000, 1000);
    gtk_widget_show (canvas);
    gtk_container_add (GTK_CONTAINER (scrolled_win), canvas);

    root = goo_canvas_group_model_new (NULL, NULL);

    rect_model = goo_canvas_rect_model_new (root, 100, 100, 400, 400,
            "line-width", 10.0,
            "radius-x", 20.0,
            "radius-y", 10.0,
            "stroke-color", "yellow",
            "fill-color", "red",
            NULL);

    text_model = goo_canvas_text_model_new (root, "Hello World", 300, 300, -1,
            GTK_ANCHOR_CENTER,
            "font", "Sans 24",
            NULL);
    goo_canvas_item_model_rotate (text_model, 45, 300, 300);

    goo_canvas_set_root_item_model (GOO_CANVAS (canvas), root);

    GooCanvasLineDash *dash = goo_canvas_line_dash_new (2, 5.0, 5.0);
    const char *buf = "M 0 128 L 1000 256";
    path = goo_canvas_path_model_new (root, buf,
            "stroke-color", "red",
            "line-dash", dash,
            NULL);

    rect_item = goo_canvas_get_item (GOO_CANVAS (canvas), rect_model);
    g_signal_connect (rect_item, "button_press_event",
            (GtkSignalFunc) on_rect_button_press, NULL);

    goo_canvas_line_dash_unref(dash);

    gtk_main ();

    return 0;
}


static gboolean on_rect_button_press (GooCanvasItem  *item,
        GooCanvasItem  *target,
        GdkEventButton *event,
        gpointer        data) {
    g_print ("rect item received button press event\n");

    static float a = 128, b = 256;
    a += 16, b += 16;

    char buf[64];
    snprintf(buf, sizeof(buf), "M 0 %f L 1000 %f", a, b);
    g_object_set(G_OBJECT(path), "data", buf, NULL);

    return TRUE;
}


static gboolean on_delete_event (GtkWidget *window,
        GdkEvent  *event,
        gpointer   unused_data) {
    exit (0);
}

Изменяя свойство data пути на g_object_set, он перемещается, когда происходит щелчок по прямоугольнику. Имена свойств должны быть взяты из документации, например. https://developer.gnome.org/goocanvas/unstable/GooCanvasPathModel.html

person keltar    schedule 29.01.2016
comment
Приведенный выше код модели работал. Спасибо. Однако как сделать пунктирную линию (путь) с этой моделью. Нет доступных документов. - person inckka; 11.02.2016
comment
Это должен быть отдельный вопрос, но в любом случае - это делается установкой свойства line-dash. git.gnome.org/browse/goocanvas/tree/demo/ В demo-events.c есть пример для rect, но он такой же. Не забудьте отменить ссылку с помощью goo_canvas_line_dash_unref. - person keltar; 11.02.2016
comment
Разве это не путь для GooCanvasItem (простой)? Мой текущий подход заключается в использовании GooCanvasItemModel. Если я создаю пунктирную линию с помощью простого метода, я не могу включить ее в родительский «корень» GooCanvasItemModel. И выдает предупреждение о компиляции: paste.ubuntu.com/15021932 - person inckka; 12.02.2016
comment
Модель имеет такое же свойство. Смотрите обновленный код в ответе. - person keltar; 12.02.2016
comment
Это идеально. оно работает. Большое спасибо. У меня есть еще одна проблема с goocanvas stackoverflow.com/questions/35355077/ Идеи приветствуются. - person inckka; 12.02.2016
comment
Пожалуйста, дайте мне знать, как я могу сделать фон goocanvas прозрачным? - person inckka; 12.02.2016